You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@servicecomb.apache.org by li...@apache.org on 2018/12/03 02:56:27 UTC
[servicecomb-service-center] 04/04: SCB-1049 Add alarms APIs
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 <su...@qq.com>
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{}) {