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-service-center.git


The following commit(s) were added to refs/heads/master by this push:
     new cc07b6f  SCB-2094 Refactor metrics (#743)
cc07b6f is described below

commit cc07b6f4aedc929f1f0af5523d24ee05f203bfae
Author: little-cui <[email protected]>
AuthorDate: Tue Nov 17 08:09:57 2020 +0800

    SCB-2094 Refactor metrics (#743)
    
    * SCB-2094 Refactor metrics
    
    * SCB-2094 Use metrics instead of the quota counter
    
    * SCB-2094 Decouple tracing and etcd client
    
    * SCB-2094 Decouple rbac and etcd client
    
    * SCB-2094 Move etcd cache
    
    * SCB-2094 Tracing can be configure
    
    * SCB-2094 Add server metrics pkg
    
    * SCB-2094 Fix bug
---
 datasource/account.go                              |   7 +
 datasource/etcd/account.go                         |  47 ++++
 .../service => datasource/etcd}/cache/common.go    |   0
 .../etcd}/cache/dependency.go                      |   0
 .../etcd}/cache/filter_consistency.go              |   0
 .../etcd}/cache/filter_consumer.go                 |   0
 .../etcd}/cache/filter_instances.go                |   8 +-
 .../etcd}/cache/filter_permission.go               |   4 +-
 .../etcd}/cache/filter_service.go                  |   0
 .../etcd}/cache/filter_tags.go                     |   0
 .../etcd}/cache/filter_version.go                  |   0
 .../service => datasource/etcd}/cache/instance.go  |   0
 datasource/etcd/client/lease_task.go               |   4 +-
 datasource/etcd/client/metrics.go                  |  25 +-
 datasource/etcd/client/remote/tracing.go           |  16 +-
 datasource/etcd/engine.go                          |   4 +-
 .../etcd/event/dependency_rule_event_handler.go    |   2 +-
 .../event/dependency_rule_event_handler_test.go    |   2 +-
 datasource/etcd/event/domain_event_handler.go      |   2 +-
 datasource/etcd/event/instance_event_handler.go    |   4 +-
 .../etcd/event/schema_summary_event_handler.go     |   2 +-
 datasource/etcd/event/service_event_handler.go     |   4 +-
 datasource/etcd/event/tag_event_handler.go         |   2 +-
 datasource/etcd/ms.go                              |   2 +-
 datasource/etcd/sd/etcd/metrics.go                 |  13 +-
 datasource/etcd/sd/etcd/metrics_test.go            |  12 +-
 datasource/etcd/sd/metrics.go                      |  19 +-
 datasource/metrics.go                              |  76 ------
 datasource/mongo/account.go                        |   4 +
 etc/conf/app.yaml                                  |  10 +-
 {server/metric => pkg/metrics}/calculator.go       |   2 +-
 {server/metric => pkg/metrics}/calculator_test.go  |   2 +-
 pkg/metrics/common.go                              |  71 ++++++
 {server/metric => pkg/metrics}/gatherer.go         |  18 +-
 {server/metric => pkg/metrics}/gatherer_test.go    |   2 +-
 server/metric/common.go => pkg/metrics/manager.go  |   7 +-
 .../common_test.go => pkg/metrics/manager_test.go  |   2 +-
 {server/metric => pkg/metrics}/metrics.go          |   2 +-
 {server/metric => pkg/metrics}/metrics_test.go     |   2 +-
 {server/metric => pkg/metrics}/options.go          |   2 +-
 {server/metric => pkg/metrics}/reporter.go         |   2 +-
 {server/metric => pkg/metrics}/reporter_test.go    |   2 +-
 pkg/prometheus/decorator.go                        |  63 +++++
 server/bootstrap/bootstrap.go                      |   6 +-
 server/connection/grpc/stream.go                   |   7 +-
 server/connection/ws/websocket.go                  |   7 +-
 .../{metric/metric.go => metrics/metrics.go}       |  12 +-
 server/health/metrics.go                           |  62 -----
 server/metric/prometheus/reporter.go               |  72 ------
 server/{metric/options.go => metrics/common.go}    |  15 +-
 .../metrics.go => metrics/connection.go}           |  32 +--
 .../prometheus/metrics.go => metrics/http.go}      |  35 ++-
 server/metrics/http_reporter.go                    |  75 ++++++
 .../metrics/metrics.go => metrics/meta.go}         |  79 +++++--
 server/metrics/sys.go                              |  70 ++++++
 server/plugin/quota/buildin/buildin.go             |   2 -
 server/plugin/quota/buildin/common.go              |  12 +-
 server/plugin/quota/buildin/counter.go             |  57 -----
 server/plugin/quota/buildin/counter_test.go        |  51 ----
 server/plugin/quota/counter/counter.go             |  49 ----
 server/plugin/quota/counter/event.go               | 109 ---------
 server/plugin/quota/counter/event_test.go          | 263 ---------------------
 server/plugin/tracing/pzipkin/buildin.go           |   8 +-
 server/plugin/tracing/pzipkin/buildin_test.go      |  14 +-
 server/plugin/tracing/pzipkin/common.go            |  13 +-
 server/plugin/tracing/pzipkin/common_test.go       |  13 +-
 server/plugin/tracing/tracing.go                   |  10 +-
 server/resource/v4/auth_resource.go                |   3 +-
 .../options.go => rest/prometheus/prometheus.go}   |  13 +-
 server/server.go                                   |   4 +-
 server/service/rbac/dao/account_dao.go             |  53 +----
 server/service/rbac/rbac.go                        |   3 +-
 72 files changed, 596 insertions(+), 999 deletions(-)

diff --git a/datasource/account.go b/datasource/account.go
index 0d473ac..cc70e0b 100644
--- a/datasource/account.go
+++ b/datasource/account.go
@@ -19,11 +19,18 @@ package datasource
 
 import (
        "context"
+       "errors"
        "github.com/apache/servicecomb-service-center/pkg/rbacframe"
 )
 
+var (
+       ErrDuplicated = errors.New("account is duplicated")
+       ErrCanNotEdit = errors.New("account can not be edited")
+)
+
 // AccountManager contains the RBAC CRUD
 type AccountManager interface {
+       CreateAccount(ctx context.Context, a *rbacframe.Account) error
        AccountExist(ctx context.Context, key string) (bool, error)
        GetAccount(ctx context.Context, key string) (*rbacframe.Account, error)
        ListAccount(ctx context.Context, key string) ([]*rbacframe.Account, 
int64, error)
diff --git a/datasource/etcd/account.go b/datasource/etcd/account.go
index 7c20821..677792f 100644
--- a/datasource/etcd/account.go
+++ b/datasource/etcd/account.go
@@ -18,12 +18,59 @@ package etcd
 import (
        "context"
        "encoding/json"
+       "fmt"
+       "github.com/apache/servicecomb-service-center/datasource"
        "github.com/apache/servicecomb-service-center/datasource/etcd/client"
        "github.com/apache/servicecomb-service-center/datasource/etcd/kv"
+       "github.com/apache/servicecomb-service-center/pkg/etcdsync"
        "github.com/apache/servicecomb-service-center/pkg/log"
        "github.com/apache/servicecomb-service-center/pkg/rbacframe"
+       "github.com/apache/servicecomb-service-center/pkg/util"
+       stringutil "github.com/go-chassis/foundation/string"
+       "golang.org/x/crypto/bcrypt"
 )
 
+func (ds *DataSource) CreateAccount(ctx context.Context, a *rbacframe.Account) 
error {
+       lock, err := etcdsync.Lock("/account-creating/"+a.Name, -1, false)
+       if err != nil {
+               return fmt.Errorf("account %s is creating", a.Name)
+       }
+       defer func() {
+               err := lock.Unlock()
+               if err != nil {
+                       log.Errorf(err, "can not release account lock")
+               }
+       }()
+       key := kv.GenerateETCDAccountKey(a.Name)
+       exist, err := datasource.Instance().AccountExist(ctx, a.Name)
+       if err != nil {
+               log.Errorf(err, "can not save account info")
+               return err
+       }
+       if exist {
+               return datasource.ErrDuplicated
+       }
+       hash, err := bcrypt.GenerateFromPassword([]byte(a.Password), 14)
+       if err != nil {
+               log.Errorf(err, "pwd hash failed")
+               return err
+       }
+       a.Password = stringutil.Bytes2str(hash)
+       a.ID = util.GenerateUUID()
+       value, err := json.Marshal(a)
+       if err != nil {
+               log.Errorf(err, "account info is invalid")
+               return err
+       }
+       err = client.PutBytes(ctx, key, value)
+       if err != nil {
+               log.Errorf(err, "can not save account info")
+               return err
+       }
+       log.Info("create new account: " + a.ID)
+       return nil
+}
+
 func (ds *DataSource) AccountExist(ctx context.Context, key string) (bool, 
error) {
        resp, err := client.Instance().Do(ctx, client.GET,
                client.WithStrKey(kv.GenerateETCDAccountKey(key)))
diff --git a/server/service/cache/common.go b/datasource/etcd/cache/common.go
similarity index 100%
rename from server/service/cache/common.go
rename to datasource/etcd/cache/common.go
diff --git a/server/service/cache/dependency.go 
b/datasource/etcd/cache/dependency.go
similarity index 100%
rename from server/service/cache/dependency.go
rename to datasource/etcd/cache/dependency.go
diff --git a/server/service/cache/filter_consistency.go 
b/datasource/etcd/cache/filter_consistency.go
similarity index 100%
rename from server/service/cache/filter_consistency.go
rename to datasource/etcd/cache/filter_consistency.go
diff --git a/server/service/cache/filter_consumer.go 
b/datasource/etcd/cache/filter_consumer.go
similarity index 100%
rename from server/service/cache/filter_consumer.go
rename to datasource/etcd/cache/filter_consumer.go
diff --git a/server/service/cache/filter_instances.go 
b/datasource/etcd/cache/filter_instances.go
similarity index 93%
rename from server/service/cache/filter_instances.go
rename to datasource/etcd/cache/filter_instances.go
index 1277270..543b6eb 100644
--- a/server/service/cache/filter_instances.go
+++ b/datasource/etcd/cache/filter_instances.go
@@ -22,7 +22,7 @@ import (
        "fmt"
        "github.com/apache/servicecomb-service-center/datasource/etcd/client"
        "github.com/apache/servicecomb-service-center/datasource/etcd/kv"
-       serviceUtil 
"github.com/apache/servicecomb-service-center/datasource/etcd/util"
+       "github.com/apache/servicecomb-service-center/datasource/etcd/util"
        "github.com/apache/servicecomb-service-center/pkg/cache"
        "github.com/apache/servicecomb-service-center/pkg/log"
        pb "github.com/apache/servicecomb-service-center/pkg/registry"
@@ -80,7 +80,7 @@ func (f *InstancesFilter) Find(ctx context.Context, parent 
*cache.Node) (
 
 func (f *InstancesFilter) findInstances(ctx context.Context, domainProject, 
serviceID, instanceID string, maxRevs []int64, counts []int64) (instances 
[]*pb.MicroServiceInstance, err error) {
        key := apt.GenerateInstanceKey(domainProject, serviceID, instanceID)
-       opts := append(serviceUtil.FromContext(ctx), client.WithStrKey(key), 
client.WithPrefix())
+       opts := append(util.FromContext(ctx), client.WithStrKey(key), 
client.WithPrefix())
        resp, err := kv.Store().Instance().Search(ctx, opts...)
        if err != nil {
                return nil, err
@@ -110,7 +110,7 @@ func (f *InstancesFilter) FindInstances(ctx 
context.Context, domainProject strin
        if err != nil {
                return
        }
-       return instances, serviceUtil.FormatRevision(maxRevs, counts), nil
+       return instances, util.FormatRevision(maxRevs, counts), nil
 }
 
 func (f *InstancesFilter) BatchFindInstances(ctx context.Context, 
domainProject string, serviceIDs []string) (instances 
[]*pb.MicroServiceInstance, rev string, err error) {
@@ -126,5 +126,5 @@ func (f *InstancesFilter) BatchFindInstances(ctx 
context.Context, domainProject
                instances = append(instances, insts...)
        }
 
-       return instances, serviceUtil.FormatRevision(maxRevs, counts), nil
+       return instances, util.FormatRevision(maxRevs, counts), nil
 }
diff --git a/server/service/cache/filter_permission.go 
b/datasource/etcd/cache/filter_permission.go
similarity index 92%
rename from server/service/cache/filter_permission.go
rename to datasource/etcd/cache/filter_permission.go
index fdfa0af..bc7d5f6 100644
--- a/server/service/cache/filter_permission.go
+++ b/datasource/etcd/cache/filter_permission.go
@@ -20,7 +20,7 @@ package cache
 import (
        "context"
        "fmt"
-       serviceUtil 
"github.com/apache/servicecomb-service-center/datasource/etcd/util"
+       "github.com/apache/servicecomb-service-center/datasource/etcd/util"
        "github.com/apache/servicecomb-service-center/pkg/cache"
        "github.com/apache/servicecomb-service-center/pkg/log"
        pb "github.com/apache/servicecomb-service-center/pkg/registry"
@@ -39,7 +39,7 @@ func (f *AccessibleFilter) Init(ctx context.Context, parent 
*cache.Node) (node *
        consumerID := ctx.Value(CtxFindConsumer).(*pb.MicroService).ServiceId
        pCopy := *parent.Cache.Get(Find).(*VersionRuleCacheItem)
        for _, providerServiceID := range pCopy.ServiceIds {
-               if err := serviceUtil.Accessible(ctx, consumerID, 
providerServiceID); err != nil {
+               if err := util.Accessible(ctx, consumerID, providerServiceID); 
err != nil {
                        provider := 
ctx.Value(CtxFindProvider).(*pb.MicroServiceKey)
                        findFlag := fmt.Sprintf("consumer '%s' find provider 
%s/%s/%s", consumerID,
                                provider.AppId, provider.ServiceName, 
provider.Version)
diff --git a/server/service/cache/filter_service.go 
b/datasource/etcd/cache/filter_service.go
similarity index 100%
rename from server/service/cache/filter_service.go
rename to datasource/etcd/cache/filter_service.go
diff --git a/server/service/cache/filter_tags.go 
b/datasource/etcd/cache/filter_tags.go
similarity index 100%
rename from server/service/cache/filter_tags.go
rename to datasource/etcd/cache/filter_tags.go
diff --git a/server/service/cache/filter_version.go 
b/datasource/etcd/cache/filter_version.go
similarity index 100%
rename from server/service/cache/filter_version.go
rename to datasource/etcd/cache/filter_version.go
diff --git a/server/service/cache/instance.go 
b/datasource/etcd/cache/instance.go
similarity index 100%
rename from server/service/cache/instance.go
rename to datasource/etcd/cache/instance.go
diff --git a/datasource/etcd/client/lease_task.go 
b/datasource/etcd/client/lease_task.go
index e7fe8c5..1fbc340 100644
--- a/datasource/etcd/client/lease_task.go
+++ b/datasource/etcd/client/lease_task.go
@@ -19,11 +19,11 @@ package client
 
 import (
        "context"
-       "github.com/apache/servicecomb-service-center/datasource"
        errorsEx "github.com/apache/servicecomb-service-center/pkg/errors"
        "github.com/apache/servicecomb-service-center/pkg/log"
        simple "github.com/apache/servicecomb-service-center/pkg/time"
        "github.com/apache/servicecomb-service-center/pkg/util"
+       "github.com/apache/servicecomb-service-center/server/metrics"
        "time"
 )
 
@@ -47,7 +47,7 @@ func (lat *LeaseTask) Key() string {
 func (lat *LeaseTask) Do(ctx context.Context) (err error) {
        recv, start := lat.ReceiveTime(), time.Now()
        lat.TTL, err = lat.Client.LeaseRenew(ctx, lat.LeaseID)
-       datasource.ReportHeartbeatCompleted(err, recv)
+       metrics.ReportHeartbeatCompleted(err, recv)
        if err != nil {
                log.Errorf(err, "[%s]task[%s] renew lease[%d] failed(recv: %s, 
send: %s)",
                        time.Since(recv),
diff --git a/datasource/etcd/client/metrics.go 
b/datasource/etcd/client/metrics.go
index 11fa7a2..607a2f4 100644
--- a/datasource/etcd/client/metrics.go
+++ b/datasource/etcd/client/metrics.go
@@ -18,7 +18,8 @@
 package client
 
 import (
-       "github.com/apache/servicecomb-service-center/server/metric"
+       "github.com/apache/servicecomb-service-center/pkg/metrics"
+       helper "github.com/apache/servicecomb-service-center/pkg/prometheus"
        "github.com/prometheus/client_golang/prometheus"
        "time"
 )
@@ -29,43 +30,39 @@ const (
 )
 
 var (
-       backendCounter = prometheus.NewGaugeVec(
+       backendCounter = helper.NewGaugeVec(
                prometheus.GaugeOpts{
-                       Namespace: metric.FamilyName,
+                       Namespace: metrics.FamilyName,
                        Subsystem: "db",
                        Name:      "backend_total",
                        Help:      "Gauge of the backend instance",
                }, []string{"instance"})
 
-       operationCounter = prometheus.NewCounterVec(
+       operationCounter = helper.NewCounterVec(
                prometheus.CounterOpts{
-                       Namespace: metric.FamilyName,
+                       Namespace: metrics.FamilyName,
                        Subsystem: "db",
                        Name:      "backend_operation_total",
                        Help:      "Counter of backend operation",
                }, []string{"instance", "operation", "status"})
 
-       operationLatency = prometheus.NewSummaryVec(
+       operationLatency = helper.NewSummaryVec(
                prometheus.SummaryOpts{
-                       Namespace:  metric.FamilyName,
+                       Namespace:  metrics.FamilyName,
                        Subsystem:  "db",
                        Name:       "backend_operation_durations_microseconds",
                        Help:       "Latency of backend operation",
-                       Objectives: metric.Pxx,
+                       Objectives: metrics.Pxx,
                }, []string{"instance", "operation", "status"})
 )
 
-func init() {
-       prometheus.MustRegister(backendCounter, operationCounter, 
operationLatency)
-}
-
 func ReportBackendInstance(c int) {
-       instance := metric.InstanceName()
+       instance := metrics.InstanceName()
        backendCounter.WithLabelValues(instance).Set(float64(c))
 }
 
 func ReportBackendOperationCompleted(operation string, err error, start 
time.Time) {
-       instance := metric.InstanceName()
+       instance := metrics.InstanceName()
        elapsed := float64(time.Since(start).Nanoseconds()) / 
float64(time.Microsecond)
        status := success
        if err != nil {
diff --git a/datasource/etcd/client/remote/tracing.go 
b/datasource/etcd/client/remote/tracing.go
index 5561576..43fe439 100644
--- a/datasource/etcd/client/remote/tracing.go
+++ b/datasource/etcd/client/remote/tracing.go
@@ -24,10 +24,22 @@ import (
        "net/http"
 )
 
+type EtcdOptions struct {
+       client.PluginOp
+}
+
+func (eo *EtcdOptions) Method() string {
+       return eo.PluginOp.Action.String()
+}
+
+func (eo *EtcdOptions) URL() string {
+       return "/?" + eo.PluginOp.FormatURLParams()
+}
+
 func TracingBegin(ctx context.Context, operationName string, op 
client.PluginOp) tracing.Span {
-       r := &tracing.RegistryRequest{
+       r := &tracing.Operation{
                Ctx:      ctx,
-               Options:  op,
+               Options:  &EtcdOptions{PluginOp: op},
                Endpoint: FirstEndpoint,
        }
        return tracing.ClientBegin(operationName, r)
diff --git a/datasource/etcd/engine.go b/datasource/etcd/engine.go
index 7fa84ec..04acb47 100644
--- a/datasource/etcd/engine.go
+++ b/datasource/etcd/engine.go
@@ -21,9 +21,9 @@ import (
        "context"
        "errors"
        "fmt"
-       "github.com/apache/servicecomb-service-center/datasource"
        "github.com/apache/servicecomb-service-center/pkg/cluster"
        "github.com/apache/servicecomb-service-center/pkg/gopool"
+       "github.com/apache/servicecomb-service-center/server/metrics"
        "strconv"
        "strings"
        "time"
@@ -45,7 +45,7 @@ func (ds *DataSource) SelfRegister(ctx context.Context) error 
{
        // start send heart beat job
        ds.autoSelfHeartBeat()
        // report the metrics
-       datasource.ReportScInstance()
+       metrics.ReportScInstance()
        return err
 }
 
diff --git a/datasource/etcd/event/dependency_rule_event_handler.go 
b/datasource/etcd/event/dependency_rule_event_handler.go
index 40e3d00..90b3b38 100644
--- a/datasource/etcd/event/dependency_rule_event_handler.go
+++ b/datasource/etcd/event/dependency_rule_event_handler.go
@@ -18,12 +18,12 @@
 package event
 
 import (
+       "github.com/apache/servicecomb-service-center/datasource/etcd/cache"
        "github.com/apache/servicecomb-service-center/datasource/etcd/kv"
        "github.com/apache/servicecomb-service-center/datasource/etcd/sd"
        "github.com/apache/servicecomb-service-center/pkg/log"
        pb "github.com/apache/servicecomb-service-center/pkg/registry"
        "github.com/apache/servicecomb-service-center/server/core"
-       "github.com/apache/servicecomb-service-center/server/service/cache"
 )
 
 // DependencyRuleEventHandler reset the find instances cache
diff --git a/datasource/etcd/event/dependency_rule_event_handler_test.go 
b/datasource/etcd/event/dependency_rule_event_handler_test.go
index 0b6757d..dabda54 100644
--- a/datasource/etcd/event/dependency_rule_event_handler_test.go
+++ b/datasource/etcd/event/dependency_rule_event_handler_test.go
@@ -18,10 +18,10 @@ package event
 
 import (
        "context"
+       "github.com/apache/servicecomb-service-center/datasource/etcd/cache"
        "github.com/apache/servicecomb-service-center/datasource/etcd/sd"
        pb "github.com/apache/servicecomb-service-center/pkg/registry"
        "github.com/apache/servicecomb-service-center/server/core"
-       "github.com/apache/servicecomb-service-center/server/service/cache"
        "testing"
 )
 
diff --git a/datasource/etcd/event/domain_event_handler.go 
b/datasource/etcd/event/domain_event_handler.go
index 54960b1..27a5244 100644
--- a/datasource/etcd/event/domain_event_handler.go
+++ b/datasource/etcd/event/domain_event_handler.go
@@ -21,7 +21,7 @@ import (
        "github.com/apache/servicecomb-service-center/datasource/etcd/kv"
        "github.com/apache/servicecomb-service-center/datasource/etcd/sd"
        "github.com/apache/servicecomb-service-center/pkg/registry"
-       "github.com/apache/servicecomb-service-center/server/service/metrics"
+       "github.com/apache/servicecomb-service-center/server/metrics"
 )
 
 // DomainEventHandler report domain & project total number
diff --git a/datasource/etcd/event/instance_event_handler.go 
b/datasource/etcd/event/instance_event_handler.go
index d424dc9..0ab39f2 100644
--- a/datasource/etcd/event/instance_event_handler.go
+++ b/datasource/etcd/event/instance_event_handler.go
@@ -19,6 +19,7 @@ package event
 
 import (
        "context"
+       "github.com/apache/servicecomb-service-center/datasource/etcd/cache"
        "github.com/apache/servicecomb-service-center/datasource/etcd/kv"
        "github.com/apache/servicecomb-service-center/datasource/etcd/sd"
        serviceUtil 
"github.com/apache/servicecomb-service-center/datasource/etcd/util"
@@ -26,9 +27,8 @@ import (
        pb "github.com/apache/servicecomb-service-center/pkg/registry"
        "github.com/apache/servicecomb-service-center/pkg/util"
        apt "github.com/apache/servicecomb-service-center/server/core"
+       "github.com/apache/servicecomb-service-center/server/metrics"
        "github.com/apache/servicecomb-service-center/server/notify"
-       "github.com/apache/servicecomb-service-center/server/service/cache"
-       "github.com/apache/servicecomb-service-center/server/service/metrics"
        "strings"
 )
 
diff --git a/datasource/etcd/event/schema_summary_event_handler.go 
b/datasource/etcd/event/schema_summary_event_handler.go
index c82ea19..b591858 100644
--- a/datasource/etcd/event/schema_summary_event_handler.go
+++ b/datasource/etcd/event/schema_summary_event_handler.go
@@ -22,7 +22,7 @@ import (
        "github.com/apache/servicecomb-service-center/datasource/etcd/sd"
        pb "github.com/apache/servicecomb-service-center/pkg/registry"
        "github.com/apache/servicecomb-service-center/server/core"
-       "github.com/apache/servicecomb-service-center/server/service/metrics"
+       "github.com/apache/servicecomb-service-center/server/metrics"
        "strings"
 )
 
diff --git a/datasource/etcd/event/service_event_handler.go 
b/datasource/etcd/event/service_event_handler.go
index 5377753..9052eb0 100644
--- a/datasource/etcd/event/service_event_handler.go
+++ b/datasource/etcd/event/service_event_handler.go
@@ -19,14 +19,14 @@ package event
 
 import (
        "context"
+       "github.com/apache/servicecomb-service-center/datasource/etcd/cache"
        "github.com/apache/servicecomb-service-center/datasource/etcd/kv"
        "github.com/apache/servicecomb-service-center/datasource/etcd/sd"
        serviceUtil 
"github.com/apache/servicecomb-service-center/datasource/etcd/util"
        "github.com/apache/servicecomb-service-center/pkg/log"
        pb "github.com/apache/servicecomb-service-center/pkg/registry"
        "github.com/apache/servicecomb-service-center/server/core"
-       "github.com/apache/servicecomb-service-center/server/service/cache"
-       "github.com/apache/servicecomb-service-center/server/service/metrics"
+       "github.com/apache/servicecomb-service-center/server/metrics"
        "strings"
 )
 
diff --git a/datasource/etcd/event/tag_event_handler.go 
b/datasource/etcd/event/tag_event_handler.go
index c66a330..cb8e4f9 100644
--- a/datasource/etcd/event/tag_event_handler.go
+++ b/datasource/etcd/event/tag_event_handler.go
@@ -20,6 +20,7 @@ package event
 import (
        "context"
        "fmt"
+       "github.com/apache/servicecomb-service-center/datasource/etcd/cache"
        "github.com/apache/servicecomb-service-center/datasource/etcd/kv"
        "github.com/apache/servicecomb-service-center/datasource/etcd/sd"
        serviceUtil 
"github.com/apache/servicecomb-service-center/datasource/etcd/util"
@@ -29,7 +30,6 @@ import (
        "github.com/apache/servicecomb-service-center/pkg/util"
        "github.com/apache/servicecomb-service-center/server/core"
        "github.com/apache/servicecomb-service-center/server/notify"
-       "github.com/apache/servicecomb-service-center/server/service/cache"
 )
 
 type TagsChangedTask struct {
diff --git a/datasource/etcd/ms.go b/datasource/etcd/ms.go
index ea65eca..9f26ea0 100644
--- a/datasource/etcd/ms.go
+++ b/datasource/etcd/ms.go
@@ -22,6 +22,7 @@ import (
        "encoding/json"
        "errors"
        "fmt"
+       "github.com/apache/servicecomb-service-center/datasource/etcd/cache"
        "github.com/apache/servicecomb-service-center/datasource/etcd/client"
        registry 
"github.com/apache/servicecomb-service-center/datasource/etcd/client"
        "github.com/apache/servicecomb-service-center/datasource/etcd/kv"
@@ -35,7 +36,6 @@ import (
        "github.com/apache/servicecomb-service-center/server/plugin/quota"
        "github.com/apache/servicecomb-service-center/server/plugin/uuid"
        scerr "github.com/apache/servicecomb-service-center/server/scerror"
-       "github.com/apache/servicecomb-service-center/server/service/cache"
        "strconv"
        "time"
 )
diff --git a/datasource/etcd/sd/etcd/metrics.go 
b/datasource/etcd/sd/etcd/metrics.go
index 6ea556b..ee74f93 100644
--- a/datasource/etcd/sd/etcd/metrics.go
+++ b/datasource/etcd/sd/etcd/metrics.go
@@ -18,26 +18,23 @@
 package etcd
 
 import (
-       "github.com/apache/servicecomb-service-center/server/metric"
+       "github.com/apache/servicecomb-service-center/pkg/metrics"
+       helper "github.com/apache/servicecomb-service-center/pkg/prometheus"
        "github.com/prometheus/client_golang/prometheus"
 )
 
 var (
-       cacheSizeGauge = prometheus.NewGaugeVec(
+       cacheSizeGauge = helper.NewGaugeVec(
                prometheus.GaugeOpts{
-                       Namespace: metric.FamilyName,
+                       Namespace: metrics.FamilyName,
                        Subsystem: "local",
                        Name:      "cache_size_bytes",
                        Help:      "Local cache size summary of backend store",
                }, []string{"instance", "resource", "type"})
 )
 
-func init() {
-       prometheus.MustRegister(cacheSizeGauge)
-}
-
 func ReportCacheSize(resource, t string, s int) {
-       instance := metric.InstanceName()
+       instance := metrics.InstanceName()
        if len(instance) == 0 || len(resource) == 0 {
                // endpoints list will be empty when initializing
                // resource may be empty when report SCHEMA
diff --git a/datasource/etcd/sd/etcd/metrics_test.go 
b/datasource/etcd/sd/etcd/metrics_test.go
index e789997..fd0f91f 100644
--- a/datasource/etcd/sd/etcd/metrics_test.go
+++ b/datasource/etcd/sd/etcd/metrics_test.go
@@ -18,30 +18,30 @@
 package etcd
 
 import (
-       "github.com/apache/servicecomb-service-center/server/metric"
+       "github.com/apache/servicecomb-service-center/pkg/metrics"
        "testing"
        "time"
 )
 
 func TestReportCacheSize(t *testing.T) {
-       if err := metric.Init(metric.Options{
+       if err := metrics.Init(metrics.Options{
                Interval:     time.Second,
                InstanceName: "test",
        }); err != nil {
                t.Fatalf("init metric failed %v", err)
        }
        ReportCacheSize("a", "b", 100)
-       err := metric.Gatherer.Collect()
+       err := metrics.Gatherer.Collect()
        if err != nil {
                t.Fatalf("TestReportCacheSize failed")
        }
-       if metric.Gatherer.Records.Summary("local_cache_size_bytes") != 100 {
+       if metrics.Gatherer.Records.Summary("local_cache_size_bytes") != 100 {
                t.Fatalf("TestReportCacheSize failed")
        }
 
        ReportCacheSize("", "b", 200)
-       err = metric.Gatherer.Collect()
-       if metric.Gatherer.Records.Summary("local_cache_size_bytes") != 100 {
+       err = metrics.Gatherer.Collect()
+       if metrics.Gatherer.Records.Summary("local_cache_size_bytes") != 100 {
                t.Fatalf("TestReportCacheSize failed")
        }
 }
diff --git a/datasource/etcd/sd/metrics.go b/datasource/etcd/sd/metrics.go
index 9fa1496..cdd7d82 100644
--- a/datasource/etcd/sd/metrics.go
+++ b/datasource/etcd/sd/metrics.go
@@ -18,40 +18,37 @@
 package sd
 
 import (
-       "github.com/apache/servicecomb-service-center/server/metric"
+       "github.com/apache/servicecomb-service-center/pkg/metrics"
+       helper "github.com/apache/servicecomb-service-center/pkg/prometheus"
        "github.com/prometheus/client_golang/prometheus"
        "time"
 )
 
 var (
-       eventsCounter = prometheus.NewGaugeVec(
+       eventsCounter = helper.NewGaugeVec(
                prometheus.GaugeOpts{
-                       Namespace: metric.FamilyName,
+                       Namespace: metrics.FamilyName,
                        Subsystem: "db",
                        Name:      "backend_event_total",
                        Help:      "Counter of backend events",
                }, []string{"instance", "prefix"})
 
-       eventsLatency = prometheus.NewSummaryVec(
+       eventsLatency = helper.NewSummaryVec(
                prometheus.SummaryOpts{
-                       Namespace:  metric.FamilyName,
+                       Namespace:  metrics.FamilyName,
                        Subsystem:  "db",
                        Name:       "backend_event_durations_microseconds",
                        Help:       "Latency of backend events processing",
-                       Objectives: metric.Pxx,
+                       Objectives: metrics.Pxx,
                }, []string{"instance", "prefix"})
 )
 
-func init() {
-       prometheus.MustRegister(eventsCounter, eventsLatency)
-}
-
 func ReportProcessEventCompleted(prefix string, evts []KvEvent) {
        l := float64(len(evts))
        if l == 0 {
                return
        }
-       instance := metric.InstanceName()
+       instance := metrics.InstanceName()
        now := time.Now()
        for _, evt := range evts {
                elapsed := float64(now.Sub(evt.CreateAt.Local()).Nanoseconds()) 
/ float64(time.Microsecond)
diff --git a/datasource/metrics.go b/datasource/metrics.go
deleted file mode 100644
index 96ab32e..0000000
--- a/datasource/metrics.go
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * 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 datasource
-
-import (
-       "github.com/apache/servicecomb-service-center/server/metric"
-       "github.com/prometheus/client_golang/prometheus"
-       "time"
-)
-
-const (
-       success = "SUCCESS"
-       failure = "FAILURE"
-)
-
-var (
-       scCounter = prometheus.NewCounterVec(
-               prometheus.CounterOpts{
-                       Namespace: metric.FamilyName,
-                       Subsystem: "db",
-                       Name:      "sc_total",
-                       Help:      "Counter of the Service Center instance",
-               }, []string{"instance"})
-
-       heartbeatCounter = prometheus.NewCounterVec(
-               prometheus.CounterOpts{
-                       Namespace: metric.FamilyName,
-                       Subsystem: "db",
-                       Name:      "heartbeat_total",
-                       Help:      "Counter of heartbeat renew",
-               }, []string{"instance", "status"})
-
-       heartbeatLatency = prometheus.NewSummaryVec(
-               prometheus.SummaryOpts{
-                       Namespace:  metric.FamilyName,
-                       Subsystem:  "db",
-                       Name:       "heartbeat_durations_microseconds",
-                       Help:       "Latency of heartbeat renew",
-                       Objectives: metric.Pxx,
-               }, []string{"instance", "status"})
-)
-
-func init() {
-       prometheus.MustRegister(scCounter, heartbeatCounter, heartbeatLatency)
-}
-
-func ReportScInstance() {
-       instance := metric.InstanceName()
-       scCounter.WithLabelValues(instance).Add(1)
-}
-
-func ReportHeartbeatCompleted(err error, start time.Time) {
-       instance := metric.InstanceName()
-       elapsed := float64(time.Since(start).Nanoseconds()) / 
float64(time.Microsecond)
-       status := success
-       if err != nil {
-               status = failure
-       }
-       heartbeatLatency.WithLabelValues(instance, status).Observe(elapsed)
-       heartbeatCounter.WithLabelValues(instance, status).Inc()
-}
diff --git a/datasource/mongo/account.go b/datasource/mongo/account.go
index 38c3234..82943fa 100644
--- a/datasource/mongo/account.go
+++ b/datasource/mongo/account.go
@@ -22,6 +22,10 @@ import (
        "github.com/apache/servicecomb-service-center/pkg/rbacframe"
 )
 
+func (ds *DataSource) CreateAccount(ctx context.Context, a *rbacframe.Account) 
error {
+       return nil
+}
+
 func (ds *DataSource) AccountExist(ctx context.Context, key string) (bool, 
error) {
        return false, nil
 }
diff --git a/etc/conf/app.yaml b/etc/conf/app.yaml
index 1df6f29..efde076 100644
--- a/etc/conf/app.yaml
+++ b/etc/conf/app.yaml
@@ -109,6 +109,14 @@ metrics:
 
 tracing:
   kind:
+  zipkin:
+    collector:
+      # type should be file or server
+      type:
+      path:
+      endpoint:
+    sampler:
+      rate:
 
 quota:
-  kind: unlimit
+  kind:
diff --git a/server/metric/calculator.go b/pkg/metrics/calculator.go
similarity index 99%
rename from server/metric/calculator.go
rename to pkg/metrics/calculator.go
index f1c4ee7..6574e6d 100644
--- a/server/metric/calculator.go
+++ b/pkg/metrics/calculator.go
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package metric
+package metrics
 
 import (
        dto "github.com/prometheus/client_model/go"
diff --git a/server/metric/calculator_test.go b/pkg/metrics/calculator_test.go
similarity index 99%
rename from server/metric/calculator_test.go
rename to pkg/metrics/calculator_test.go
index 41ce510..a147b27 100644
--- a/server/metric/calculator_test.go
+++ b/pkg/metrics/calculator_test.go
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package metric
+package metrics
 
 import (
        dto "github.com/prometheus/client_model/go"
diff --git a/pkg/metrics/common.go b/pkg/metrics/common.go
new file mode 100644
index 0000000..459e9a4
--- /dev/null
+++ b/pkg/metrics/common.go
@@ -0,0 +1,71 @@
+/*
+ * 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 metrics
+
+import (
+       helper "github.com/apache/servicecomb-service-center/pkg/prometheus"
+       "github.com/prometheus/client_golang/prometheus"
+       dto "github.com/prometheus/client_model/go"
+)
+
+func getValue(name string, labels prometheus.Labels, apply func(m *dto.Metric) 
float64) float64 {
+       f := Family(name)
+       if f == nil {
+               return 0
+       }
+       matchAll := len(labels) == 0
+       var sum float64
+       for _, m := range f.Metric {
+               if !matchAll && !MatchLabels(m, labels) {
+                       continue
+               }
+               sum += apply(m)
+       }
+       return sum
+}
+
+func GaugeValue(name string, labels prometheus.Labels) int64 {
+       return int64(getValue(name, labels, func(m *dto.Metric) float64 { 
return m.GetGauge().GetValue() }))
+}
+
+func MatchLabels(m *dto.Metric, labels prometheus.Labels) bool {
+       count := 0
+       for _, label := range m.GetLabel() {
+               v, ok := labels[label.GetName()]
+               if ok && v != label.GetValue() {
+                       return false
+               }
+               if ok {
+                       count++
+               }
+       }
+       return count == len(labels)
+}
+
+func Family(name string) *dto.MetricFamily {
+       families, err := helper.Gather()
+       if err != nil {
+               return nil
+       }
+       for _, f := range families {
+               if f.GetName() == familyNamePrefix+name {
+                       return f
+               }
+       }
+       return nil
+}
diff --git a/server/metric/gatherer.go b/pkg/metrics/gatherer.go
similarity index 83%
rename from server/metric/gatherer.go
rename to pkg/metrics/gatherer.go
index 29f41b2..8eda08c 100644
--- a/server/metric/gatherer.go
+++ b/pkg/metrics/gatherer.go
@@ -15,27 +15,27 @@
  * limitations under the License.
  */
 
-package metric
+package metrics
 
 import (
        "context"
        "github.com/apache/servicecomb-service-center/pkg/gopool"
        "github.com/apache/servicecomb-service-center/pkg/log"
-       "github.com/prometheus/client_golang/prometheus"
+       "github.com/apache/servicecomb-service-center/pkg/prometheus"
        "strings"
        "sync"
        "time"
 )
 
-func NewGatherer(opts Options) *MetricsGatherer {
-       return &MetricsGatherer{
+func NewGatherer(opts Options) *Gather {
+       return &Gather{
                Interval: opts.Interval,
                Records:  NewMetrics(),
                closed:   true,
        }
 }
 
-type MetricsGatherer struct {
+type Gather struct {
        Records  *Metrics
        Interval time.Duration
 
@@ -43,7 +43,7 @@ type MetricsGatherer struct {
        closed bool
 }
 
-func (mm *MetricsGatherer) Start() {
+func (mm *Gather) Start() {
        mm.lock.Lock()
        if !mm.closed {
                mm.lock.Unlock()
@@ -56,7 +56,7 @@ func (mm *MetricsGatherer) Start() {
        mm.lock.Unlock()
 }
 
-func (mm *MetricsGatherer) loop(ctx context.Context) {
+func (mm *Gather) loop(ctx context.Context) {
        ticker := time.NewTicker(mm.Interval)
        for {
                select {
@@ -73,8 +73,8 @@ func (mm *MetricsGatherer) loop(ctx context.Context) {
        }
 }
 
-func (mm *MetricsGatherer) Collect() error {
-       mfs, err := prometheus.DefaultGatherer.Gather()
+func (mm *Gather) Collect() error {
+       mfs, err := prometheus.Gather()
        if err != nil {
                return err
        }
diff --git a/server/metric/gatherer_test.go b/pkg/metrics/gatherer_test.go
similarity index 98%
rename from server/metric/gatherer_test.go
rename to pkg/metrics/gatherer_test.go
index a778670..dc0f741 100644
--- a/server/metric/gatherer_test.go
+++ b/pkg/metrics/gatherer_test.go
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package metric
+package metrics
 
 import "testing"
 
diff --git a/server/metric/common.go b/pkg/metrics/manager.go
similarity index 88%
rename from server/metric/common.go
rename to pkg/metrics/manager.go
index bc28def..f6c38b9 100644
--- a/server/metric/common.go
+++ b/pkg/metrics/manager.go
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package metric
+package metrics
 
 import (
        "github.com/apache/servicecomb-service-center/pkg/util"
@@ -31,8 +31,9 @@ var (
        options Options
        // SysMetrics map
        SysMetrics util.ConcurrentMap
-       // Gatherer is the reader of sc metrics
-       Gatherer *MetricsGatherer
+       // Gatherer is the reader of sc metrics, but can not get not real time 
metrics
+       // Call the prometheus.Gather() if get the real time metrics
+       Gatherer *Gather
 )
 
 func Init(opts Options) error {
diff --git a/server/metric/common_test.go b/pkg/metrics/manager_test.go
similarity index 98%
rename from server/metric/common_test.go
rename to pkg/metrics/manager_test.go
index 8d2ece7..964889b 100644
--- a/server/metric/common_test.go
+++ b/pkg/metrics/manager_test.go
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package metric
+package metrics
 
 import (
        "github.com/astaxie/beego"
diff --git a/server/metric/metrics.go b/pkg/metrics/metrics.go
similarity index 99%
rename from server/metric/metrics.go
rename to pkg/metrics/metrics.go
index 45bb294..23297c8 100644
--- a/server/metric/metrics.go
+++ b/pkg/metrics/metrics.go
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package metric
+package metrics
 
 import (
        "reflect"
diff --git a/server/metric/metrics_test.go b/pkg/metrics/metrics_test.go
similarity index 99%
rename from server/metric/metrics_test.go
rename to pkg/metrics/metrics_test.go
index fd678c5..1685363 100644
--- a/server/metric/metrics_test.go
+++ b/pkg/metrics/metrics_test.go
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package metric
+package metrics
 
 import (
        dto "github.com/prometheus/client_model/go"
diff --git a/server/metric/options.go b/pkg/metrics/options.go
similarity index 98%
copy from server/metric/options.go
copy to pkg/metrics/options.go
index 17cc97a..c8a25ea 100644
--- a/server/metric/options.go
+++ b/pkg/metrics/options.go
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package metric
+package metrics
 
 import (
        "time"
diff --git a/server/metric/reporter.go b/pkg/metrics/reporter.go
similarity index 98%
rename from server/metric/reporter.go
rename to pkg/metrics/reporter.go
index decfba4..072acc2 100644
--- a/server/metric/reporter.go
+++ b/pkg/metrics/reporter.go
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package metric
+package metrics
 
 import "github.com/apache/servicecomb-service-center/pkg/log"
 
diff --git a/server/metric/reporter_test.go b/pkg/metrics/reporter_test.go
similarity index 98%
rename from server/metric/reporter_test.go
rename to pkg/metrics/reporter_test.go
index 3962540..0b76074 100644
--- a/server/metric/reporter_test.go
+++ b/pkg/metrics/reporter_test.go
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package metric
+package metrics
 
 import "testing"
 
diff --git a/pkg/prometheus/decorator.go b/pkg/prometheus/decorator.go
new file mode 100644
index 0000000..318c456
--- /dev/null
+++ b/pkg/prometheus/decorator.go
@@ -0,0 +1,63 @@
+/*
+ * 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 prometheus
+
+import (
+       "github.com/apache/servicecomb-service-center/pkg/log"
+       "github.com/apache/servicecomb-service-center/pkg/util"
+       "github.com/prometheus/client_golang/prometheus"
+       dto "github.com/prometheus/client_model/go"
+)
+
+// Vectors is unsafe, so all NewXXXVec funcs should be called during the 
initialization phase
+var Vectors = make(map[string]prometheus.Collector)
+
+func registerMetrics(name string, vec prometheus.Collector) {
+       if _, ok := Vectors[name]; ok {
+               log.Warnf("found duplicate metrics name[%s], override!", name)
+       }
+       if err := prometheus.Register(vec); err != nil {
+               log.Fatalf(err, "register prometheus metrics[%s] failed", name)
+       }
+       Vectors[name] = vec
+}
+
+func NewCounterVec(opts prometheus.CounterOpts, labelNames []string) 
*prometheus.CounterVec {
+       name := util.StringJoin([]string{opts.Subsystem, opts.Name}, "_")
+       vec := prometheus.NewCounterVec(opts, labelNames)
+       registerMetrics(name, vec)
+       return vec
+}
+
+func NewGaugeVec(opts prometheus.GaugeOpts, labelNames []string) 
*prometheus.GaugeVec {
+       name := util.StringJoin([]string{opts.Subsystem, opts.Name}, "_")
+       vec := prometheus.NewGaugeVec(opts, labelNames)
+       registerMetrics(name, vec)
+       return vec
+}
+
+func NewSummaryVec(opts prometheus.SummaryOpts, labelNames []string) 
*prometheus.SummaryVec {
+       name := util.StringJoin([]string{opts.Subsystem, opts.Name}, "_")
+       vec := prometheus.NewSummaryVec(opts, labelNames)
+       registerMetrics(name, vec)
+       return vec
+}
+
+func Gather() ([]*dto.MetricFamily, error) {
+       return prometheus.DefaultGatherer.Gather()
+}
diff --git a/server/bootstrap/bootstrap.go b/server/bootstrap/bootstrap.go
index c8661bc..c98e43a 100644
--- a/server/bootstrap/bootstrap.go
+++ b/server/bootstrap/bootstrap.go
@@ -53,7 +53,7 @@ import _ 
"github.com/apache/servicecomb-service-center/server/rest/govern"
 import _ "github.com/apache/servicecomb-service-center/server/rest/admin"
 
 //metrics
-import _ "github.com/apache/servicecomb-service-center/server/metric"
+import _ "github.com/apache/servicecomb-service-center/server/rest/prometheus"
 
 import (
        "github.com/apache/servicecomb-service-center/pkg/log"
@@ -63,7 +63,7 @@ import (
        "github.com/apache/servicecomb-service-center/server/handler/cache"
        "github.com/apache/servicecomb-service-center/server/handler/context"
        "github.com/apache/servicecomb-service-center/server/handler/maxbody"
-       "github.com/apache/servicecomb-service-center/server/handler/metric"
+       "github.com/apache/servicecomb-service-center/server/handler/metrics"
        "github.com/apache/servicecomb-service-center/server/handler/tracing"
        "github.com/apache/servicecomb-service-center/server/interceptor"
        "github.com/apache/servicecomb-service-center/server/interceptor/access"
@@ -80,7 +80,7 @@ func init() {
        // handle requests after routing.
        accesslog.RegisterHandlers()
        maxbody.RegisterHandlers()
-       metric.RegisterHandlers()
+       metrics.RegisterHandlers()
        tracing.RegisterHandlers()
        auth.RegisterHandlers()
        context.RegisterHandlers()
diff --git a/server/connection/grpc/stream.go b/server/connection/grpc/stream.go
index f0f9811..ccb92d3 100644
--- a/server/connection/grpc/stream.go
+++ b/server/connection/grpc/stream.go
@@ -25,6 +25,7 @@ import (
        pb "github.com/apache/servicecomb-service-center/pkg/registry"
        "github.com/apache/servicecomb-service-center/pkg/util"
        "github.com/apache/servicecomb-service-center/server/connection"
+       "github.com/apache/servicecomb-service-center/server/metrics"
        "github.com/apache/servicecomb-service-center/server/notify"
        "time"
 )
@@ -55,7 +56,7 @@ func Handle(watcher *notify.InstanceEventListWatcher, stream 
proto.ServiceInstan
                                watcher.Subject(), watcher.Group())
 
                        err = stream.Send(resp)
-                       connection.ReportPublishCompleted(job, err)
+                       metrics.ReportPublishCompleted(job, err)
                        if err != nil {
                                log.Errorf(err, "send message error, subject: 
%s, group: %s",
                                        watcher.Subject(), watcher.Group())
@@ -75,8 +76,8 @@ func ListAndWatch(ctx context.Context, serviceID string, f 
func() ([]*pb.WatchIn
        if err != nil {
                return
        }
-       connection.ReportSubscriber(domain, GRPC, 1)
+       metrics.ReportSubscriber(domain, GRPC, 1)
        err = Handle(watcher, stream)
-       connection.ReportSubscriber(domain, GRPC, -1)
+       metrics.ReportSubscriber(domain, GRPC, -1)
        return
 }
diff --git a/server/connection/ws/websocket.go 
b/server/connection/ws/websocket.go
index a61ce16..3a25a9d 100644
--- a/server/connection/ws/websocket.go
+++ b/server/connection/ws/websocket.go
@@ -26,6 +26,7 @@ import (
        pb "github.com/apache/servicecomb-service-center/pkg/registry"
        "github.com/apache/servicecomb-service-center/pkg/util"
        "github.com/apache/servicecomb-service-center/server/connection"
+       "github.com/apache/servicecomb-service-center/server/metrics"
        "github.com/apache/servicecomb-service-center/server/notify"
        "github.com/gorilla/websocket"
        "time"
@@ -259,7 +260,7 @@ func (wh *WebSocket) HandleEvent(o interface{}) {
 
        err := wh.WriteMessage(message)
        if evt, ok := o.(*notify.InstanceEvent); ok {
-               connection.ReportPublishCompleted(evt, err)
+               metrics.ReportPublishCompleted(evt, err)
        }
        if err != nil {
                log.Errorf(err, "watcher[%s] catch an err, subject: %s, group: 
%s",
@@ -295,9 +296,9 @@ func ListAndWatch(ctx context.Context, serviceID string, f 
func() ([]*pb.WatchIn
        domain := util.ParseDomain(ctx)
        socket := New(ctx, conn, notify.NewInstanceEventListWatcher(serviceID, 
domainProject, f))
 
-       connection.ReportSubscriber(domain, Websocket, 1)
+       metrics.ReportSubscriber(domain, Websocket, 1)
        process(socket)
-       connection.ReportSubscriber(domain, Websocket, -1)
+       metrics.ReportSubscriber(domain, Websocket, -1)
 }
 
 func process(socket *WebSocket) {
diff --git a/server/handler/metric/metric.go b/server/handler/metrics/metrics.go
similarity index 82%
rename from server/handler/metric/metric.go
rename to server/handler/metrics/metrics.go
index 6a0de03..39cc3e7 100644
--- a/server/handler/metric/metric.go
+++ b/server/handler/metrics/metrics.go
@@ -15,21 +15,21 @@
  * limitations under the License.
  */
 
-package metric
+package metrics
 
 import (
        "github.com/apache/servicecomb-service-center/pkg/chain"
        "github.com/apache/servicecomb-service-center/pkg/log"
        "github.com/apache/servicecomb-service-center/pkg/rest"
-       "github.com/apache/servicecomb-service-center/server/metric/prometheus"
+       "github.com/apache/servicecomb-service-center/server/metrics"
        "net/http"
        "time"
 )
 
-type MetricsHandler struct {
+type Handler struct {
 }
 
-func (h *MetricsHandler) Handle(i *chain.Invocation) {
+func (h *Handler) Handle(i *chain.Invocation) {
        i.Next(chain.WithAsyncFunc(func(ret chain.Result) {
                start, ok := 
i.Context().Value(rest.CtxStartTimestamp).(time.Time)
                if !ok {
@@ -37,11 +37,11 @@ func (h *MetricsHandler) Handle(i *chain.Invocation) {
                }
                w, r := 
i.Context().Value(rest.CtxResponse).(http.ResponseWriter),
                        i.Context().Value(rest.CtxRequest).(*http.Request)
-               prometheus.ReportRequestCompleted(w, r, start)
+               metrics.ReportRequestCompleted(w, r, start)
                log.NilOrWarnf(start, "%s %s", r.Method, r.RequestURI)
        }))
 }
 
 func RegisterHandlers() {
-       chain.RegisterHandler(rest.ServerChainName, &MetricsHandler{})
+       chain.RegisterHandler(rest.ServerChainName, &Handler{})
 }
diff --git a/server/health/metrics.go b/server/health/metrics.go
deleted file mode 100644
index 79e0d6a..0000000
--- a/server/health/metrics.go
+++ /dev/null
@@ -1,62 +0,0 @@
-// 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 health
-
-import (
-       "context"
-       "github.com/apache/servicecomb-service-center/pkg/gopool"
-       "github.com/apache/servicecomb-service-center/pkg/util"
-       "github.com/apache/servicecomb-service-center/server/metric"
-       "github.com/prometheus/client_golang/prometheus"
-       "runtime"
-       "time"
-)
-
-const durationReportCPUUsage = 3 * time.Second
-
-var (
-       cpuGauge = prometheus.NewGaugeVec(
-               prometheus.GaugeOpts{
-                       Namespace: metric.FamilyName,
-                       Subsystem: "process",
-                       Name:      "cpu_usage",
-                       Help:      "Process cpu usage",
-               }, []string{"instance"})
-)
-
-func init() {
-       prometheus.MustRegister(cpuGauge)
-       gopool.Go(AutoReportCPUUsage)
-}
-
-func AutoReportCPUUsage(ctx context.Context) {
-       var (
-               cpuTotal float64
-               cpuProc  float64
-               cpus     = runtime.NumCPU()
-       )
-       for {
-               select {
-               case <-ctx.Done():
-                       return
-               case <-time.After(durationReportCPUUsage):
-                       pt, ct := util.GetProcCPUUsage()
-                       cpuGauge.WithLabelValues(metric.InstanceName()).Set(
-                               (pt - cpuProc) * float64(cpus) / (ct - 
cpuTotal))
-                       cpuTotal, cpuProc = ct, pt
-               }
-       }
-}
diff --git a/server/metric/prometheus/reporter.go 
b/server/metric/prometheus/reporter.go
deleted file mode 100644
index cf38c53..0000000
--- a/server/metric/prometheus/reporter.go
+++ /dev/null
@@ -1,72 +0,0 @@
-// 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 prometheus
-
-import (
-       "github.com/apache/servicecomb-service-center/server/metric"
-       dto "github.com/prometheus/client_model/go"
-)
-
-const (
-       httpRequestTotal = "http_request_total"
-)
-
-var qpsLabelMap = map[string]int{
-       "method":   0,
-       "instance": 1,
-       "api":      2,
-       "domain":   3,
-}
-
-type APIReporter struct {
-       cache *metric.Details
-}
-
-func (r *APIReporter) Report() {
-       details := metric.Gatherer.Records.Get(httpRequestTotal)
-       if details == nil {
-               return
-       }
-
-       defer func() { r.cache = details }()
-
-       if r.cache == nil {
-               return
-       }
-       details.ForEach(func(labels []*dto.LabelPair, v float64) (next bool) {
-               old := r.cache.Get(labels)
-               queryPerSeconds.WithLabelValues(r.toLabels(labels)...).Set((v - 
old) / metric.GetOptions().Interval.Seconds())
-               return true
-       })
-}
-
-func (r *APIReporter) toLabels(pairs []*dto.LabelPair) (labels []string) {
-       labels = make([]string, len(qpsLabelMap))
-       for _, pair := range pairs {
-               if i, ok := qpsLabelMap[pair.GetName()]; ok {
-                       labels[i] = pair.GetValue()
-               }
-       }
-       return
-}
-
-func init() {
-       metric.RegisterReporter("rest", NewAPIReporter())
-}
-
-func NewAPIReporter() *APIReporter {
-       return &APIReporter{}
-}
diff --git a/server/metric/options.go b/server/metrics/common.go
similarity index 81%
copy from server/metric/options.go
copy to server/metrics/common.go
index 17cc97a..f800d66 100644
--- a/server/metric/options.go
+++ b/server/metrics/common.go
@@ -15,16 +15,9 @@
  * limitations under the License.
  */
 
-package metric
+package metrics
 
-import (
-       "time"
+const (
+       success = "SUCCESS"
+       failure = "FAILURE"
 )
-
-//Options contains metrics configs
-type Options struct {
-       Interval     time.Duration
-       InstanceName string
-       // SysMetrics set
-       SysMetrics []string
-}
diff --git a/server/connection/metrics.go b/server/metrics/connection.go
similarity index 78%
rename from server/connection/metrics.go
rename to server/metrics/connection.go
index 00b201a..cd9c805 100644
--- a/server/connection/metrics.go
+++ b/server/metrics/connection.go
@@ -15,53 +15,45 @@
  * limitations under the License.
  */
 
-package connection
+package metrics
 
 import (
+       "github.com/apache/servicecomb-service-center/pkg/metrics"
        "github.com/apache/servicecomb-service-center/pkg/notify"
-       "github.com/apache/servicecomb-service-center/server/metric"
+       helper "github.com/apache/servicecomb-service-center/pkg/prometheus"
        "github.com/prometheus/client_golang/prometheus"
        "time"
 )
 
-const (
-       success = "SUCCESS"
-       failure = "FAILURE"
-)
-
 var (
-       notifyCounter = prometheus.NewCounterVec(
+       notifyCounter = helper.NewCounterVec(
                prometheus.CounterOpts{
-                       Namespace: metric.FamilyName,
+                       Namespace: metrics.FamilyName,
                        Subsystem: "notify",
                        Name:      "publish_total",
                        Help:      "Counter of publishing instance events",
                }, []string{"instance", "source", "status"})
 
-       notifyLatency = prometheus.NewSummaryVec(
+       notifyLatency = helper.NewSummaryVec(
                prometheus.SummaryOpts{
-                       Namespace:  metric.FamilyName,
+                       Namespace:  metrics.FamilyName,
                        Subsystem:  "notify",
                        Name:       "publish_durations_microseconds",
                        Help:       "Latency of publishing instance events",
-                       Objectives: metric.Pxx,
+                       Objectives: metrics.Pxx,
                }, []string{"instance", "source", "status"})
 
-       subscriberGauge = prometheus.NewGaugeVec(
+       subscriberGauge = helper.NewGaugeVec(
                prometheus.GaugeOpts{
-                       Namespace: metric.FamilyName,
+                       Namespace: metrics.FamilyName,
                        Subsystem: "notify",
                        Name:      "subscriber_total",
                        Help:      "Gauge of subscribers",
                }, []string{"instance", "domain", "scheme"})
 )
 
-func init() {
-       prometheus.MustRegister(notifyCounter, notifyLatency, subscriberGauge)
-}
-
 func ReportPublishCompleted(evt notify.Event, err error) {
-       instance := metric.InstanceName()
+       instance := metrics.InstanceName()
        elapsed := float64(time.Since(evt.CreateAt()).Nanoseconds()) / 
float64(time.Microsecond)
        status := success
        if err != nil {
@@ -72,7 +64,7 @@ func ReportPublishCompleted(evt notify.Event, err error) {
 }
 
 func ReportSubscriber(domain, scheme string, n float64) {
-       instance := metric.InstanceName()
+       instance := metrics.InstanceName()
 
        subscriberGauge.WithLabelValues(instance, domain, scheme).Add(n)
 }
diff --git a/server/metric/prometheus/metrics.go b/server/metrics/http.go
similarity index 78%
rename from server/metric/prometheus/metrics.go
rename to server/metrics/http.go
index 94985af..ee0fe81 100644
--- a/server/metric/prometheus/metrics.go
+++ b/server/metrics/http.go
@@ -15,15 +15,16 @@
  * limitations under the License.
  */
 
-package prometheus
+// metrics pkg declare http metrics and impl a reporter to set the
+// 'query_per_seconds' value periodically
+package metrics
 
 import (
+       "github.com/apache/servicecomb-service-center/pkg/metrics"
+       helper "github.com/apache/servicecomb-service-center/pkg/prometheus"
        "github.com/apache/servicecomb-service-center/pkg/rest"
        "github.com/apache/servicecomb-service-center/pkg/util"
-       "github.com/apache/servicecomb-service-center/server/metric"
-       router "github.com/apache/servicecomb-service-center/server/rest"
        "github.com/prometheus/client_golang/prometheus"
-       "github.com/prometheus/client_golang/prometheus/promhttp"
        "net/http"
        "strconv"
        "strings"
@@ -31,48 +32,42 @@ import (
 )
 
 var (
-       incomingRequests = prometheus.NewCounterVec(
+       incomingRequests = helper.NewCounterVec(
                prometheus.CounterOpts{
-                       Namespace: metric.FamilyName,
+                       Namespace: metrics.FamilyName,
                        Subsystem: "http",
                        Name:      "request_total",
                        Help:      "Counter of requests received into ROA 
handler",
                }, []string{"method", "code", "instance", "api", "domain"})
 
-       successfulRequests = prometheus.NewCounterVec(
+       successfulRequests = helper.NewCounterVec(
                prometheus.CounterOpts{
-                       Namespace: metric.FamilyName,
+                       Namespace: metrics.FamilyName,
                        Subsystem: "http",
                        Name:      "success_total",
                        Help:      "Counter of successful requests processed by 
ROA handler",
                }, []string{"method", "code", "instance", "api", "domain"})
 
-       reqDurations = prometheus.NewSummaryVec(
+       reqDurations = helper.NewSummaryVec(
                prometheus.SummaryOpts{
-                       Namespace:  metric.FamilyName,
+                       Namespace:  metrics.FamilyName,
                        Subsystem:  "http",
                        Name:       "request_durations_microseconds",
                        Help:       "HTTP request latency summary of ROA 
handler",
-                       Objectives: metric.Pxx,
+                       Objectives: metrics.Pxx,
                }, []string{"method", "instance", "api", "domain"})
 
-       queryPerSeconds = prometheus.NewGaugeVec(
+       queryPerSeconds = helper.NewGaugeVec(
                prometheus.GaugeOpts{
-                       Namespace: metric.FamilyName,
+                       Namespace: metrics.FamilyName,
                        Subsystem: "http",
                        Name:      "query_per_seconds",
                        Help:      "HTTP requests per seconds of ROA handler",
                }, []string{"method", "instance", "api", "domain"})
 )
 
-func init() {
-       prometheus.MustRegister(incomingRequests, successfulRequests, 
reqDurations, queryPerSeconds)
-
-       router.RegisterServerHandler("/metrics", promhttp.Handler())
-}
-
 func ReportRequestCompleted(w http.ResponseWriter, r *http.Request, start 
time.Time) {
-       instance := metric.InstanceName()
+       instance := metrics.InstanceName()
        elapsed := float64(time.Since(start).Nanoseconds()) / 
float64(time.Microsecond)
        route, _ := r.Context().Value(rest.CtxMatchFunc).(string)
        domain := util.ParseDomain(r.Context())
diff --git a/server/metrics/http_reporter.go b/server/metrics/http_reporter.go
new file mode 100644
index 0000000..86faf37
--- /dev/null
+++ b/server/metrics/http_reporter.go
@@ -0,0 +1,75 @@
+/*
+ * 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 metrics
+
+import (
+       "github.com/apache/servicecomb-service-center/pkg/metrics"
+       dto "github.com/prometheus/client_model/go"
+)
+
+const (
+       httpRequestTotal = "http_request_total"
+)
+
+var qpsLabelMap = map[string]int{
+       "method":   0,
+       "instance": 1,
+       "api":      2,
+       "domain":   3,
+}
+
+// APIReporter is used to calc the http TPS
+type APIReporter struct {
+       cache *metrics.Details
+}
+
+func (r *APIReporter) Report() {
+       details := metrics.Gatherer.Records.Get(httpRequestTotal)
+       if details == nil {
+               return
+       }
+
+       defer func() { r.cache = details }()
+
+       if r.cache == nil {
+               return
+       }
+       details.ForEach(func(labels []*dto.LabelPair, v float64) (next bool) {
+               old := r.cache.Get(labels)
+               queryPerSeconds.WithLabelValues(r.toLabels(labels)...).Set((v - 
old) / metrics.GetOptions().Interval.Seconds())
+               return true
+       })
+}
+
+func (r *APIReporter) toLabels(pairs []*dto.LabelPair) (labels []string) {
+       labels = make([]string, len(qpsLabelMap))
+       for _, pair := range pairs {
+               if i, ok := qpsLabelMap[pair.GetName()]; ok {
+                       labels[i] = pair.GetValue()
+               }
+       }
+       return
+}
+
+func init() {
+       metrics.RegisterReporter("rest", NewAPIReporter())
+}
+
+func NewAPIReporter() *APIReporter {
+       return &APIReporter{}
+}
diff --git a/server/service/metrics/metrics.go b/server/metrics/meta.go
similarity index 61%
rename from server/service/metrics/metrics.go
rename to server/metrics/meta.go
index 389abc8..7722788 100644
--- a/server/service/metrics/metrics.go
+++ b/server/metrics/meta.go
@@ -18,9 +18,11 @@
 package metrics
 
 import (
+       "github.com/apache/servicecomb-service-center/pkg/metrics"
+       helper "github.com/apache/servicecomb-service-center/pkg/prometheus"
        "github.com/apache/servicecomb-service-center/pkg/util"
-       "github.com/apache/servicecomb-service-center/server/metric"
        "github.com/prometheus/client_golang/prometheus"
+       "time"
 )
 
 // keys of gauge
@@ -40,45 +42,70 @@ func Key(name string) string {
 }
 
 var (
-       domainCounter = prometheus.NewGaugeVec(
+       domainCounter = helper.NewGaugeVec(
                prometheus.GaugeOpts{
-                       Namespace: metric.FamilyName,
+                       Namespace: metrics.FamilyName,
                        Subsystem: SubSystem,
                        Name:      KeyDomainTotal,
                        Help:      "Gauge of domain created in Service Center",
                }, []string{"instance"})
 
-       serviceCounter = prometheus.NewGaugeVec(
+       serviceCounter = helper.NewGaugeVec(
                prometheus.GaugeOpts{
-                       Namespace: metric.FamilyName,
+                       Namespace: metrics.FamilyName,
                        Subsystem: "db",
                        Name:      KeyServiceTotal,
                        Help:      "Gauge of microservice created in Service 
Center",
                }, []string{"instance", "framework", "frameworkVersion", 
"domain"})
 
-       instanceCounter = prometheus.NewGaugeVec(
+       instanceCounter = helper.NewGaugeVec(
                prometheus.GaugeOpts{
-                       Namespace: metric.FamilyName,
+                       Namespace: metrics.FamilyName,
                        Subsystem: SubSystem,
                        Name:      KeyInstanceTotal,
                        Help:      "Gauge of microservice created in Service 
Center",
                }, []string{"instance", "domain"})
 
-       schemaCounter = prometheus.NewGaugeVec(
+       schemaCounter = helper.NewGaugeVec(
                prometheus.GaugeOpts{
-                       Namespace: metric.FamilyName,
+                       Namespace: metrics.FamilyName,
                        Subsystem: SubSystem,
                        Name:      KeySchemaTotal,
                        Help:      "Gauge of schema created in Service Center",
                }, []string{"instance", "domain"})
 
-       frameworkCounter = prometheus.NewGaugeVec(
+       frameworkCounter = helper.NewGaugeVec(
                prometheus.GaugeOpts{
-                       Namespace: metric.FamilyName,
+                       Namespace: metrics.FamilyName,
                        Subsystem: SubSystem,
                        Name:      KeyFrameworkTotal,
                        Help:      "Gauge of client framework info in Service 
Center",
-               }, metric.ToLabelNames(Framework{}))
+               }, metrics.ToLabelNames(Framework{}))
+
+       scCounter = helper.NewCounterVec(
+               prometheus.CounterOpts{
+                       Namespace: metrics.FamilyName,
+                       Subsystem: "db",
+                       Name:      "sc_total",
+                       Help:      "Counter of the Service Center instance",
+               }, []string{"instance"})
+
+       heartbeatCounter = helper.NewCounterVec(
+               prometheus.CounterOpts{
+                       Namespace: metrics.FamilyName,
+                       Subsystem: "db",
+                       Name:      "heartbeat_total",
+                       Help:      "Counter of heartbeat renew",
+               }, []string{"instance", "status"})
+
+       heartbeatLatency = helper.NewSummaryVec(
+               prometheus.SummaryOpts{
+                       Namespace:  metrics.FamilyName,
+                       Subsystem:  "db",
+                       Name:       "heartbeat_durations_microseconds",
+                       Help:       "Latency of heartbeat renew",
+                       Objectives: metrics.Pxx,
+               }, []string{"instance", "status"})
 )
 
 // Framework return framework info.
@@ -89,30 +116,42 @@ type Framework struct {
        FrameworkVersion string `json:"frameworkVersion"`
 }
 
-func init() {
-       prometheus.MustRegister(domainCounter, serviceCounter, instanceCounter, 
schemaCounter, frameworkCounter)
-}
-
 func ReportDomains(c float64) {
-       instance := metric.InstanceName()
+       instance := metrics.InstanceName()
        domainCounter.WithLabelValues(instance).Add(c)
 }
 
 func ReportServices(domain, framework, frameworkVersion string, c float64) {
-       instance := metric.InstanceName()
+       instance := metrics.InstanceName()
        serviceCounter.WithLabelValues(instance, framework, frameworkVersion, 
domain).Add(c)
 }
 
 func ReportInstances(domain string, c float64) {
-       instance := metric.InstanceName()
+       instance := metrics.InstanceName()
        instanceCounter.WithLabelValues(instance, domain).Add(c)
 }
 
 func ReportSchemas(domain string, c float64) {
-       instance := metric.InstanceName()
+       instance := metrics.InstanceName()
        schemaCounter.WithLabelValues(instance, domain).Add(c)
 }
 
 func ReportFramework(domainName, projectName string, framework, 
frameworkVersion string, c float64) {
        frameworkCounter.WithLabelValues(domainName, projectName, framework, 
frameworkVersion).Add(c)
 }
+
+func ReportScInstance() {
+       instance := metrics.InstanceName()
+       scCounter.WithLabelValues(instance).Add(1)
+}
+
+func ReportHeartbeatCompleted(err error, start time.Time) {
+       instance := metrics.InstanceName()
+       elapsed := float64(time.Since(start).Nanoseconds()) / 
float64(time.Microsecond)
+       status := success
+       if err != nil {
+               status = failure
+       }
+       heartbeatLatency.WithLabelValues(instance, status).Observe(elapsed)
+       heartbeatCounter.WithLabelValues(instance, status).Inc()
+}
diff --git a/server/metrics/sys.go b/server/metrics/sys.go
new file mode 100644
index 0000000..9e23f05
--- /dev/null
+++ b/server/metrics/sys.go
@@ -0,0 +1,70 @@
+/*
+ * 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 metrics
+
+import (
+       "context"
+       "github.com/apache/servicecomb-service-center/pkg/gopool"
+       "github.com/apache/servicecomb-service-center/pkg/log"
+       "github.com/apache/servicecomb-service-center/pkg/metrics"
+       helper "github.com/apache/servicecomb-service-center/pkg/prometheus"
+       "github.com/apache/servicecomb-service-center/pkg/util"
+       "github.com/prometheus/client_golang/prometheus"
+       "runtime"
+       "time"
+)
+
+const durationReportCPUUsage = 3 * time.Second
+
+var (
+       cpuGauge = helper.NewGaugeVec(
+               prometheus.GaugeOpts{
+                       Namespace: metrics.FamilyName,
+                       Subsystem: "process",
+                       Name:      "cpu_usage",
+                       Help:      "Process cpu usage",
+               }, []string{"instance"})
+)
+
+func init() {
+       gopool.Go(AutoReportCPUUsage)
+}
+
+func AutoReportCPUUsage(ctx context.Context) {
+       var (
+               cpuTotal float64
+               cpuProc  float64
+               cpus     = runtime.NumCPU()
+       )
+       for {
+               select {
+               case <-ctx.Done():
+                       return
+               case <-time.After(durationReportCPUUsage):
+                       pt, ct := util.GetProcCPUUsage()
+                       diff := ct - cpuTotal
+                       if diff <= 0 {
+                               log.Warnf("the current cpu usage is the same as 
the previous period")
+                               continue
+                       }
+                       cpuGauge.WithLabelValues(metrics.InstanceName()).Set(
+                               (pt - cpuProc) * float64(cpus) / diff)
+                       cpuTotal, cpuProc = ct, pt
+               }
+       }
+}
diff --git a/server/plugin/quota/buildin/buildin.go 
b/server/plugin/quota/buildin/buildin.go
index ebd2cde..3ecd377 100644
--- a/server/plugin/quota/buildin/buildin.go
+++ b/server/plugin/quota/buildin/buildin.go
@@ -22,7 +22,6 @@ import (
        "github.com/apache/servicecomb-service-center/pkg/log"
        mgr "github.com/apache/servicecomb-service-center/server/plugin"
        "github.com/apache/servicecomb-service-center/server/plugin/quota"
-       
"github.com/apache/servicecomb-service-center/server/plugin/quota/counter"
 )
 
 func init() {
@@ -31,7 +30,6 @@ func init() {
 
 func New() mgr.Instance {
        quota.Init()
-       counter.RegisterCounterListener("buildin")
        log.Infof("quota init, service: %d, instance: %d, schema: %d/service, 
tag: %d/service, rule: %d/service",
                quota.DefaultServiceQuota, quota.DefaultInstanceQuota,
                quota.DefaultSchemaQuota, quota.DefaultTagQuota, 
quota.DefaultRuleQuota)
diff --git a/server/plugin/quota/buildin/common.go 
b/server/plugin/quota/buildin/common.go
index dd6d742..05f6c0f 100644
--- a/server/plugin/quota/buildin/common.go
+++ b/server/plugin/quota/buildin/common.go
@@ -23,11 +23,17 @@ import (
        "fmt"
        "github.com/apache/servicecomb-service-center/datasource"
        "github.com/apache/servicecomb-service-center/pkg/log"
+       "github.com/apache/servicecomb-service-center/pkg/metrics"
        pb "github.com/apache/servicecomb-service-center/pkg/registry"
        "github.com/apache/servicecomb-service-center/server/plugin/quota"
        scerr "github.com/apache/servicecomb-service-center/server/scerror"
 )
 
+const (
+       TotalService  = "db_service_total"
+       TotalInstance = "db_instance_total"
+)
+
 type GetCurUsedNum func(context.Context, *quota.ApplyQuotaResource) (int64, 
error)
 type GetLimitQuota func() int64
 
@@ -77,10 +83,10 @@ func resourceLimitHandler(ctx context.Context, res 
*quota.ApplyQuotaResource) (i
        serviceID := res.ServiceID
 
        switch res.QuotaType {
-       case quota.MicroServiceInstanceQuotaType:
-               return globalCounter.InstanceCount, nil
        case quota.MicroServiceQuotaType:
-               return globalCounter.ServiceCount, nil
+               return metrics.GaugeValue(TotalService, nil), nil
+       case quota.MicroServiceInstanceQuotaType:
+               return metrics.GaugeValue(TotalInstance, nil), nil
        case quota.RuleQuotaType:
                {
                        resp, err := datasource.Instance().GetRules(ctx, 
&pb.GetServiceRulesRequest{
diff --git a/server/plugin/quota/buildin/counter.go 
b/server/plugin/quota/buildin/counter.go
deleted file mode 100644
index 96e5421..0000000
--- a/server/plugin/quota/buildin/counter.go
+++ /dev/null
@@ -1,57 +0,0 @@
-// 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 buildin
-
-import (
-       "github.com/apache/servicecomb-service-center/datasource/etcd/kv"
-       "github.com/apache/servicecomb-service-center/datasource/etcd/sd"
-       
"github.com/apache/servicecomb-service-center/server/plugin/quota/counter"
-)
-
-var globalCounter = &GlobalCounter{}
-
-func init() {
-       counter.RegisterCounter(globalCounter)
-}
-
-type GlobalCounter struct {
-       ServiceCount  int64
-       InstanceCount int64
-}
-
-func (c *GlobalCounter) OnCreate(t sd.Type, domainProject string) {
-       switch t {
-       case kv.ServiceIndex:
-               c.ServiceCount++
-       case kv.INSTANCE:
-               c.InstanceCount++
-       }
-}
-
-func (c *GlobalCounter) OnDelete(t sd.Type, domainProject string) {
-       switch t {
-       case kv.ServiceIndex:
-               if c.ServiceCount == 0 {
-                       return
-               }
-               c.ServiceCount--
-       case kv.INSTANCE:
-               if c.InstanceCount == 0 {
-                       return
-               }
-               c.InstanceCount--
-       }
-}
diff --git a/server/plugin/quota/buildin/counter_test.go 
b/server/plugin/quota/buildin/counter_test.go
deleted file mode 100644
index e35fd08..0000000
--- a/server/plugin/quota/buildin/counter_test.go
+++ /dev/null
@@ -1,51 +0,0 @@
-// 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 buildin_test
-
-import (
-       "github.com/apache/servicecomb-service-center/datasource/etcd/kv"
-       
"github.com/apache/servicecomb-service-center/server/plugin/quota/buildin"
-       "testing"
-)
-
-func TestGlobalCounter_OnCreate(t *testing.T) {
-       var counter buildin.GlobalCounter
-       counter.OnCreate(kv.SERVICE, "a/b")
-       counter.OnCreate(kv.ServiceIndex, "a/b")
-       counter.OnCreate(kv.INSTANCE, "a/b")
-       counter.OnCreate(kv.ServiceIndex, "a/b")
-       counter.OnCreate(kv.INSTANCE, "a/b")
-       if counter.ServiceCount != 2 || counter.InstanceCount != 2 {
-               t.Fatal("TestGlobalCounter_OnCreate failed", counter)
-       }
-}
-
-func TestGlobalCounter_OnDelete(t *testing.T) {
-       var counter buildin.GlobalCounter
-       counter.OnDelete(kv.SERVICE, "a/b")
-       counter.OnDelete(kv.ServiceIndex, "a/b")
-       counter.OnDelete(kv.INSTANCE, "a/b")
-       if counter.ServiceCount != 0 || counter.InstanceCount != 0 {
-               t.Fatal("TestGlobalCounter_OnDelete failed", counter)
-       }
-       counter.OnCreate(kv.ServiceIndex, "a/b")
-       counter.OnCreate(kv.INSTANCE, "a/b")
-       counter.OnDelete(kv.ServiceIndex, "a/b")
-       counter.OnDelete(kv.INSTANCE, "a/b")
-       if counter.ServiceCount != 0 || counter.InstanceCount != 0 {
-               t.Fatal("TestGlobalCounter_OnDelete failed", counter)
-       }
-}
diff --git a/server/plugin/quota/counter/counter.go 
b/server/plugin/quota/counter/counter.go
deleted file mode 100644
index 4812538..0000000
--- a/server/plugin/quota/counter/counter.go
+++ /dev/null
@@ -1,49 +0,0 @@
-// 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 counter
-
-import (
-       "github.com/apache/servicecomb-service-center/datasource/etcd/sd"
-)
-
-var counters = Counters{}
-
-type Counter interface {
-       OnCreate(t sd.Type, domainProject string)
-       OnDelete(t sd.Type, domainProject string)
-}
-
-type Counters []Counter
-
-func (cs Counters) OnCreate(t sd.Type, domainProject string) {
-       for _, c := range cs {
-               c.OnCreate(t, domainProject)
-       }
-}
-
-func (cs Counters) OnDelete(t sd.Type, domainProject string) {
-       for _, c := range cs {
-               c.OnDelete(t, domainProject)
-       }
-}
-
-func RegisterCounter(c Counter) {
-       counters = append(counters, c)
-}
-
-func GetCounters() Counters {
-       return counters
-}
diff --git a/server/plugin/quota/counter/event.go 
b/server/plugin/quota/counter/event.go
deleted file mode 100644
index 0af39a5..0000000
--- a/server/plugin/quota/counter/event.go
+++ /dev/null
@@ -1,109 +0,0 @@
-// 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 counter
-
-import (
-       "context"
-       "github.com/apache/servicecomb-service-center/datasource"
-       "github.com/apache/servicecomb-service-center/datasource/etcd/kv"
-       "github.com/apache/servicecomb-service-center/datasource/etcd/sd"
-       "github.com/apache/servicecomb-service-center/pkg/log"
-       "github.com/apache/servicecomb-service-center/pkg/registry"
-       "github.com/apache/servicecomb-service-center/pkg/util"
-       "github.com/apache/servicecomb-service-center/server/config"
-       "github.com/apache/servicecomb-service-center/server/core"
-)
-
-var (
-       SharedServiceIds util.ConcurrentMap
-)
-
-// ServiceIndexEventHandler counting the number of services
-// Deprecated: Use metrics instead.
-type ServiceIndexEventHandler struct {
-}
-
-func (h *ServiceIndexEventHandler) Type() sd.Type {
-       return kv.ServiceIndex
-}
-
-func (h *ServiceIndexEventHandler) OnEvent(evt sd.KvEvent) {
-       key := core.GetInfoFromSvcIndexKV(evt.KV.Key)
-       if core.IsGlobal(key) {
-               
SharedServiceIds.Put(key.Tenant+core.SPLIT+evt.KV.Value.(string), struct{}{})
-               return
-       }
-
-       switch evt.Type {
-       case registry.EVT_INIT, registry.EVT_CREATE:
-               GetCounters().OnCreate(h.Type(), key.Tenant)
-       case registry.EVT_DELETE:
-               GetCounters().OnDelete(h.Type(), key.Tenant)
-       default:
-       }
-}
-
-func NewServiceIndexEventHandler() *ServiceIndexEventHandler {
-       return &ServiceIndexEventHandler{}
-}
-
-// InstanceEventHandler counting the number of instances
-// Deprecated: Use metrics instead.
-type InstanceEventHandler struct {
-       SharedServiceIds map[string]struct{}
-}
-
-func (h *InstanceEventHandler) Type() sd.Type {
-       return kv.INSTANCE
-}
-
-func (h *InstanceEventHandler) OnEvent(evt sd.KvEvent) {
-       serviceID, _, domainProject := core.GetInfoFromInstKV(evt.KV.Key)
-       key := domainProject + core.SPLIT + serviceID
-       if _, ok := SharedServiceIds.Get(key); ok {
-               return
-       }
-
-       switch evt.Type {
-       case registry.EVT_INIT, registry.EVT_CREATE:
-               if domainProject == core.RegistryDomainProject {
-                       resp, err := 
datasource.Instance().GetService(context.Background(), 
&registry.GetServiceRequest{ServiceId: serviceID})
-                       if err != nil || resp.Service == nil {
-                               log.Errorf(err, "GetService[%s] failed", key)
-                               return
-                       }
-                       if 
core.IsGlobal(registry.MicroServiceToKey(domainProject, resp.Service)) {
-                               SharedServiceIds.Put(key, struct{}{})
-                               return
-                       }
-               }
-               GetCounters().OnCreate(h.Type(), domainProject)
-       case registry.EVT_DELETE:
-               GetCounters().OnDelete(h.Type(), domainProject)
-       }
-}
-
-func NewInstanceEventHandler() *InstanceEventHandler {
-       return &InstanceEventHandler{SharedServiceIds: 
make(map[string]struct{})}
-}
-
-func RegisterCounterListener(pluginName string) {
-       if pluginName != config.GetString("quota.kind", "buildin", 
config.WithStandby("quota_plugin")) {
-               return
-       }
-       sd.AddEventHandler(NewServiceIndexEventHandler())
-       sd.AddEventHandler(NewInstanceEventHandler())
-}
diff --git a/server/plugin/quota/counter/event_test.go 
b/server/plugin/quota/counter/event_test.go
deleted file mode 100644
index fc8f296..0000000
--- a/server/plugin/quota/counter/event_test.go
+++ /dev/null
@@ -1,263 +0,0 @@
-// 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 counter
-
-import (
-       "github.com/apache/servicecomb-service-center/datasource/etcd/kv"
-       "github.com/apache/servicecomb-service-center/datasource/etcd/sd"
-       "github.com/apache/servicecomb-service-center/pkg/registry"
-       "github.com/apache/servicecomb-service-center/server/config"
-       "github.com/apache/servicecomb-service-center/server/core"
-       "testing"
-)
-
-type mockCounter struct {
-       ServiceCount  int64
-       InstanceCount int64
-}
-
-func (c *mockCounter) OnCreate(t sd.Type, domainProject string) {
-       switch t {
-       case kv.ServiceIndex:
-               c.ServiceCount++
-       case kv.INSTANCE:
-               c.InstanceCount++
-       default:
-               panic("error")
-       }
-}
-
-func (c *mockCounter) OnDelete(t sd.Type, domainProject string) {
-       switch t {
-       case kv.ServiceIndex:
-               c.ServiceCount--
-       case kv.INSTANCE:
-               c.InstanceCount--
-       default:
-               panic("error")
-       }
-}
-
-func TestNewServiceIndexEventHandler(t *testing.T) {
-       config.Init()
-       core.RegisterGlobalServices()
-
-       var counter = mockCounter{}
-       RegisterCounter(&counter)
-       h := NewServiceIndexEventHandler()
-
-       cases := []sd.KvEvent{
-               {
-                       Type: registry.EVT_INIT,
-                       KV: &sd.KeyValue{
-                               Key: 
[]byte(core.GenerateServiceIndexKey(&registry.MicroServiceKey{
-                                       Tenant:      core.RegistryDomainProject,
-                                       Project:     "",
-                                       AppId:       core.RegistryAppID,
-                                       ServiceName: core.RegistryServiceName,
-                                       Version:     "e",
-                                       Environment: "f",
-                                       Alias:       "g",
-                               })),
-                               Value: "1",
-                       },
-               },
-               {
-                       Type: registry.EVT_UPDATE,
-                       KV: &sd.KeyValue{
-                               Key: 
[]byte(core.GenerateServiceIndexKey(&registry.MicroServiceKey{
-                                       Tenant:      core.RegistryDomainProject,
-                                       Project:     "",
-                                       AppId:       core.RegistryAppID,
-                                       ServiceName: core.RegistryServiceName,
-                                       Version:     "e",
-                                       Environment: "f",
-                                       Alias:       "g",
-                               })),
-                               Value: "1",
-                       },
-               },
-               {
-                       Type: registry.EVT_DELETE,
-                       KV: &sd.KeyValue{
-                               Key: 
[]byte(core.GenerateServiceIndexKey(&registry.MicroServiceKey{
-                                       Tenant:      core.RegistryDomainProject,
-                                       Project:     "",
-                                       AppId:       core.RegistryAppID,
-                                       ServiceName: core.RegistryServiceName,
-                                       Version:     "e",
-                                       Environment: "f",
-                                       Alias:       "g",
-                               })),
-                               Value: "1",
-                       },
-               },
-               {
-                       Type: registry.EVT_CREATE,
-                       KV: &sd.KeyValue{
-                               Key: 
[]byte(core.GenerateServiceIndexKey(&registry.MicroServiceKey{
-                                       Tenant:      core.RegistryDomainProject,
-                                       Project:     "",
-                                       AppId:       core.RegistryAppID,
-                                       ServiceName: core.RegistryServiceName,
-                                       Version:     "e",
-                                       Environment: "f",
-                                       Alias:       "g",
-                               })),
-                               Value: "1",
-                       },
-               },
-               {
-                       Type: registry.EVT_INIT,
-                       KV: &sd.KeyValue{
-                               Key: 
[]byte(core.GenerateServiceIndexKey(&registry.MicroServiceKey{
-                                       Tenant:      "a/b",
-                                       Project:     "",
-                                       AppId:       "c",
-                                       ServiceName: "d",
-                                       Version:     "e",
-                                       Environment: "f",
-                                       Alias:       "g",
-                               })),
-                               Value: "1",
-                       },
-               },
-               {
-                       Type: registry.EVT_DELETE,
-                       KV: &sd.KeyValue{
-                               Key: 
[]byte(core.GenerateServiceIndexKey(&registry.MicroServiceKey{
-                                       Tenant:      "a/b",
-                                       Project:     "",
-                                       AppId:       "c",
-                                       ServiceName: "d",
-                                       Version:     "e",
-                                       Environment: "f",
-                                       Alias:       "g",
-                               })),
-                               Value: "1",
-                       },
-               },
-               {
-                       Type: registry.EVT_UPDATE,
-                       KV: &sd.KeyValue{
-                               Key: 
[]byte(core.GenerateServiceIndexKey(&registry.MicroServiceKey{
-                                       Tenant:      "a/b",
-                                       Project:     "",
-                                       AppId:       "c",
-                                       ServiceName: "d",
-                                       Version:     "e",
-                                       Environment: "f",
-                                       Alias:       "g",
-                               })),
-                               Value: "1",
-                       },
-               },
-               {
-                       Type: registry.EVT_CREATE,
-                       KV: &sd.KeyValue{
-                               Key: 
[]byte(core.GenerateServiceIndexKey(&registry.MicroServiceKey{
-                                       Tenant:      "a/b",
-                                       Project:     "",
-                                       AppId:       "c",
-                                       ServiceName: "d",
-                                       Version:     "e",
-                                       Environment: "f",
-                                       Alias:       "g",
-                               })),
-                               Value: "1",
-                       },
-               },
-       }
-
-       for _, evt := range cases {
-               h.OnEvent(evt)
-       }
-       if counter.ServiceCount != 1 || counter.InstanceCount != 0 {
-               t.Fatal("TestNewServiceIndexEventHandler failed", counter)
-       }
-}
-
-func TestNewInstanceEventHandler(t *testing.T) {
-       var counter = mockCounter{}
-       RegisterCounter(&counter)
-       h := NewInstanceEventHandler()
-       SharedServiceIds.Put(core.RegistryDomainProject+core.SPLIT+"2", 
struct{}{})
-       cases := []sd.KvEvent{
-               {
-                       Type: registry.EVT_INIT,
-                       KV: &sd.KeyValue{
-                               Key:   
[]byte(core.GenerateInstanceKey(core.RegistryDomainProject, "2", "1")),
-                               Value: nil,
-                       },
-               },
-               {
-                       Type: registry.EVT_UPDATE,
-                       KV: &sd.KeyValue{
-                               Key:   
[]byte(core.GenerateInstanceKey(core.RegistryDomainProject, "2", "1")),
-                               Value: nil,
-                       },
-               },
-               {
-                       Type: registry.EVT_CREATE,
-                       KV: &sd.KeyValue{
-                               Key:   
[]byte(core.GenerateInstanceKey(core.RegistryDomainProject, "2", "1")),
-                               Value: nil,
-                       },
-               },
-               {
-                       Type: registry.EVT_DELETE,
-                       KV: &sd.KeyValue{
-                               Key:   
[]byte(core.GenerateInstanceKey(core.RegistryDomainProject, "2", "1")),
-                               Value: nil,
-                       },
-               },
-               {
-                       Type: registry.EVT_INIT,
-                       KV: &sd.KeyValue{
-                               Key:   []byte(core.GenerateInstanceKey("a/b", 
"1", "1")),
-                               Value: nil,
-                       },
-               },
-               {
-                       Type: registry.EVT_DELETE,
-                       KV: &sd.KeyValue{
-                               Key:   []byte(core.GenerateInstanceKey("a/b", 
"1", "1")),
-                               Value: nil,
-                       },
-               },
-               {
-                       Type: registry.EVT_UPDATE,
-                       KV: &sd.KeyValue{
-                               Key:   []byte(core.GenerateInstanceKey("a/b", 
"1", "1")),
-                               Value: nil,
-                       },
-               },
-               {
-                       Type: registry.EVT_CREATE,
-                       KV: &sd.KeyValue{
-                               Key:   []byte(core.GenerateInstanceKey("a/b", 
"1", "1")),
-                               Value: nil,
-                       },
-               },
-       }
-
-       for _, evt := range cases {
-               h.OnEvent(evt)
-       }
-       if counter.InstanceCount != 1 || counter.ServiceCount != 0 {
-               t.Fatal("TestNewServiceIndexEventHandler failed", counter)
-       }
-}
diff --git a/server/plugin/tracing/pzipkin/buildin.go 
b/server/plugin/tracing/pzipkin/buildin.go
index 624fecb..dca910e 100644
--- a/server/plugin/tracing/pzipkin/buildin.go
+++ b/server/plugin/tracing/pzipkin/buildin.go
@@ -120,8 +120,8 @@ func (zp *Zipkin) ClientBegin(operationName string, itf 
tracing.Request) tracing
                ); err != nil {
                        log.Errorf(err, "tracer inject request failed")
                }
-       case *tracing.RegistryRequest:
-               r := itf.(*tracing.RegistryRequest)
+       case *tracing.Operation:
+               r := itf.(*tracing.Operation)
                ctx := r.Ctx
 
                parentSpan, ok := 
ctx.Value(tracing.CtxTraceSpan).(opentracing.Span)
@@ -129,11 +129,11 @@ func (zp *Zipkin) ClientBegin(operationName string, itf 
tracing.Request) tracing
                        return nil
                }
 
-               u, _ := url.Parse(r.Endpoint + "/?" + 
r.Options.FormatURLParams())
+               u, _ := url.Parse(r.Endpoint + r.Options.URL())
 
                span = ZipkinTracer().StartSpan(operationName, 
opentracing.ChildOf(parentSpan.Context()))
                ext.SpanKindRPCClient.Set(span)
-               ext.HTTPMethod.Set(span, r.Options.Action.String())
+               ext.HTTPMethod.Set(span, r.Options.Method())
                ext.HTTPUrl.Set(span, u.String())
 
                span.SetTag("protocol", "gRPC")
diff --git a/server/plugin/tracing/pzipkin/buildin_test.go 
b/server/plugin/tracing/pzipkin/buildin_test.go
index ce5b501..4b1ae9d 100644
--- a/server/plugin/tracing/pzipkin/buildin_test.go
+++ b/server/plugin/tracing/pzipkin/buildin_test.go
@@ -19,15 +19,21 @@ package pzipkin
 import (
        "context"
        "github.com/apache/servicecomb-service-center/datasource/etcd/client"
+       
"github.com/apache/servicecomb-service-center/datasource/etcd/client/remote"
+       "github.com/apache/servicecomb-service-center/server/config"
        "github.com/apache/servicecomb-service-center/server/core"
        "github.com/apache/servicecomb-service-center/server/plugin/tracing"
+       "github.com/go-chassis/go-archaius"
        "net/http"
-       "os"
        "testing"
 )
 
+func init() {
+       config.Init()
+}
+
 func TestZipkin_XBegin(t *testing.T) {
-       os.Setenv("TRACING_COLLECTOR", "server")
+       archaius.Set("TRACING_COLLECTOR", "server")
        core.Instance.HostName, core.Instance.Endpoints = "x", []string{"x"}
        initTracer()
 
@@ -61,9 +67,9 @@ func TestZipkin_XBegin(t *testing.T) {
 
        zk.ClientEnd(span, 0, "")
 
-       span = zk.ClientBegin("x", &tracing.RegistryRequest{
+       span = zk.ClientBegin("x", &tracing.Operation{
                Ctx:      req.Context(),
-               Options:  client.OpGet(),
+               Options:  &remote.EtcdOptions{PluginOp: client.OpGet()},
                Endpoint: "x",
        })
        if span == nil {
diff --git a/server/plugin/tracing/pzipkin/common.go 
b/server/plugin/tracing/pzipkin/common.go
index f8ac3b1..007b050 100644
--- a/server/plugin/tracing/pzipkin/common.go
+++ b/server/plugin/tracing/pzipkin/common.go
@@ -20,8 +20,9 @@ package pzipkin
 import (
        "fmt"
        "github.com/apache/servicecomb-service-center/pkg/log"
+       "github.com/apache/servicecomb-service-center/pkg/metrics"
+       "github.com/apache/servicecomb-service-center/server/config"
        "github.com/apache/servicecomb-service-center/server/core"
-       "github.com/apache/servicecomb-service-center/server/metric"
        "github.com/opentracing/opentracing-go"
        zipkin "github.com/openzipkin/zipkin-go-opentracing"
        "os"
@@ -44,7 +45,7 @@ func initTracer() {
                log.Errorf(err, "new tracing collector failed, use the noop 
tracer")
                return
        }
-       ipPort := metric.InstanceName()
+       ipPort := metrics.InstanceName()
        recorder := zipkin.NewRecorder(collector, false, ipPort, 
strings.ToLower(core.Service.ServiceName))
        tracer, err := zipkin.NewTracer(recorder,
                zipkin.TraceID128Bit(true),
@@ -57,7 +58,7 @@ func initTracer() {
 }
 
 func newCollector() (collector zipkin.Collector, err error) {
-       ct := strings.TrimSpace(os.Getenv(collectorType))
+       ct := config.GetString("tracing.zipkin.collector.type", "", 
config.WithENV(collectorType))
        switch ct {
        case "server":
                sa := GetServerEndpoint()
@@ -83,7 +84,7 @@ func ZipkinTracer() opentracing.Tracer {
 }
 
 func GetFilePath(defName string) string {
-       path := os.Getenv(fileCollectorPath)
+       path := config.GetString("tracing.zipkin.collector.path", "", 
config.WithENV(fileCollectorPath))
        if len(path) == 0 {
                wd, _ := os.Getwd()
                return filepath.Join(wd, defName)
@@ -92,7 +93,7 @@ func GetFilePath(defName string) string {
 }
 
 func GetServerEndpoint() string {
-       sa := os.Getenv(serverCollectorAddr)
+       sa := config.GetString("tracing.zipkin.collector.endpoint", "", 
config.WithENV(serverCollectorAddr))
        if len(sa) == 0 {
                sa = "http://127.0.0.1:9411";
        }
@@ -100,7 +101,7 @@ func GetServerEndpoint() string {
 }
 
 func GetSamplerRate() float64 {
-       strRate := os.Getenv(samplerRate)
+       strRate := config.GetString("tracing.zipkin.sampler.rate", "", 
config.WithENV(samplerRate))
        rate, err := strconv.ParseFloat(strRate, 64)
        if rate <= 0 || err != nil {
                return defaultSamplerRate
diff --git a/server/plugin/tracing/pzipkin/common_test.go 
b/server/plugin/tracing/pzipkin/common_test.go
index fb005a0..09e9ed6 100644
--- a/server/plugin/tracing/pzipkin/common_test.go
+++ b/server/plugin/tracing/pzipkin/common_test.go
@@ -16,6 +16,7 @@
 package pzipkin
 
 import (
+       "github.com/go-chassis/go-archaius"
        "github.com/openzipkin/zipkin-go-opentracing"
        "os"
        "path/filepath"
@@ -28,7 +29,7 @@ func TestGetFilePath(t *testing.T) {
        if f != filepath.Join(wd, "a") {
                t.Fatalf("TestGetFilePath failed, %v", f)
        }
-       os.Setenv(fileCollectorPath, "trace.log")
+       archaius.Set(fileCollectorPath, "trace.log")
        f = GetFilePath("a")
        if f != "trace.log" {
                t.Fatalf("TestGetFilePath failed, %v", f)
@@ -40,12 +41,12 @@ func TestGetSamplerRate(t *testing.T) {
        if r != defaultSamplerRate {
                t.Fatalf("TestGetSamplerRate failed, %v", r)
        }
-       os.Setenv(samplerRate, "a")
+       archaius.Set(samplerRate, "a")
        r = GetSamplerRate()
        if r != defaultSamplerRate {
                t.Fatalf("TestGetSamplerRate failed, %v", r)
        }
-       os.Setenv(samplerRate, "0.1")
+       archaius.Set(samplerRate, "0.1")
        r = GetSamplerRate()
        if r != 0.1 {
                t.Fatalf("TestGetSamplerRate failed, %v", r)
@@ -53,12 +54,12 @@ func TestGetSamplerRate(t *testing.T) {
 }
 
 func TestNewCollector(t *testing.T) {
-       os.Setenv(collectorType, "")
+       archaius.Set(collectorType, "")
        tracer, err := newCollector()
        if err == nil {
                t.Fatalf("TestNewCollector failed")
        }
-       os.Setenv(collectorType, "server")
+       archaius.Set(collectorType, "server")
        tracer, err = newCollector()
        if err != nil {
                t.Fatalf("TestNewCollector failed")
@@ -67,7 +68,7 @@ func TestNewCollector(t *testing.T) {
        if !ok {
                t.Fatalf("TestNewCollector failed")
        }
-       os.Setenv(collectorType, "file")
+       archaius.Set(collectorType, "file")
        tracer, err = newCollector()
        if err != nil {
                t.Fatalf("TestNewCollector failed")
diff --git a/server/plugin/tracing/tracing.go b/server/plugin/tracing/tracing.go
index 284f311..86910d4 100644
--- a/server/plugin/tracing/tracing.go
+++ b/server/plugin/tracing/tracing.go
@@ -19,7 +19,6 @@ package tracing
 
 import (
        "context"
-       "github.com/apache/servicecomb-service-center/datasource/etcd/client"
        "github.com/apache/servicecomb-service-center/pkg/util"
        "github.com/apache/servicecomb-service-center/server/plugin"
 )
@@ -40,10 +39,15 @@ type Tracing interface {
        ClientEnd(span Span, code int, message string)
 }
 
-type RegistryRequest struct {
+type Options interface {
+       Method() string
+       URL() string
+}
+
+type Operation struct {
        Ctx      context.Context
        Endpoint string
-       Options  client.PluginOp
+       Options  Options
 }
 
 func Trace() Tracing {
diff --git a/server/resource/v4/auth_resource.go 
b/server/resource/v4/auth_resource.go
index baad398..9ff1e27 100644
--- a/server/resource/v4/auth_resource.go
+++ b/server/resource/v4/auth_resource.go
@@ -20,6 +20,7 @@ package v4
 import (
        "context"
        "encoding/json"
+       "github.com/apache/servicecomb-service-center/datasource"
        errorsEx "github.com/apache/servicecomb-service-center/pkg/errors"
        "github.com/apache/servicecomb-service-center/pkg/log"
        "github.com/apache/servicecomb-service-center/pkg/rbacframe"
@@ -69,7 +70,7 @@ func (r *AuthResource) CreateAccount(w http.ResponseWriter, 
req *http.Request) {
        }
        err = dao.CreateAccount(context.TODO(), a)
        if err != nil {
-               if err == dao.ErrDuplicated {
+               if err == datasource.ErrDuplicated {
                        controller.WriteError(w, scerror.ErrConflictAccount, "")
                        return
                }
diff --git a/server/metric/options.go b/server/rest/prometheus/prometheus.go
similarity index 79%
rename from server/metric/options.go
rename to server/rest/prometheus/prometheus.go
index 17cc97a..65ef0be 100644
--- a/server/metric/options.go
+++ b/server/rest/prometheus/prometheus.go
@@ -15,16 +15,13 @@
  * limitations under the License.
  */
 
-package metric
+package prometheus
 
 import (
-       "time"
+       "github.com/apache/servicecomb-service-center/server/rest"
+       "github.com/prometheus/client_golang/prometheus/promhttp"
 )
 
-//Options contains metrics configs
-type Options struct {
-       Interval     time.Duration
-       InstanceName string
-       // SysMetrics set
-       SysMetrics []string
+func init() {
+       rest.RegisterServerHandler("/metrics", promhttp.Handler())
 }
diff --git a/server/server.go b/server/server.go
index 8f13147..51cd458 100644
--- a/server/server.go
+++ b/server/server.go
@@ -22,13 +22,13 @@ import (
        "github.com/apache/servicecomb-service-center/datasource"
        "github.com/apache/servicecomb-service-center/pkg/gopool"
        "github.com/apache/servicecomb-service-center/pkg/log"
+       "github.com/apache/servicecomb-service-center/pkg/metrics"
        nf "github.com/apache/servicecomb-service-center/pkg/notify"
        "github.com/apache/servicecomb-service-center/pkg/signal"
        "github.com/apache/servicecomb-service-center/pkg/util"
        "github.com/apache/servicecomb-service-center/server/command"
        "github.com/apache/servicecomb-service-center/server/config"
        "github.com/apache/servicecomb-service-center/server/core"
-       "github.com/apache/servicecomb-service-center/server/metric"
        "github.com/apache/servicecomb-service-center/server/notify"
        "github.com/apache/servicecomb-service-center/server/plugin"
        
"github.com/apache/servicecomb-service-center/server/plugin/security/tlsconf"
@@ -132,7 +132,7 @@ func (s *ServiceCenterServer) initMetrics() {
                }
        }
 
-       if err := metric.Init(metric.Options{
+       if err := metrics.Init(metrics.Options{
                Interval:     interval,
                InstanceName: instance,
                SysMetrics: []string{
diff --git a/server/service/rbac/dao/account_dao.go 
b/server/service/rbac/dao/account_dao.go
index 24ae073..8624a13 100644
--- a/server/service/rbac/dao/account_dao.go
+++ b/server/service/rbac/dao/account_dao.go
@@ -20,64 +20,15 @@ package dao
 
 import (
        "context"
-       "encoding/json"
-       "errors"
-       "fmt"
        "github.com/apache/servicecomb-service-center/datasource"
-       "github.com/apache/servicecomb-service-center/datasource/etcd/client"
-       "github.com/apache/servicecomb-service-center/pkg/etcdsync"
        "github.com/apache/servicecomb-service-center/pkg/log"
        "github.com/apache/servicecomb-service-center/pkg/rbacframe"
-       "github.com/apache/servicecomb-service-center/pkg/util"
-       "github.com/apache/servicecomb-service-center/server/core"
-       stringutil "github.com/go-chassis/foundation/string"
-       "golang.org/x/crypto/bcrypt"
 )
 
-var ErrDuplicated = errors.New("account is duplicated")
-var ErrCanNotEdit = errors.New("account can not be edited")
-
 //CreateAccount save 2 kv
 //1. account info
 func CreateAccount(ctx context.Context, a *rbacframe.Account) error {
-       lock, err := etcdsync.Lock("/account-creating/"+a.Name, -1, false)
-       if err != nil {
-               return fmt.Errorf("account %s is creating", a.Name)
-       }
-       defer func() {
-               err := lock.Unlock()
-               if err != nil {
-                       log.Errorf(err, "can not release account lock")
-               }
-       }()
-       key := core.GenerateAccountKey(a.Name)
-       exist, err := datasource.Instance().AccountExist(ctx, a.Name)
-       if err != nil {
-               log.Errorf(err, "can not save account info")
-               return err
-       }
-       if exist {
-               return ErrDuplicated
-       }
-       hash, err := bcrypt.GenerateFromPassword([]byte(a.Password), 14)
-       if err != nil {
-               log.Errorf(err, "pwd hash failed")
-               return err
-       }
-       a.Password = stringutil.Bytes2str(hash)
-       a.ID = util.GenerateUUID()
-       value, err := json.Marshal(a)
-       if err != nil {
-               log.Errorf(err, "account info is invalid")
-               return err
-       }
-       err = client.PutBytes(ctx, key, value)
-       if err != nil {
-               log.Errorf(err, "can not save account info")
-               return err
-       }
-       log.Info("create new account: " + a.ID)
-       return nil
+       return datasource.Instance().CreateAccount(ctx, a)
 }
 
 func GetAccount(ctx context.Context, name string) (*rbacframe.Account, error) {
@@ -102,7 +53,7 @@ func EditAccount(ctx context.Context, a *rbacframe.Account) 
error {
                return err
        }
        if !exist {
-               return ErrCanNotEdit
+               return datasource.ErrCanNotEdit
        }
 
        err = datasource.Instance().UpdateAccount(ctx, a.Name, a)
diff --git a/server/service/rbac/rbac.go b/server/service/rbac/rbac.go
index 2987e5e..b4cacb4 100644
--- a/server/service/rbac/rbac.go
+++ b/server/service/rbac/rbac.go
@@ -21,6 +21,7 @@ import (
        "context"
        "crypto/rsa"
        "errors"
+       "github.com/apache/servicecomb-service-center/datasource"
        "github.com/apache/servicecomb-service-center/pkg/log"
        "github.com/apache/servicecomb-service-center/pkg/rbacframe"
        "github.com/apache/servicecomb-service-center/server/config"
@@ -128,7 +129,7 @@ func initFirstTime(admin string) {
                return
        }
        if err := dao.CreateAccount(context.Background(), a); err != nil {
-               if err == dao.ErrDuplicated {
+               if err == datasource.ErrDuplicated {
                        log.Info("rbac is enabled")
                        return
                }

Reply via email to