You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@servicecomb.apache.org by ti...@apache.org on 2020/03/14 07:29:17 UTC
[servicecomb-kie] branch master updated: refactor polling detail
(#116)
This is an automated email from the ASF dual-hosted git repository.
tianxiaoliang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/servicecomb-kie.git
The following commit(s) were added to refs/heads/master by this push:
new 758438e refactor polling detail (#116)
758438e is described below
commit 758438ee79060094456208a411bbc653c3e3a912
Author: Shawn <xi...@gmail.com>
AuthorDate: Sat Mar 14 15:29:09 2020 +0800
refactor polling detail (#116)
---
examples/dev/conf/chassis.yaml | 2 +-
pkg/common/common.go | 1 +
scripts/start.sh | 2 +-
server/handler/track_handler.go | 118 ++++++++++++++++++++++
server/resource/v1/common.go | 18 ++--
server/resource/v1/kv_resource.go | 92 +++++------------
server/service/mongo/record/polling_detail_dao.go | 2 +
7 files changed, 158 insertions(+), 77 deletions(-)
diff --git a/examples/dev/conf/chassis.yaml b/examples/dev/conf/chassis.yaml
index 2b22ce9..d5c8888 100755
--- a/examples/dev/conf/chassis.yaml
+++ b/examples/dev/conf/chassis.yaml
@@ -10,7 +10,7 @@ cse:
handler:
chain:
Provider:
- default: auth-handler,ratelimiter-provider
+ default: auth-handler,track-handler,ratelimiter-provider
# ssl:
# Provider.cipherPlugin: default
# Provider.verifyPeer: false
diff --git a/pkg/common/common.go b/pkg/common/common.go
index 4cdf3fc..191d627 100644
--- a/pkg/common/common.go
+++ b/pkg/common/common.go
@@ -27,6 +27,7 @@ const (
QueryParamRev = "revision"
QueryParamMatch = "match"
QueryParamKeyID = "kv_id"
+ QueryParamLabel = "label"
QueryParamStatus = "status"
QueryParamOffset = "offset"
QueryParamLimit = "limit"
diff --git a/scripts/start.sh b/scripts/start.sh
index 9abf470..3f230e0 100755
--- a/scripts/start.sh
+++ b/scripts/start.sh
@@ -38,7 +38,7 @@ cse:
handler:
chain:
Provider:
- default: auth-handler,ratelimiter-provider
+ default: auth-handler,track-handler,ratelimiter-provider
EOM
cat <<EOM > ${root_dir}/conf/lager.yaml
logger_level: ${LOG_LEVEL}
diff --git a/server/handler/track_handler.go b/server/handler/track_handler.go
new file mode 100644
index 0000000..f85df93
--- /dev/null
+++ b/server/handler/track_handler.go
@@ -0,0 +1,118 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package handler
+
+import (
+ "github.com/apache/servicecomb-kie/pkg/common"
+ "github.com/apache/servicecomb-kie/pkg/iputil"
+ "github.com/apache/servicecomb-kie/pkg/model"
+ "github.com/apache/servicecomb-kie/server/resource/v1"
+ "github.com/apache/servicecomb-kie/server/service/mongo/record"
+ "github.com/emicklei/go-restful"
+ "github.com/go-chassis/go-chassis/core/handler"
+ "github.com/go-chassis/go-chassis/core/invocation"
+ "github.com/go-mesh/openlogging"
+ "net/http"
+ "strings"
+)
+
+//const of noop auth handler
+const (
+ TrackHandlerName = "track-handler"
+)
+
+//TrackHandler tracks polling data
+type TrackHandler struct{}
+
+//Handle set local attribute to http request
+func (h *TrackHandler) Handle(chain *handler.Chain, inv *invocation.Invocation, cb invocation.ResponseCallBack) {
+ req, ok := inv.Args.(*restful.Request)
+ if !ok {
+ chain.Next(inv, cb)
+ return
+ }
+ if req.Request.Method != http.MethodGet {
+ chain.Next(inv, cb)
+ return
+ }
+ if !strings.Contains(req.Request.URL.Path, "kie/kv") {
+ chain.Next(inv, cb)
+ return
+ }
+ sessionID := req.HeaderParameter(v1.HeaderSessionID)
+ if sessionID == "" {
+ chain.Next(inv, cb)
+ return
+ }
+ chain.Next(inv, func(ir *invocation.Response) error {
+ resp, ok := ir.Result.(*restful.Response)
+ if !ok {
+ err := cb(ir)
+ if err != nil {
+ return err
+ }
+ return nil
+ }
+ revStr := req.QueryParameter(common.QueryParamRev)
+ wait := req.QueryParameter(common.QueryParamWait)
+ data := &model.PollingDetail{}
+ data.URLPath = req.Request.Method + " " + req.Request.URL.Path
+ data.SessionID = sessionID
+ data.UserAgent = req.HeaderParameter(v1.HeaderUserAgent)
+ data.Domain = inv.Metadata[v1.AttributeDomainKey].(string)
+ data.IP = iputil.ClientIP(req.Request)
+ data.ResponseBody = inv.Ctx.Value(common.RespBodyContextKey)
+ data.ResponseCode = ir.Status
+ data.ResponseHeader = resp.Header()
+ data.PollingData = map[string]interface{}{
+ "revStr": revStr,
+ "wait": wait,
+ "project": req.HeaderParameter(v1.PathParameterProject),
+ "labels": req.QueryParameter("label"),
+ }
+ _, err := record.CreateOrUpdate(inv.Ctx, data)
+ if err != nil {
+ openlogging.Warn("record polling detail failed" + err.Error())
+ err := cb(ir)
+ if err != nil {
+ return err
+ }
+ return nil
+ }
+ err = cb(ir)
+ if err != nil {
+ return err
+ }
+ return nil
+ })
+
+}
+
+func newTrackHandler() handler.Handler {
+ return &TrackHandler{}
+}
+
+//Name is handler name
+func (h *TrackHandler) Name() string {
+ return TrackHandlerName
+}
+func init() {
+ if err := handler.RegisterHandler(TrackHandlerName, newTrackHandler); err != nil {
+ openlogging.Fatal("register handler failed: " + err.Error())
+ }
+}
diff --git a/server/resource/v1/common.go b/server/resource/v1/common.go
index 8fda4b8..957308f 100644
--- a/server/resource/v1/common.go
+++ b/server/resource/v1/common.go
@@ -21,6 +21,7 @@ import (
"context"
"encoding/json"
"errors"
+ "github.com/apache/servicecomb-kie/pkg/model"
"net/http"
"strconv"
"strings"
@@ -129,7 +130,7 @@ func writeResponse(ctx *restful.Context, v interface{}) error {
return ctx.WriteJSON(v, goRestful.MIME_JSON) // json is default
}
func getLabels(rctx *restful.Context) (map[string]string, error) {
- labelSlice := rctx.Req.QueryParameters("label")
+ labelSlice := rctx.Req.QueryParameters(common.QueryParamLabel)
if len(labelSlice) == 0 {
return nil, nil
}
@@ -220,27 +221,26 @@ func checkStatus(status string) (string, error) {
return status, nil
}
-func queryAndResponse(rctx *restful.Context,
- domain interface{}, project string, key string, labels map[string]string, offset, limit int64, status string) {
+func queryAndResponse(rctx *restful.Context, doc *model.KVDoc, offset, limit int64) {
m := getMatchPattern(rctx)
opts := []service.FindOption{
- service.WithKey(key),
- service.WithLabels(labels),
+ service.WithKey(doc.Key),
+ service.WithLabels(doc.Labels),
service.WithOffset(offset),
service.WithLimit(limit),
}
if m == common.PatternExact {
opts = append(opts, service.WithExactLabels())
}
- if status != "" {
- opts = append(opts, service.WithStatus(status))
+ if doc.Status != "" {
+ opts = append(opts, service.WithStatus(doc.Status))
}
- rev, err := service.RevisionService.GetRevision(rctx.Ctx, domain.(string))
+ rev, err := service.RevisionService.GetRevision(rctx.Ctx, doc.Domain)
if err != nil {
WriteErrResponse(rctx, http.StatusInternalServerError, err.Error(), common.ContentTypeText)
return
}
- kv, err := service.KVService.List(rctx.Ctx, domain.(string), project, opts...)
+ kv, err := service.KVService.List(rctx.Ctx, doc.Domain, doc.Project, opts...)
if err != nil {
if err == service.ErrKeyNotExists {
rctx.ReadResponseWriter().Header().Set(common.HeaderRevision, strconv.FormatInt(rev, 10))
diff --git a/server/resource/v1/kv_resource.go b/server/resource/v1/kv_resource.go
index aa77096..e4d883e 100644
--- a/server/resource/v1/kv_resource.go
+++ b/server/resource/v1/kv_resource.go
@@ -23,15 +23,12 @@ import (
"net/http"
"github.com/apache/servicecomb-kie/pkg/common"
- "github.com/apache/servicecomb-kie/pkg/iputil"
"github.com/apache/servicecomb-kie/pkg/model"
"github.com/apache/servicecomb-kie/server/pubsub"
"github.com/apache/servicecomb-kie/server/service"
- "github.com/apache/servicecomb-kie/server/service/mongo/record"
goRestful "github.com/emicklei/go-restful"
"github.com/go-chassis/go-chassis/server/restful"
"github.com/go-mesh/openlogging"
- uuid "github.com/satori/go.uuid"
)
//KVResource has API about kv operations
@@ -49,10 +46,6 @@ func (r *KVResource) Put(context *restful.Context) {
return
}
domain := ReadDomain(context)
- if domain == nil {
- WriteErrResponse(context, http.StatusInternalServerError, common.MsgDomainMustNotBeEmpty, common.ContentTypeText)
- return
- }
kv.Key = key
kv.Domain = domain.(string)
kv.Project = project
@@ -101,10 +94,6 @@ func (r *KVResource) GetByKey(rctx *restful.Context) {
return
}
domain := ReadDomain(rctx)
- if domain == nil {
- WriteErrResponse(rctx, http.StatusInternalServerError, common.MsgDomainMustNotBeEmpty, common.ContentTypeText)
- return
- }
offsetStr := rctx.ReadQueryParameter(common.QueryParamOffset)
limitStr := rctx.ReadQueryParameter(common.QueryParamLimit)
offset, limit, err := checkPagination(offsetStr, limitStr)
@@ -112,14 +101,20 @@ func (r *KVResource) GetByKey(rctx *restful.Context) {
WriteErrResponse(rctx, http.StatusBadRequest, err.Error(), common.ContentTypeText)
return
}
- insID := rctx.ReadHeader(HeaderSessionID)
+ sessionID := rctx.ReadHeader(HeaderSessionID)
statusStr := rctx.ReadQueryParameter(common.QueryParamStatus)
status, err := checkStatus(statusStr)
if err != nil {
WriteErrResponse(rctx, http.StatusBadRequest, err.Error(), common.ContentTypeText)
return
}
- returnData(rctx, domain, project, key, labels, offset, limit, status, insID)
+ returnData(rctx, &model.KVDoc{
+ Domain: domain.(string),
+ Project: project,
+ Key: key,
+ Labels: labels,
+ Status: status,
+ }, offset, limit, sessionID)
}
//List response kv list
@@ -127,10 +122,6 @@ func (r *KVResource) List(rctx *restful.Context) {
var err error
project := rctx.ReadPathParameter(PathParameterProject)
domain := ReadDomain(rctx)
- if domain == nil {
- WriteErrResponse(rctx, http.StatusInternalServerError, common.MsgDomainMustNotBeEmpty, common.ContentTypeText)
- return
- }
labels, err := getLabels(rctx)
if err != nil {
WriteErrResponse(rctx, http.StatusBadRequest, err.Error(), common.ContentTypeText)
@@ -150,37 +141,39 @@ func (r *KVResource) List(rctx *restful.Context) {
WriteErrResponse(rctx, http.StatusBadRequest, err.Error(), common.ContentTypeText)
return
}
- returnData(rctx, domain, project, "", labels, offset, limit, status, sessionID)
+ returnData(rctx, &model.KVDoc{
+ Domain: domain.(string),
+ Project: project,
+ Labels: labels,
+ Status: status,
+ }, offset, limit, sessionID)
}
-func returnData(rctx *restful.Context, domain interface{}, project, key string, labels map[string]string, offset, limit int64, status, sessionID string) {
+func returnData(rctx *restful.Context, doc *model.KVDoc, offset, limit int64, sessionID string) {
revStr := rctx.ReadQueryParameter(common.QueryParamRev)
wait := rctx.ReadQueryParameter(common.QueryParamWait)
- if sessionID != "" {
- defer RecordPollingDetail(rctx, revStr, wait, domain.(string), project, labels, offset, limit, sessionID)
- }
if revStr == "" {
if wait == "" {
- queryAndResponse(rctx, domain, project, key, labels, offset, limit, status)
+ queryAndResponse(rctx, doc, offset, limit)
return
}
changed, err := eventHappened(rctx, wait, &pubsub.Topic{
- Labels: labels,
- Project: project,
+ Labels: doc.Labels,
+ Project: doc.Project,
MatchType: getMatchPattern(rctx),
- DomainID: domain.(string),
+ DomainID: doc.Domain,
})
if err != nil {
WriteErrResponse(rctx, http.StatusBadRequest, err.Error(), common.ContentTypeText)
return
}
if changed {
- queryAndResponse(rctx, domain, project, key, labels, offset, limit, status)
+ queryAndResponse(rctx, doc, offset, limit)
return
}
rctx.WriteHeader(http.StatusNotModified)
} else {
- revised, err := isRevised(rctx.Ctx, revStr, domain.(string))
+ revised, err := isRevised(rctx.Ctx, revStr, doc.Domain)
if err != nil {
if err == ErrInvalidRev {
WriteErrResponse(rctx, http.StatusBadRequest, err.Error(), common.ContentTypeText)
@@ -190,21 +183,21 @@ func returnData(rctx *restful.Context, domain interface{}, project, key string,
return
}
if revised {
- queryAndResponse(rctx, domain, project, key, labels, offset, limit, status)
+ queryAndResponse(rctx, doc, offset, limit)
return
} else if wait != "" {
changed, err := eventHappened(rctx, wait, &pubsub.Topic{
- Labels: labels,
- Project: project,
+ Labels: doc.Labels,
+ Project: doc.Project,
MatchType: getMatchPattern(rctx),
- DomainID: domain.(string),
+ DomainID: doc.Domain,
})
if err != nil {
WriteErrResponse(rctx, http.StatusBadRequest, err.Error(), common.ContentTypeText)
return
}
if changed {
- queryAndResponse(rctx, domain, project, key, labels, offset, limit, status)
+ queryAndResponse(rctx, doc, offset, limit)
return
}
rctx.WriteHeader(http.StatusNotModified)
@@ -215,43 +208,10 @@ func returnData(rctx *restful.Context, domain interface{}, project, key string,
}
}
-//RecordPollingDetail to record data after get or list
-func RecordPollingDetail(context *restful.Context, revStr, wait, domain, project string, labels map[string]string, limit, offset int64, sessionID string) {
- data := &model.PollingDetail{}
- data.ID = uuid.NewV4().String()
- data.SessionID = sessionID
- data.Domain = domain
- data.IP = iputil.ClientIP(context.Req.Request)
- dataMap := map[string]interface{}{
- "revStr": revStr,
- "wait": wait,
- "domain": domain,
- "project": project,
- "labels": labels,
- "limit": limit,
- "offset": offset,
- }
- data.PollingData = dataMap
- data.UserAgent = context.Req.HeaderParameter(HeaderUserAgent)
- data.URLPath = context.ReadRequest().Method + " " + context.ReadRequest().URL.Path
- data.ResponseHeader = context.Resp.Header()
- data.ResponseCode = context.Resp.StatusCode()
- data.ResponseBody = context.Ctx.Value(common.RespBodyContextKey)
- _, err := record.CreateOrUpdate(context.Ctx, data)
- if err != nil {
- openlogging.Warn("record polling detail failed" + err.Error())
- return
- }
-}
-
//Delete deletes key by ids
func (r *KVResource) Delete(context *restful.Context) {
project := context.ReadPathParameter(PathParameterProject)
domain := ReadDomain(context)
- if domain == nil {
- WriteErrResponse(context, http.StatusInternalServerError, common.MsgDomainMustNotBeEmpty, common.ContentTypeText)
- return
- }
kvID := context.ReadQueryParameter(common.QueryParamKeyID)
if kvID == "" {
WriteErrResponse(context, http.StatusBadRequest, common.ErrKvIDMustNotEmpty, common.ContentTypeText)
diff --git a/server/service/mongo/record/polling_detail_dao.go b/server/service/mongo/record/polling_detail_dao.go
index 3e76bcb..6cefe5c 100644
--- a/server/service/mongo/record/polling_detail_dao.go
+++ b/server/service/mongo/record/polling_detail_dao.go
@@ -21,6 +21,7 @@ import (
"context"
"github.com/apache/servicecomb-kie/pkg/model"
"github.com/apache/servicecomb-kie/server/service/mongo/session"
+ uuid "github.com/satori/go.uuid"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
)
@@ -32,6 +33,7 @@ func CreateOrUpdate(ctx context.Context, detail *model.PollingDetail) (*model.Po
res := collection.FindOne(ctx, queryFilter)
if res.Err() != nil {
if res.Err() == mongo.ErrNoDocuments {
+ detail.ID = uuid.NewV4().String()
_, err := collection.InsertOne(ctx, detail)
if err != nil {
return nil, err