This is an automated email from the ASF dual-hosted git repository.

littlecui pushed a commit to branch alarm
in repository https://gitbox.apache.org/repos/asf/servicecomb-service-center.git

commit aed4a12c6b85203c2dc3874826da06f2dc5e9ed8
Author: little-cui <[email protected]>
AuthorDate: Fri Nov 30 13:28:18 2018 +0800

    SCB-1049 Add alarms APIs
---
 pkg/notify/subscriber.go                           |  2 +-
 pkg/util/{map.go => json.go}                       |  4 +
 pkg/util/{map_test.go => json_test.go}             |  2 +-
 server/admin/controller_v4.go                      | 29 ++++++-
 server/admin/model/{cluster.go => types.go}        | 16 ++++
 server/admin/service.go                            | 66 +++++++++++++---
 server/alarm/alarm.go                              | 51 +++----------
 server/alarm/{alarm.go => center.go}               | 89 ++++++++++------------
 server/{admin/model/cluster.go => alarm/common.go} | 23 +++---
 server/core/config.go                              |  2 +-
 server/core/swagger/v4.yaml                        | 75 +++++++++++++++++-
 server/notify/{common.go => center.go}             |  8 --
 server/notify/common.go                            | 16 +---
 server/rest/controller/rest_util.go                |  5 ++
 14 files changed, 246 insertions(+), 142 deletions(-)

diff --git a/pkg/notify/subscriber.go b/pkg/notify/subscriber.go
index 7544919..23d848c 100644
--- a/pkg/notify/subscriber.go
+++ b/pkg/notify/subscriber.go
@@ -35,7 +35,7 @@ type Subscriber interface {
        Close()
        OnAccept()
        // The event bus will callback this function, so it must be non-blocked.
-       OnMessage(job Event)
+       OnMessage(Event)
 }
 
 type baseSubscriber struct {
diff --git a/pkg/util/map.go b/pkg/util/json.go
similarity index 97%
rename from pkg/util/map.go
rename to pkg/util/json.go
index f5d8597..7f7dbb1 100644
--- a/pkg/util/map.go
+++ b/pkg/util/json.go
@@ -74,3 +74,7 @@ func toString(v interface{}) string {
                return fmt.Sprintf("%#v", v)
        }
 }
+
+func NewJSONObject() JSONObject {
+       return make(JSONObject)
+}
diff --git a/pkg/util/map_test.go b/pkg/util/json_test.go
similarity index 99%
rename from pkg/util/map_test.go
rename to pkg/util/json_test.go
index 2e4affe..70f6461 100644
--- a/pkg/util/map_test.go
+++ b/pkg/util/json_test.go
@@ -23,7 +23,7 @@ import (
 
 func TestNewServerInformation(t *testing.T) {
        var c JSONObject
-       c = make(JSONObject)
+       c = NewJSONObject()
        if !c.Bool("a", true) {
                t.Fatalf("TestNewServerInformation failed")
        }
diff --git a/server/admin/controller_v4.go b/server/admin/controller_v4.go
index 55d23e9..af620f4 100644
--- a/server/admin/controller_v4.go
+++ b/server/admin/controller_v4.go
@@ -22,6 +22,7 @@ import (
        "github.com/apache/servicecomb-service-center/pkg/rest"
        "github.com/apache/servicecomb-service-center/server/admin/model"
        "github.com/apache/servicecomb-service-center/server/rest/controller"
+       "strings"
 )
 
 // AdminService 治理相关接口服务
@@ -31,13 +32,22 @@ type AdminServiceControllerV4 struct {
 // URLPatterns 路由
 func (ctrl *AdminServiceControllerV4) URLPatterns() []rest.Route {
        return []rest.Route{
+               {rest.HTTP_METHOD_GET, "/v4/:project/admin/alarms", 
ctrl.AlarmList},
+               {rest.HTTP_METHOD_DELETE, "/v4/:project/admin/alarms", 
ctrl.ClearAlarm},
                {rest.HTTP_METHOD_GET, "/v4/:project/admin/dump", ctrl.Dump},
                {rest.HTTP_METHOD_GET, "/v4/:project/admin/clusters", 
ctrl.Clusters},
        }
 }
 
 func (ctrl *AdminServiceControllerV4) Dump(w http.ResponseWriter, r 
*http.Request) {
-       request := &model.DumpRequest{}
+       query := r.URL.Query()
+       var options []string
+       if s := strings.TrimSpace(query.Get("options")); len(s) > 0 {
+               options = strings.Split(s, ",")
+       }
+       request := &model.DumpRequest{
+               Options: options,
+       }
        ctx := r.Context()
        resp, _ := AdminServiceAPI.Dump(ctx, request)
 
@@ -55,3 +65,20 @@ func (ctrl *AdminServiceControllerV4) Clusters(w 
http.ResponseWriter, r *http.Re
        resp.Response = nil
        controller.WriteResponse(w, respInternal, resp)
 }
+
+func (ctrl *AdminServiceControllerV4) AlarmList(w http.ResponseWriter, r 
*http.Request) {
+       request := &model.AlarmListRequest{}
+       ctx := r.Context()
+       resp, _ := AdminServiceAPI.AlarmList(ctx, request)
+
+       respInternal := resp.Response
+       resp.Response = nil
+       controller.WriteResponse(w, respInternal, resp)
+}
+
+func (ctrl *AdminServiceControllerV4) ClearAlarm(w http.ResponseWriter, r 
*http.Request) {
+       request := &model.ClearAlarmRequest{}
+       ctx := r.Context()
+       resp, _ := AdminServiceAPI.ClearAlarm(ctx, request)
+       controller.WriteResponse(w, resp.Response, nil)
+}
diff --git a/server/admin/model/cluster.go b/server/admin/model/types.go
similarity index 75%
copy from server/admin/model/cluster.go
copy to server/admin/model/types.go
index 6cabae9..5a803ad 100644
--- a/server/admin/model/cluster.go
+++ b/server/admin/model/types.go
@@ -16,10 +16,19 @@
 package model
 
 import (
+       "github.com/apache/servicecomb-service-center/server/alarm"
        pb "github.com/apache/servicecomb-service-center/server/core/proto"
        
"github.com/apache/servicecomb-service-center/server/plugin/pkg/registry"
 )
 
+type AlarmListRequest struct {
+}
+
+type AlarmListResponse struct {
+       Response *pb.Response        `json:"response,omitempty"`
+       Alarms   []*alarm.AlarmEvent `json:"alarms,omitempty"`
+}
+
 type ClustersRequest struct {
 }
 
@@ -27,3 +36,10 @@ type ClustersResponse struct {
        Response *pb.Response      `json:"response,omitempty"`
        Clusters registry.Clusters `json:"clusters,omitempty"`
 }
+
+type ClearAlarmRequest struct {
+}
+
+type ClearAlarmResponse struct {
+       Response *pb.Response `json:"response,omitempty"`
+}
diff --git a/server/admin/service.go b/server/admin/service.go
index f6c9e7e..61d69df 100644
--- a/server/admin/service.go
+++ b/server/admin/service.go
@@ -18,8 +18,10 @@ package admin
 
 import (
        "github.com/apache/servicecomb-service-center/pkg/gopool"
+       "github.com/apache/servicecomb-service-center/pkg/log"
        "github.com/apache/servicecomb-service-center/pkg/util"
        "github.com/apache/servicecomb-service-center/server/admin/model"
+       "github.com/apache/servicecomb-service-center/server/alarm"
        "github.com/apache/servicecomb-service-center/server/core"
        "github.com/apache/servicecomb-service-center/server/core/backend"
        pb "github.com/apache/servicecomb-service-center/server/core/proto"
@@ -59,9 +61,7 @@ type AdminService struct {
 }
 
 func (service *AdminService) Dump(ctx context.Context, in *model.DumpRequest) 
(*model.DumpResponse, error) {
-
        domainProject := util.ParseDomainProject(ctx)
-       var cache model.Cache
 
        if !core.IsDefaultDomainProject(domainProject) {
                return &model.DumpResponse{
@@ -69,18 +69,50 @@ func (service *AdminService) Dump(ctx context.Context, in 
*model.DumpRequest) (*
                }, nil
        }
 
-       service.dumpAll(ctx, &cache)
+       resp := &model.DumpResponse{
+               Response: pb.CreateResponse(pb.Response_SUCCESS, "Admin dump 
successfully"),
+       }
 
-       return &model.DumpResponse{
-               Response:     pb.CreateResponse(pb.Response_SUCCESS, "Admin 
dump successfully"),
-               Info:         version.Ver(),
-               AppConfig:    configs,
-               Environments: environments,
-               Cache:        &cache,
-       }, nil
+       if len(in.Options) == 0 {
+               service.dump(ctx, "cache", resp)
+               return resp, nil
+       }
+
+       options := make(map[string]struct{}, len(in.Options))
+       for _, option := range in.Options {
+               if option == "all" {
+                       service.dump(ctx, "all", resp)
+                       return resp, nil
+               }
+               options[option] = struct{}{}
+       }
+       for option := range options {
+               service.dump(ctx, option, resp)
+       }
+       return resp, nil
 }
 
-func (service *AdminService) dumpAll(ctx context.Context, cache *model.Cache) {
+func (service *AdminService) dump(ctx context.Context, option string, resp 
*model.DumpResponse) {
+       switch option {
+       case "info":
+               resp.Info = version.Ver()
+       case "config":
+               resp.AppConfig = configs
+       case "env":
+               resp.Environments = environments
+       case "cache":
+               var cache model.Cache
+               service.dumpAllCache(ctx, &cache)
+               resp.Cache = &cache
+       case "all":
+               service.dump(ctx, "info", resp)
+               service.dump(ctx, "config", resp)
+               service.dump(ctx, "env", resp)
+               service.dump(ctx, "cache", resp)
+       }
+}
+
+func (service *AdminService) dumpAllCache(ctx context.Context, cache 
*model.Cache) {
        gopool.New(ctx, gopool.Configure().Workers(2)).
                Do(func(_ context.Context) { 
setValue(backend.Store().Service(), &cache.Microservices) }).
                Do(func(_ context.Context) { 
setValue(backend.Store().ServiceIndex(), &cache.Indexes) }).
@@ -111,3 +143,15 @@ func (service *AdminService) Clusters(ctx context.Context, 
in *model.ClustersReq
                Clusters: registry.Configuration().Clusters,
        }, nil
 }
+
+func (service *AdminService) AlarmList(ctx context.Context, in 
*model.AlarmListRequest) (*model.AlarmListResponse, error) {
+       return &model.AlarmListResponse{
+               Alarms: alarm.AlarmCenter().AlarmList(),
+       }, nil
+}
+
+func (service *AdminService) ClearAlarm(ctx context.Context, in 
*model.ClearAlarmRequest) (*model.ClearAlarmResponse, error) {
+       alarm.AlarmCenter().Clear()
+       log.Infof("service center alarms are cleared")
+       return &model.ClearAlarmResponse{}, nil
+}
diff --git a/server/alarm/alarm.go b/server/alarm/alarm.go
index e3639e7..c96d917 100644
--- a/server/alarm/alarm.go
+++ b/server/alarm/alarm.go
@@ -17,69 +17,38 @@ package alarm
 
 import (
        nf "github.com/apache/servicecomb-service-center/pkg/notify"
-       "github.com/apache/servicecomb-service-center/server/notify"
-       "sync/atomic"
+       "github.com/apache/servicecomb-service-center/pkg/util"
 )
 
-type ID int32
-
-const (
-       CodeBackendConnectionRefuse ID = iota
-       CodeServerOverload
-       CodeServiceQuotaLimit
-       CodeInstanceQuotaLimit
-       CodeDiagnoseFailure
-       CodeInternalError
-       typeEnd
-)
-
-const Subject = "__ALARM_CENTER__"
-
-var latestId = int32(typeEnd)
+type ID string
 
 type AlarmEvent struct {
-       nf.Event
-       Id     ID
-       fields map[string]interface{}
+       nf.Event `json:"-"`
+       Id       ID              `json:"id"`
+       Fields   util.JSONObject `json:"fields,omitempty"`
 }
 
 func (ae *AlarmEvent) FieldBool(key string) bool {
-       v, _ := ae.fields[key].(bool)
+       v, _ := ae.Fields[key].(bool)
        return v
 }
 
 func (ae *AlarmEvent) FieldString(key string) string {
-       v, _ := ae.fields[key].(string)
+       v, _ := ae.Fields[key].(string)
        return v
 }
 
 func (ae *AlarmEvent) FieldInt64(key string) int64 {
-       v, _ := ae.fields[key].(int64)
+       v, _ := ae.Fields[key].(int64)
        return v
 }
 
 func (ae *AlarmEvent) FieldInt(key string) int {
-       v, _ := ae.fields[key].(int)
+       v, _ := ae.Fields[key].(int)
        return v
 }
 
 func (ae *AlarmEvent) FieldFloat64(key string) float64 {
-       v, _ := ae.fields[key].(float64)
+       v, _ := ae.Fields[key].(float64)
        return v
 }
-
-func RegisterAlarmSource() ID {
-       return ID(atomic.AddInt32(&latestId, 1))
-}
-
-func Alarm(id ID, fields ...Field) error {
-       ae := &AlarmEvent{
-               Event:  nf.NewEvent(nf.NOTIFTY, Subject, ""),
-               Id:     id,
-               fields: make(map[string]interface{}, len(fields)),
-       }
-       for _, f := range fields {
-               ae.fields[f.Key] = f.Value
-       }
-       return notify.NotifyCenter().Publish(ae)
-}
diff --git a/server/alarm/alarm.go b/server/alarm/center.go
similarity index 52%
copy from server/alarm/alarm.go
copy to server/alarm/center.go
index e3639e7..d28c2c5 100644
--- a/server/alarm/alarm.go
+++ b/server/alarm/center.go
@@ -17,69 +17,62 @@ package alarm
 
 import (
        nf "github.com/apache/servicecomb-service-center/pkg/notify"
+       "github.com/apache/servicecomb-service-center/pkg/util"
        "github.com/apache/servicecomb-service-center/server/notify"
-       "sync/atomic"
+       "sync"
 )
 
-type ID int32
-
-const (
-       CodeBackendConnectionRefuse ID = iota
-       CodeServerOverload
-       CodeServiceQuotaLimit
-       CodeInstanceQuotaLimit
-       CodeDiagnoseFailure
-       CodeInternalError
-       typeEnd
+var (
+       center *Center
+       once   sync.Once
 )
 
-const Subject = "__ALARM_CENTER__"
-
-var latestId = int32(typeEnd)
-
-type AlarmEvent struct {
-       nf.Event
-       Id     ID
-       fields map[string]interface{}
-}
-
-func (ae *AlarmEvent) FieldBool(key string) bool {
-       v, _ := ae.fields[key].(bool)
-       return v
+type Center struct {
+       nf.Subscriber
+       alarms util.ConcurrentMap
 }
 
-func (ae *AlarmEvent) FieldString(key string) string {
-       v, _ := ae.fields[key].(string)
-       return v
+func (ac *Center) Alarm(id ID, fields ...Field) error {
+       ae := &AlarmEvent{
+               Event:  nf.NewEvent(nf.NOTIFTY, Subject, ""),
+               Id:     id,
+               Fields: util.NewJSONObject(),
+       }
+       for _, f := range fields {
+               ae.Fields[f.Key] = f.Value
+       }
+       return notify.NotifyCenter().Publish(ae)
 }
 
-func (ae *AlarmEvent) FieldInt64(key string) int64 {
-       v, _ := ae.fields[key].(int64)
-       return v
+func (ac *Center) AlarmList() (ls []*AlarmEvent) {
+       ac.alarms.ForEach(func(item util.MapItem) (next bool) {
+               ls = append(ls, item.Value.(*AlarmEvent))
+               return true
+       })
+       return
 }
 
-func (ae *AlarmEvent) FieldInt(key string) int {
-       v, _ := ae.fields[key].(int)
-       return v
+func (ac *Center) Clear() {
+       ac.alarms = util.ConcurrentMap{}
+       return
 }
 
-func (ae *AlarmEvent) FieldFloat64(key string) float64 {
-       v, _ := ae.fields[key].(float64)
-       return v
+func (ac *Center) OnMessage(evt nf.Event) {
+       alarm := evt.(*AlarmEvent)
+       ac.alarms.Put(alarm.Id, alarm)
 }
 
-func RegisterAlarmSource() ID {
-       return ID(atomic.AddInt32(&latestId, 1))
+func NewAlarmCenter() *Center {
+       c := &Center{
+               Subscriber: nf.NewSubscriber(nf.NOTIFTY, Subject, Group),
+       }
+       notify.NotifyCenter().AddSubscriber(c)
+       return c
 }
 
-func Alarm(id ID, fields ...Field) error {
-       ae := &AlarmEvent{
-               Event:  nf.NewEvent(nf.NOTIFTY, Subject, ""),
-               Id:     id,
-               fields: make(map[string]interface{}, len(fields)),
-       }
-       for _, f := range fields {
-               ae.fields[f.Key] = f.Value
-       }
-       return notify.NotifyCenter().Publish(ae)
+func AlarmCenter() *Center {
+       once.Do(func() {
+               center = NewAlarmCenter()
+       })
+       return center
 }
diff --git a/server/admin/model/cluster.go b/server/alarm/common.go
similarity index 67%
rename from server/admin/model/cluster.go
rename to server/alarm/common.go
index 6cabae9..ab95b98 100644
--- a/server/admin/model/cluster.go
+++ b/server/alarm/common.go
@@ -13,17 +13,18 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package model
+package alarm
 
-import (
-       pb "github.com/apache/servicecomb-service-center/server/core/proto"
-       
"github.com/apache/servicecomb-service-center/server/plugin/pkg/registry"
+const (
+       BackendConnectionRefuse ID = "BackendConnectionRefuse"
+       ServerOverload          ID = "ServerOverload"
+       ServiceQuotaLimit       ID = "ServiceQuotaLimit"
+       InstanceQuotaLimit      ID = "InstanceQuotaLimit"
+       DiagnoseFailure         ID = "DiagnoseFailure"
+       InternalError           ID = "InternalError"
 )
 
-type ClustersRequest struct {
-}
-
-type ClustersResponse struct {
-       Response *pb.Response      `json:"response,omitempty"`
-       Clusters registry.Clusters `json:"clusters,omitempty"`
-}
+const (
+       Subject = "__ALARM_SUBJECT__"
+       Group   = "__ALARM_GROUP__"
+)
diff --git a/server/core/config.go b/server/core/config.go
index c95224d..ab2f891 100644
--- a/server/core/config.go
+++ b/server/core/config.go
@@ -87,7 +87,7 @@ func newInfo() pb.ServerInformation {
                        LogSys:         beego.AppConfig.DefaultBool("log_sys", 
false),
 
                        PluginsDir: 
beego.AppConfig.DefaultString("plugins_dir", "./plugins"),
-                       Plugins:    make(util.JSONObject),
+                       Plugins:    util.NewJSONObject(),
 
                        EnablePProf:  
beego.AppConfig.DefaultInt("enable_pprof", 0) != 0,
                        EnableCache:  
beego.AppConfig.DefaultInt("enable_cache", 1) != 0,
diff --git a/server/core/swagger/v4.yaml b/server/core/swagger/v4.yaml
index 7d3aaef..06f071a 100644
--- a/server/core/swagger/v4.yaml
+++ b/server/core/swagger/v4.yaml
@@ -1533,7 +1533,7 @@ paths:
     get:
       description: |
         查询单个服务的所有信息。
-      operationId: GetServiceDetail
+      operationId: getServiceDetail
       parameters:
         - name: x-domain-name
           in: header
@@ -1568,7 +1568,7 @@ paths:
     get:
       description: |
         查询单个服务的所有信息。
-      operationId: GetServicesInfo
+      operationId: getServicesInfo
       parameters:
         - name: x-domain-name
           in: header
@@ -1603,7 +1603,7 @@ paths:
     get:
       description: |
         查询服务间的关系。
-      operationId: GetGraph
+      operationId: getGraph
       parameters:
         - name: x-domain-name
           in: header
@@ -1635,7 +1635,7 @@ paths:
     get:
       description: |
         查询所有appId。
-      operationId: GetApplications
+      operationId: getApplications
       parameters:
         - name: x-domain-name
           in: header
@@ -1685,6 +1685,11 @@ paths:
           description: default项目
           required: true
           type: string
+        - name: options
+          in: query
+          default: cache
+          description: 枚举值有:info,config,env,cache和all
+          type: string
       tags:
         - admin
       responses:
@@ -1721,6 +1726,53 @@ paths:
           description: clusters information
           schema:
             $ref: '#/definitions/ClustersResponse'
+  /v4/{project}/admin/alarms:
+    get:
+      description: |
+        Return the alarms list of Service Center
+      operationId: alarmList
+      parameters:
+        - name: x-domain-name
+          in: header
+          type: string
+          default: default
+          description: default租户
+          required: true
+        - name: project
+          in: path
+          default: default
+          description: default项目
+          required: true
+          type: string
+      tags:
+        - admin
+      responses:
+        200:
+          description: alarms information
+          schema:
+            $ref: '#/definitions/AlarmList'
+    delete:
+      description: |
+        Clear the alarms list of Service Center
+      operationId: clearAlarm
+      parameters:
+        - name: x-domain-name
+          in: header
+          type: string
+          default: default
+          description: default租户
+          required: true
+        - name: project
+          in: path
+          default: default
+          description: default项目
+          required: true
+          type: string
+      tags:
+        - admin
+      responses:
+        200:
+          description: cleared
 definitions:
   Version:
     type: object
@@ -2552,3 +2604,18 @@ definitions:
         type: string
       detail:
         type: string
+  AlarmList:
+    type: object
+    description: alarms information
+    additionalProperties:
+      type: array
+      items:
+        $ref: '#/definitions/Alarm'
+  Alarm:
+    type: object
+    description: alarm information
+    properties:
+      id:
+        type: string
+      fields:
+        $ref: '#/definitions/Properties'
diff --git a/server/notify/common.go b/server/notify/center.go
similarity index 86%
copy from server/notify/common.go
copy to server/notify/center.go
index b130cb1..db95ec3 100644
--- a/server/notify/common.go
+++ b/server/notify/center.go
@@ -17,14 +17,6 @@ package notify
 
 import (
        "github.com/apache/servicecomb-service-center/pkg/notify"
-       "time"
-)
-
-const (
-       AddJobTimeout          = 1 * time.Second
-       SendTimeout            = 5 * time.Second
-       HeartbeatTimeout       = 30 * time.Second
-       InstanceEventQueueSize = 5000
 )
 
 var INSTANCE = notify.RegisterType("INSTANCE", InstanceEventQueueSize)
diff --git a/server/notify/common.go b/server/notify/common.go
index b130cb1..e3c9a67 100644
--- a/server/notify/common.go
+++ b/server/notify/common.go
@@ -15,10 +15,7 @@
 
 package notify
 
-import (
-       "github.com/apache/servicecomb-service-center/pkg/notify"
-       "time"
-)
+import "time"
 
 const (
        AddJobTimeout          = 1 * time.Second
@@ -26,14 +23,3 @@ const (
        HeartbeatTimeout       = 30 * time.Second
        InstanceEventQueueSize = 5000
 )
-
-var INSTANCE = notify.RegisterType("INSTANCE", InstanceEventQueueSize)
-var notifyService *notify.NotifyService
-
-func init() {
-       notifyService = notify.NewNotifyService()
-}
-
-func NotifyCenter() *notify.NotifyService {
-       return notifyService
-}
diff --git a/server/rest/controller/rest_util.go 
b/server/rest/controller/rest_util.go
index ca75b1f..b603e41 100644
--- a/server/rest/controller/rest_util.go
+++ b/server/rest/controller/rest_util.go
@@ -21,6 +21,7 @@ import (
        "fmt"
        "github.com/apache/servicecomb-service-center/pkg/rest"
        "github.com/apache/servicecomb-service-center/pkg/util"
+       "github.com/apache/servicecomb-service-center/server/alarm"
        pb "github.com/apache/servicecomb-service-center/server/core/proto"
        "github.com/apache/servicecomb-service-center/server/error"
        "net/http"
@@ -33,6 +34,10 @@ func WriteError(w http.ResponseWriter, code int32, detail 
string) {
        w.Header().Set(rest.HEADER_CONTENT_TYPE, rest.CONTENT_TYPE_JSON)
        w.WriteHeader(err.StatusCode())
        fmt.Fprintln(w, util.BytesToStringWithNoCopy(err.Marshal()))
+
+       if err.InternalError() {
+               alarm.AlarmCenter().Alarm(alarm.InternalError, 
alarm.FieldString("detail", detail))
+       }
 }
 
 func WriteResponse(w http.ResponseWriter, resp *pb.Response, obj interface{}) {

Reply via email to