You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@servicecomb.apache.org by ti...@apache.org on 2020/11/17 00:10:08 UTC

[servicecomb-service-center] branch master updated: SCB-2094 Refactor metrics (#743)

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 <su...@qq.com>
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
 		}