Fix: Etcd metrics not correct (#1069)

* Fix: Etcd metrics not correct

* Add mongo metrics impl

* Upgrade CARI v0.5.0

* Upgrade Go-chassis

* Fix: UT failures
diff --git a/datasource/common.go b/datasource/common.go
index b732eb8..13b82cd 100644
--- a/datasource/common.go
+++ b/datasource/common.go
@@ -18,7 +18,11 @@
 package datasource
 
 const (
-	ServiceKeyPrefix  = "/cse-sr/ms/files"
-	InstanceKeyPrefix = "/cse-sr/inst/files"
-	SPLIT             = "/"
+	SPLIT                 = "/"
+	ServiceKeyPrefix      = "/cse-sr/ms/files"
+	InstanceKeyPrefix     = "/cse-sr/inst/files"
+	RegistryDomain        = "default"
+	RegistryProject       = "default"
+	RegistryDomainProject = "default/default"
+	RegistryAppID         = "default"
 )
diff --git a/datasource/datasource.go b/datasource/datasource.go
index 7909178..cc1efce 100644
--- a/datasource/datasource.go
+++ b/datasource/datasource.go
@@ -26,4 +26,5 @@
 	DependencyManager() DependencyManager
 	MetadataManager() MetadataManager
 	SCManager() SCManager
+	MetricsManager() MetricsManager
 }
diff --git a/datasource/etcd/etcd.go b/datasource/etcd/etcd.go
index 37fd951..ce6faa2 100644
--- a/datasource/etcd/etcd.go
+++ b/datasource/etcd/etcd.go
@@ -48,6 +48,7 @@
 	sysManager         datasource.SystemManager
 	depManager         datasource.DependencyManager
 	scManager          datasource.SCManager
+	metricsManager     datasource.MetricsManager
 }
 
 func (ds *DataSource) AccountLockManager() datasource.AccountLockManager {
@@ -78,6 +79,10 @@
 	return ds.scManager
 }
 
+func (ds *DataSource) MetricsManager() datasource.MetricsManager {
+	return ds.metricsManager
+}
+
 func NewDataSource(opts datasource.Options) (datasource.DataSource, error) {
 	// TODO: construct a reasonable DataSource instance
 	log.Warnf("data source enable etcd mode")
@@ -100,6 +105,7 @@
 	inst.sysManager = newSysManager()
 	inst.depManager = &DepManager{}
 	inst.scManager = &SCManager{}
+	inst.metricsManager = &MetricsManager{}
 	return inst, nil
 }
 
diff --git a/datasource/etcd/event/domain_event_handler.go b/datasource/etcd/event/domain_event_handler.go
deleted file mode 100644
index 8e1cce3..0000000
--- a/datasource/etcd/event/domain_event_handler.go
+++ /dev/null
@@ -1,48 +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 event
-
-import (
-	"github.com/go-chassis/cari/discovery"
-
-	"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/metrics"
-)
-
-// DomainEventHandler report domain & project total number
-type DomainEventHandler struct {
-}
-
-func (h *DomainEventHandler) Type() sd.Type {
-	return kv.DOMAIN
-}
-
-func (h *DomainEventHandler) OnEvent(evt sd.KvEvent) {
-	action := evt.Type
-	switch action {
-	case discovery.EVT_INIT, discovery.EVT_CREATE:
-		metrics.ReportDomains(1)
-	case discovery.EVT_DELETE:
-		metrics.ReportDomains(-1)
-	}
-}
-
-func NewDomainEventHandler() *DomainEventHandler {
-	return &DomainEventHandler{}
-}
diff --git a/datasource/etcd/event/event.go b/datasource/etcd/event/event.go
index 9b1e6c5..92c00fa 100644
--- a/datasource/etcd/event/event.go
+++ b/datasource/etcd/event/event.go
@@ -22,12 +22,10 @@
 )
 
 func Initialize() {
-	sd.AddEventHandler(NewDomainEventHandler())
 	sd.AddEventHandler(NewServiceEventHandler())
 	sd.AddEventHandler(NewInstanceEventHandler())
 	sd.AddEventHandler(NewRuleEventHandler())
 	sd.AddEventHandler(NewTagEventHandler())
 	sd.AddEventHandler(NewDependencyEventHandler())
 	sd.AddEventHandler(NewDependencyRuleEventHandler())
-	sd.AddEventHandler(NewSchemaSummaryEventHandler())
 }
diff --git a/datasource/etcd/event/instance_event_handler.go b/datasource/etcd/event/instance_event_handler.go
index b6dd461..ce7f9a1 100644
--- a/datasource/etcd/event/instance_event_handler.go
+++ b/datasource/etcd/event/instance_event_handler.go
@@ -20,9 +20,6 @@
 import (
 	"context"
 	"fmt"
-	"strings"
-
-	pb "github.com/go-chassis/cari/discovery"
 
 	"github.com/apache/servicecomb-service-center/datasource"
 	"github.com/apache/servicecomb-service-center/datasource/etcd/cache"
@@ -33,15 +30,12 @@
 	"github.com/apache/servicecomb-service-center/pkg/dump"
 	"github.com/apache/servicecomb-service-center/pkg/log"
 	"github.com/apache/servicecomb-service-center/pkg/util"
-	"github.com/apache/servicecomb-service-center/server/core"
 	"github.com/apache/servicecomb-service-center/server/event"
-	"github.com/apache/servicecomb-service-center/server/metrics"
 	"github.com/apache/servicecomb-service-center/server/syncernotify"
+	pb "github.com/go-chassis/cari/discovery"
 )
 
 const (
-	increaseOne = 1
-	decreaseOne = -1
 	msKeyPrefix = "/cse-sr/ms/files/"
 	sep         = "/"
 )
@@ -66,33 +60,16 @@
 		return
 	}
 	providerID, providerInstanceID, domainProject := path.GetInfoFromInstKV(evt.KV.Key)
-	idx := strings.Index(domainProject, "/")
-	domainName := domainProject[:idx]
-	projectName := domainProject[idx+1:]
-
 	ctx := util.WithGlobal(util.WithCacheOnly(context.Background()))
 
-	var count float64 = increaseOne
 	if action == pb.EVT_INIT {
-		metrics.ReportInstances(domainName, count)
-		ms, err := serviceUtil.GetService(ctx, domainProject, providerID)
-		if err != nil {
-			log.Warnf("caught [%s] instance[%s/%s] event, endpoints %v, get cached provider's file failed",
-				action, providerID, providerInstanceID, instance.Endpoints)
-			return
-		}
-		frameworkName, frameworkVersion := getFramework(ms)
-		metrics.ReportFramework(domainName, projectName, frameworkName, frameworkVersion, count)
 		return
 	}
 
-	if action == pb.EVT_DELETE {
-		count = decreaseOne
-		if !core.IsDefaultDomainProject(domainProject) {
-			projectName := domainProject[idx+1:]
-			serviceUtil.RemandInstanceQuota(
-				util.SetDomainProject(context.Background(), domainName, projectName))
-		}
+	if action == pb.EVT_DELETE && !datasource.IsDefaultDomainProject(domainProject) {
+		domain, project := path.SplitDomainProject(domainProject)
+		serviceUtil.RemandInstanceQuota(
+			util.SetDomainProject(context.Background(), domain, project))
 	}
 
 	// 查询服务版本信息
@@ -113,12 +90,6 @@
 		return
 	}
 
-	if action != pb.EVT_UPDATE {
-		frameworkName, frameworkVersion := getFramework(ms)
-		metrics.ReportInstances(domainName, count)
-		metrics.ReportFramework(domainName, projectName, frameworkName, frameworkVersion, count)
-	}
-
 	log.Infof("caught [%s] service[%s][%s/%s/%s/%s] instance[%s] event, endpoints %v",
 		action, providerID, ms.Environment, ms.AppId, ms.ServiceName, ms.Version,
 		providerInstanceID, instance.Endpoints)
diff --git a/datasource/etcd/event/schema_summary_event_handler.go b/datasource/etcd/event/schema_summary_event_handler.go
deleted file mode 100644
index f15db70..0000000
--- a/datasource/etcd/event/schema_summary_event_handler.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 event
-
-import (
-	"strings"
-
-	pb "github.com/go-chassis/cari/discovery"
-
-	"github.com/apache/servicecomb-service-center/datasource/etcd/kv"
-	"github.com/apache/servicecomb-service-center/datasource/etcd/path"
-	"github.com/apache/servicecomb-service-center/datasource/etcd/sd"
-	"github.com/apache/servicecomb-service-center/server/metrics"
-)
-
-// SchemaSummaryEventHandler report schema metrics
-type SchemaSummaryEventHandler struct {
-}
-
-func (h *SchemaSummaryEventHandler) Type() sd.Type {
-	return kv.SchemaSummary
-}
-
-func (h *SchemaSummaryEventHandler) OnEvent(evt sd.KvEvent) {
-	action := evt.Type
-	switch action {
-	case pb.EVT_INIT, pb.EVT_CREATE, pb.EVT_DELETE:
-		domainProject, _, _ := path.GetInfoFromSchemaSummaryKV(evt.KV.Key)
-		idx := strings.Index(domainProject, "/")
-		newDomain := domainProject[:idx]
-		if pb.EVT_DELETE == action {
-			metrics.ReportSchemas(newDomain, -1)
-		} else {
-			metrics.ReportSchemas(newDomain, 1)
-		}
-	default:
-	}
-}
-
-func NewSchemaSummaryEventHandler() *SchemaSummaryEventHandler {
-	return &SchemaSummaryEventHandler{}
-}
diff --git a/datasource/etcd/event/service_event_handler.go b/datasource/etcd/event/service_event_handler.go
index b4ee26b..cd9e479 100644
--- a/datasource/etcd/event/service_event_handler.go
+++ b/datasource/etcd/event/service_event_handler.go
@@ -19,9 +19,6 @@
 
 import (
 	"context"
-	"strings"
-
-	pb "github.com/go-chassis/cari/discovery"
 
 	"github.com/apache/servicecomb-service-center/datasource"
 	"github.com/apache/servicecomb-service-center/datasource/etcd/cache"
@@ -30,11 +27,10 @@
 	"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"
-	"github.com/apache/servicecomb-service-center/server/metrics"
+	pb "github.com/go-chassis/cari/discovery"
 )
 
 // ServiceEventHandler is the handler to handle:
-// 1. report service metrics
 // 2. save the new domain & project mapping
 // 3. reset the find instance cache
 type ServiceEventHandler struct {
@@ -51,22 +47,14 @@
 		return
 	}
 	_, domainProject := path.GetInfoFromSvcKV(evt.KV.Key)
-	fn, fv := getFramework(ms)
 
 	switch evt.Type {
 	case pb.EVT_INIT, pb.EVT_CREATE:
-		idx := strings.Index(domainProject, "/")
-		newDomain := domainProject[:idx]
-		newProject := domainProject[idx+1:]
+		newDomain, newProject := path.SplitDomainProject(domainProject)
 		err := serviceUtil.NewDomainProject(context.Background(), newDomain, newProject)
 		if err != nil {
 			log.Errorf(err, "new domain[%s] or project[%s] failed", newDomain, newProject)
 		}
-		metrics.ReportServices(newDomain, fn, fv, 1)
-	case pb.EVT_DELETE:
-		domainName := domainProject[:strings.Index(domainProject, "/")]
-		metrics.ReportServices(domainName, fn, fv, -1)
-	default:
 	}
 
 	if evt.Type == pb.EVT_INIT {
@@ -81,17 +69,6 @@
 	cache.FindInstances.Remove(providerKey)
 }
 
-func getFramework(ms *pb.MicroService) (string, string) {
-	if ms.Framework != nil && len(ms.Framework.Name) > 0 {
-		version := ms.Framework.Version
-		if len(ms.Framework.Version) == 0 {
-			version = "UNKNOWN"
-		}
-		return ms.Framework.Name, version
-	}
-	return "UNKNOWN", "UNKNOWN"
-}
-
 func NewServiceEventHandler() *ServiceEventHandler {
 	return &ServiceEventHandler{}
 }
diff --git a/datasource/etcd/kv/types.go b/datasource/etcd/kv/types.go
index fe88425..752c464 100644
--- a/datasource/etcd/kv/types.go
+++ b/datasource/etcd/kv/types.go
@@ -59,7 +59,7 @@
 			WithInitSize(1000).WithParser(value.InstanceParser).
 			WithDeferHandler(NewInstanceEventDeferHandler())))
 	DOMAIN = Store().MustInstall(NewAddOn("DOMAIN",
-		sd.Configure().WithPrefix(path.GetDomainRootKey()+path.SPLIT).
+		sd.Configure().WithPrefix(path.GenerateDomainKey("")).
 			WithInitSize(100).WithParser(value.StringParser)))
 	SCHEMA = Store().MustInstall(NewAddOn("SCHEMA",
 		sd.Configure().WithPrefix(path.GetServiceSchemaRootKey("")).
diff --git a/datasource/etcd/metrics.go b/datasource/etcd/metrics.go
new file mode 100644
index 0000000..2e8cccc
--- /dev/null
+++ b/datasource/etcd/metrics.go
@@ -0,0 +1,129 @@
+/*
+ * 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 etcd
+
+import (
+	"context"
+	"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/datasource/etcd/path"
+	"github.com/apache/servicecomb-service-center/pkg/log"
+	"github.com/go-chassis/cari/discovery"
+)
+
+type MetricsManager struct {
+}
+
+func (m *MetricsManager) Report(ctx context.Context, r datasource.MetricsReporter) error {
+	reportDomains(ctx, r)
+	reportServices(ctx, r)
+	reportSchemas(ctx, r)
+	return nil
+}
+
+func reportDomains(ctx context.Context, r datasource.MetricsReporter) {
+	key := path.GenerateDomainKey("")
+	domainsResp, err := kv.Store().Domain().Search(ctx,
+		client.WithCacheOnly(), client.WithCountOnly(),
+		client.WithStrKey(key),
+		client.WithPrefix())
+	if err != nil {
+		log.Error("query all domains failed", err)
+		return
+	}
+	r.DomainAdd(float64(domainsResp.Count))
+}
+
+func reportSchemas(ctx context.Context, r datasource.MetricsReporter) {
+	key := path.GetServiceSchemaSummaryRootKey("")
+	schemaKeysResp, err := kv.Store().SchemaSummary().Search(ctx,
+		client.WithCacheOnly(), client.WithKeyOnly(),
+		client.WithStrKey(key),
+		client.WithPrefix())
+	if err != nil {
+		log.Error("query all schemas failed", err)
+		return
+	}
+	for _, keyValue := range schemaKeysResp.Kvs {
+		domainProject, _, _ := path.GetInfoFromSchemaSummaryKV(keyValue.Key)
+		domain, project := path.SplitDomainProject(domainProject)
+		labels := datasource.MetricsLabels{
+			Domain:  domain,
+			Project: project,
+		}
+		r.SchemaAdd(1, labels)
+	}
+}
+
+func reportServices(ctx context.Context, r datasource.MetricsReporter) {
+	key := path.GetServiceRootKey("")
+	servicesResp, err := kv.Store().Service().Search(ctx,
+		client.WithCacheOnly(),
+		client.WithStrKey(key),
+		client.WithPrefix())
+	if err != nil {
+		log.Error("query all microservices failed", err)
+		return
+	}
+	for _, keyValue := range servicesResp.Kvs {
+		service := keyValue.Value.(*discovery.MicroService)
+		_, domainProject := path.GetInfoFromSvcKV(keyValue.Key)
+		if datasource.IsGlobal(discovery.MicroServiceToKey(domainProject, service)) {
+			continue
+		}
+		domain, project := path.SplitDomainProject(domainProject)
+		frameworkName, frameworkVersion := discovery.ToFrameworkLabel(service)
+		labels := datasource.MetricsLabels{
+			Domain:           domain,
+			Project:          project,
+			Framework:        frameworkName,
+			FrameworkVersion: frameworkVersion,
+		}
+		r.ServiceAdd(1, labels)
+
+		reportInstances(ctx, r, domainProject, service)
+	}
+}
+
+func reportInstances(ctx context.Context, r datasource.MetricsReporter, domainProject string, service *discovery.MicroService) {
+	instancesResp, err := kv.Store().Instance().Search(ctx,
+		client.WithCacheOnly(), client.WithCountOnly(),
+		client.WithStrKey(path.GenerateInstanceKey(domainProject, service.ServiceId, "")),
+		client.WithPrefix())
+	if err != nil {
+		log.Error(fmt.Sprintf("query microservice %s isntances failed", service.ServiceId), err)
+		return
+	}
+	if instancesResp.Count == 0 {
+		return
+	}
+	count := float64(instancesResp.Count)
+	domain, project := path.SplitDomainProject(domainProject)
+	frameworkName, frameworkVersion := discovery.ToFrameworkLabel(service)
+	labels := datasource.MetricsLabels{
+		Domain:           domain,
+		Project:          project,
+		Framework:        frameworkName,
+		FrameworkVersion: frameworkVersion,
+	}
+	r.FrameworkSet(labels)
+	r.InstanceAdd(count, labels)
+}
diff --git a/datasource/etcd/ms.go b/datasource/etcd/ms.go
index 11298a7..93f2c12 100644
--- a/datasource/etcd/ms.go
+++ b/datasource/etcd/ms.go
@@ -353,7 +353,7 @@
 }
 
 func (ds *MetadataManager) filterServices(domainProject string, request *pb.GetServicesInfoRequest, service *pb.MicroService) bool {
-	if !request.WithShared && core.IsGlobal(pb.MicroServiceToKey(domainProject, service)) {
+	if !request.WithShared && datasource.IsGlobal(pb.MicroServiceToKey(domainProject, service)) {
 		return false
 	}
 	if len(request.Environment) > 0 && request.Environment != service.Environment {
@@ -409,7 +409,7 @@
 	appMap := make(map[string]struct{}, l)
 	for _, keyValue := range resp.Kvs {
 		key := path.GetInfoFromSvcIndexKV(keyValue.Key)
-		if !request.WithShared && core.IsGlobal(key) {
+		if !request.WithShared && datasource.IsGlobal(key) {
 			continue
 		}
 		if _, ok := appMap[key.AppId]; ok {
@@ -927,7 +927,7 @@
 		}, err
 	}
 
-	if core.IsGlobal(provider) {
+	if datasource.IsGlobal(provider) {
 		return ds.findSharedServiceInstance(ctx, request, provider, rev)
 	}
 	return ds.findInstance(ctx, request, provider, rev)
diff --git a/datasource/etcd/path/key_convertor.go b/datasource/etcd/path/key_convertor.go
index 1a652d0..774a6cb 100644
--- a/datasource/etcd/path/key_convertor.go
+++ b/datasource/etcd/path/key_convertor.go
@@ -21,9 +21,8 @@
 	"fmt"
 	"strings"
 
-	"github.com/go-chassis/cari/discovery"
-
 	"github.com/apache/servicecomb-service-center/pkg/util"
+	"github.com/go-chassis/cari/discovery"
 )
 
 func ToResponse(key []byte) (keys []string) {
@@ -169,3 +168,9 @@
 		Version:     keys[l-1],
 	}
 }
+
+func SplitDomainProject(domainProject string) (string, string) {
+	domain := domainProject[:strings.Index(domainProject, SPLIT)]
+	project := domainProject[strings.Index(domainProject, SPLIT)+1:]
+	return domain, project
+}
diff --git a/datasource/etcd/path/key_generator.go b/datasource/etcd/path/key_generator.go
index 228f808..d95563c 100644
--- a/datasource/etcd/path/key_generator.go
+++ b/datasource/etcd/path/key_generator.go
@@ -53,11 +53,11 @@
 	return SPLIT + RegistryRootKey
 }
 
-func GenerateRBACAccountKey(name string) string {
+func GenerateDomainKey(domain string) string {
 	return util.StringJoin([]string{
 		GetRootKey(),
-		"accounts",
-		name,
+		RegistryDomainKey,
+		domain,
 	}, SPLIT)
 }
 
@@ -69,6 +69,20 @@
 	}, SPLIT)
 }
 
+func GenerateProjectKey(domain, project string) string {
+	return util.StringJoin([]string{
+		GetProjectRootKey(domain),
+		project,
+	}, SPLIT)
+}
+
+func GenerateRBACAccountKey(name string) string {
+	return util.StringJoin([]string{
+		GetRootKey(),
+		"accounts",
+		name,
+	}, SPLIT)
+}
 func GenerateRBACRoleKey(name string) string {
 	return util.StringJoin([]string{
 		GetRootKey(),
@@ -90,19 +104,6 @@
 		role,
 	}, SPLIT)
 }
-func GenerateETCDProjectKey(domain, project string) string {
-	return util.StringJoin([]string{
-		GetProjectRootKey(domain),
-		project,
-	}, SPLIT)
-}
-
-func GenerateETCDDomainKey(domain string) string {
-	return util.StringJoin([]string{
-		GetDomainRootKey(),
-		domain,
-	}, SPLIT)
-}
 
 func GetServiceRootKey(domainProject string) string {
 	return util.StringJoin([]string{
@@ -353,19 +354,6 @@
 	}, SPLIT)
 }
 
-func GetDomainRootKey() string {
-	return util.StringJoin([]string{
-		GetRootKey(),
-		RegistryDomainKey,
-	}, SPLIT)
-}
-
-func GenerateDomainKey(domain string) string {
-	return util.StringJoin([]string{
-		GetDomainRootKey(),
-		domain,
-	}, SPLIT)
-}
 func GenerateAccountKey(name string) string {
 	return util.StringJoin([]string{
 		GetRootKey(),
@@ -408,10 +396,3 @@
 		domain,
 	}, SPLIT)
 }
-
-func GenerateProjectKey(domain, project string) string {
-	return util.StringJoin([]string{
-		GetProjectRootKey(domain),
-		project,
-	}, SPLIT)
-}
diff --git a/datasource/etcd/path/key_generator_test.go b/datasource/etcd/path/key_generator_test.go
index 76a8ea3..2614ae1 100644
--- a/datasource/etcd/path/key_generator_test.go
+++ b/datasource/etcd/path/key_generator_test.go
@@ -31,11 +31,11 @@
 }
 
 func TestGenerateETCDProjectKey(t *testing.T) {
-	assert.Equal(t, "/cse-sr/projects/domain/project", path.GenerateETCDProjectKey("domain", "project"))
+	assert.Equal(t, "/cse-sr/projects/domain/project", path.GenerateProjectKey("domain", "project"))
 }
 
 func TestGenerateETCDDomainKey(t *testing.T) {
-	assert.Equal(t, "/cse-sr/domains/domain", path.GenerateETCDDomainKey("domain"))
+	assert.Equal(t, "/cse-sr/domains/domain", path.GenerateDomainKey("domain"))
 }
 
 func TestGenerateAccountKey(t *testing.T) {
diff --git a/datasource/etcd/sd/k8s/adaptor/convertor.go b/datasource/etcd/sd/k8s/adaptor/convertor.go
index 2f58a58..4bd2c8b 100644
--- a/datasource/etcd/sd/k8s/adaptor/convertor.go
+++ b/datasource/etcd/sd/k8s/adaptor/convertor.go
@@ -99,7 +99,7 @@
 		Version:     getLabel(svc.Labels, LabelVersion, pb.VERSION),
 		Level:       "BACK",
 		Status:      pb.MS_UP,
-		Framework: &pb.FrameWorkProperty{
+		Framework: &pb.FrameWork{
 			Name: Name,
 		},
 		RegisterBy: pb.REGISTERBY_PLATFORM,
diff --git a/datasource/etcd/util/domain_util.go b/datasource/etcd/util/domain_util.go
index 5a5efb9..525f6ca 100644
--- a/datasource/etcd/util/domain_util.go
+++ b/datasource/etcd/util/domain_util.go
@@ -32,7 +32,7 @@
 
 func GetAllDomainRawData(ctx context.Context) ([]*sd.KeyValue, error) {
 	opts := append(FromContext(ctx),
-		client.WithStrKey(path.GenerateETCDDomainKey("")),
+		client.WithStrKey(path.GenerateDomainKey("")),
 		client.WithPrefix())
 	rsp, err := kv.Store().Domain().Search(ctx, opts...)
 	if err != nil {
@@ -67,7 +67,7 @@
 
 func AddDomain(ctx context.Context, domain string) (bool, error) {
 	ok, err := client.Instance().PutNoOverride(ctx,
-		client.WithStrKey(path.GenerateETCDDomainKey(domain)))
+		client.WithStrKey(path.GenerateDomainKey(domain)))
 	if err != nil {
 		return false, err
 	}
@@ -76,7 +76,7 @@
 
 func DomainExist(ctx context.Context, domain string) (bool, error) {
 	opts := append(FromContext(ctx),
-		client.WithStrKey(path.GenerateETCDDomainKey(domain)),
+		client.WithStrKey(path.GenerateDomainKey(domain)),
 		client.WithCountOnly())
 	rsp, err := kv.Store().Domain().Search(ctx, opts...)
 	if err != nil {
@@ -87,7 +87,7 @@
 
 func AddProject(ctx context.Context, domain, project string) (bool, error) {
 	ok, err := client.Instance().PutNoOverride(ctx,
-		client.WithStrKey(path.GenerateETCDProjectKey(domain, project)))
+		client.WithStrKey(path.GenerateProjectKey(domain, project)))
 	if err != nil {
 		return ok, err
 	}
@@ -96,7 +96,7 @@
 
 func ProjectExist(ctx context.Context, domain, project string) (bool, error) {
 	opts := append(FromContext(ctx),
-		client.WithStrKey(path.GenerateETCDProjectKey(domain, project)),
+		client.WithStrKey(path.GenerateProjectKey(domain, project)),
 		client.WithCountOnly())
 	rsp, err := kv.Store().Project().Search(ctx, opts...)
 	if err != nil {
diff --git a/datasource/etcd/util/rule_util.go b/datasource/etcd/util/rule_util.go
index 6588820..8ebff79 100644
--- a/datasource/etcd/util/rule_util.go
+++ b/datasource/etcd/util/rule_util.go
@@ -34,7 +34,6 @@
 	"github.com/apache/servicecomb-service-center/datasource/etcd/path"
 	"github.com/apache/servicecomb-service-center/pkg/log"
 	"github.com/apache/servicecomb-service-center/pkg/util"
-	apt "github.com/apache/servicecomb-service-center/server/core"
 )
 
 type RuleFilter struct {
@@ -164,7 +163,7 @@
 		}
 	}
 
-	if !apt.IsGlobal(discovery.MicroServiceToKey(util.ParseTargetDomainProject(ctx), providerService)) &&
+	if !datasource.IsGlobal(discovery.MicroServiceToKey(util.ParseTargetDomainProject(ctx), providerService)) &&
 		providerService.Environment != consumerService.Environment {
 		return fmt.Errorf("not allow across environment access")
 	}
diff --git a/datasource/manager.go b/datasource/manager.go
index 9cd2f23..abfdf07 100644
--- a/datasource/manager.go
+++ b/datasource/manager.go
@@ -87,3 +87,6 @@
 func GetDependencyManager() DependencyManager {
 	return dataSourceInst.DependencyManager()
 }
+func GetMetricsManager() MetricsManager {
+	return dataSourceInst.MetricsManager()
+}
diff --git a/datasource/metrics.go b/datasource/metrics.go
new file mode 100644
index 0000000..914d432
--- /dev/null
+++ b/datasource/metrics.go
@@ -0,0 +1,39 @@
+/*
+ * 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 "context"
+
+type MetricsLabels struct {
+	Domain           string `json:"domain,omitempty"`
+	Project          string `json:"project,omitempty"`
+	Framework        string `json:"framework,omitempty"`
+	FrameworkVersion string `json:"frameworkVersion,omitempty"`
+}
+
+type MetricsReporter interface {
+	DomainAdd(delta float64)
+	ServiceAdd(delta float64, labels MetricsLabels)
+	InstanceAdd(delta float64, labels MetricsLabels)
+	SchemaAdd(delta float64, labels MetricsLabels)
+	FrameworkSet(labels MetricsLabels)
+}
+
+type MetricsManager interface {
+	Report(ctx context.Context, r MetricsReporter) error
+}
diff --git a/datasource/mongo/client/dao/domain.go b/datasource/mongo/client/dao/domain.go
index 6e3cd1f..20cda4b 100644
--- a/datasource/mongo/client/dao/domain.go
+++ b/datasource/mongo/client/dao/domain.go
@@ -23,6 +23,7 @@
 
 	"github.com/apache/servicecomb-service-center/datasource/mongo/client"
 	"github.com/apache/servicecomb-service-center/datasource/mongo/client/model"
+	mutil "github.com/apache/servicecomb-service-center/datasource/mongo/util"
 	"github.com/apache/servicecomb-service-center/pkg/log"
 )
 
@@ -40,3 +41,7 @@
 func ExistDomain(ctx context.Context, filter interface{}) (bool, error) {
 	return client.GetMongoClient().DocExist(ctx, model.CollectionDomain, filter)
 }
+
+func CountDomain(ctx context.Context) (int64, error) {
+	return client.GetMongoClient().Count(ctx, model.CollectionDomain, mutil.NewFilter())
+}
diff --git a/datasource/mongo/client/dao/schema.go b/datasource/mongo/client/dao/schema.go
index c7d41e8..6cf10ea 100644
--- a/datasource/mongo/client/dao/schema.go
+++ b/datasource/mongo/client/dao/schema.go
@@ -80,3 +80,8 @@
 	}
 	return len(s.SchemaSummary) != 0, nil
 }
+
+func CountSchema(ctx context.Context, serviceID string) (int64, error) {
+	filter := mutil.NewBasicFilter(ctx, mutil.ServiceID(serviceID))
+	return client.Count(ctx, model.CollectionSchema, filter)
+}
diff --git a/datasource/mongo/event/domain_event_handler.go b/datasource/mongo/event/domain_event_handler.go
deleted file mode 100644
index c3311ce..0000000
--- a/datasource/mongo/event/domain_event_handler.go
+++ /dev/null
@@ -1,48 +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 event
-
-import (
-	"github.com/go-chassis/cari/discovery"
-
-	"github.com/apache/servicecomb-service-center/datasource/mongo/client/model"
-	"github.com/apache/servicecomb-service-center/datasource/mongo/sd"
-	"github.com/apache/servicecomb-service-center/server/metrics"
-)
-
-// DomainEventHandler report domain & project total number
-type DomainEventHandler struct {
-}
-
-func NewDomainEventHandler() *DomainEventHandler {
-	return &DomainEventHandler{}
-}
-
-func (h *DomainEventHandler) Type() string {
-	return model.ColumnDomain
-}
-
-func (h *DomainEventHandler) OnEvent(evt sd.MongoEvent) {
-	action := evt.Type
-	switch action {
-	case discovery.EVT_INIT, discovery.EVT_CREATE:
-		metrics.ReportDomains(increaseOne)
-	case discovery.EVT_DELETE:
-		metrics.ReportDomains(decreaseOne)
-	}
-}
diff --git a/datasource/mongo/event/event.go b/datasource/mongo/event/event.go
index 8889e84..3d77b38 100644
--- a/datasource/mongo/event/event.go
+++ b/datasource/mongo/event/event.go
@@ -22,16 +22,9 @@
 	"github.com/apache/servicecomb-service-center/pkg/log"
 )
 
-const (
-	increaseOne = 1
-	decreaseOne = -1
-)
-
 func init() {
 	log.Info("event init")
 	instanceEventHandler := NewInstanceEventHandler()
 	sd.EventProxy(instanceEventHandler.Type()).AddHandleFunc(instanceEventHandler.OnEvent)
 	sd.AddEventHandler(NewServiceEventHandler())
-	sd.AddEventHandler(NewSchemaSummaryEventHandler())
-	sd.AddEventHandler(NewDomainEventHandler())
 }
diff --git a/datasource/mongo/event/instance_event_handler.go b/datasource/mongo/event/instance_event_handler.go
index 908e251..6e2ceb1 100644
--- a/datasource/mongo/event/instance_event_handler.go
+++ b/datasource/mongo/event/instance_event_handler.go
@@ -35,7 +35,6 @@
 	simple "github.com/apache/servicecomb-service-center/pkg/time"
 	"github.com/apache/servicecomb-service-center/pkg/util"
 	"github.com/apache/servicecomb-service-center/server/event"
-	"github.com/apache/servicecomb-service-center/server/metrics"
 	"github.com/apache/servicecomb-service-center/server/syncernotify"
 )
 
@@ -72,16 +71,8 @@
 		return
 	}
 	microService := res.Service
-	switch action {
-	case discovery.EVT_INIT:
-		metrics.ReportInstances(instance.Domain, increaseOne)
-		frameworkName, frameworkVersion := getFramework(microService)
-		metrics.ReportFramework(instance.Domain, instance.Project, frameworkName, frameworkVersion, increaseOne)
+	if action == discovery.EVT_INIT {
 		return
-	case discovery.EVT_CREATE:
-		metrics.ReportInstances(instance.Domain, increaseOne)
-	case discovery.EVT_DELETE:
-		metrics.ReportInstances(instance.Domain, decreaseOne)
 	}
 	if !syncernotify.GetSyncerNotifyCenter().Closed() {
 		NotifySyncerInstanceEvent(evt, microService)
diff --git a/datasource/mongo/event/schema_summary_event_handler.go b/datasource/mongo/event/schema_summary_event_handler.go
deleted file mode 100644
index ad79856..0000000
--- a/datasource/mongo/event/schema_summary_event_handler.go
+++ /dev/null
@@ -1,55 +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 event
-
-import (
-	pb "github.com/go-chassis/cari/discovery"
-
-	"github.com/apache/servicecomb-service-center/datasource"
-	"github.com/apache/servicecomb-service-center/datasource/mongo/client/model"
-	"github.com/apache/servicecomb-service-center/datasource/mongo/sd"
-	"github.com/apache/servicecomb-service-center/pkg/log"
-	"github.com/apache/servicecomb-service-center/server/metrics"
-)
-
-type SchemaSummaryEventHandler struct {
-}
-
-func NewSchemaSummaryEventHandler() *SchemaSummaryEventHandler {
-	return &SchemaSummaryEventHandler{}
-}
-
-func (h *SchemaSummaryEventHandler) Type() string {
-	return model.ColumnSchema
-}
-
-func (h *SchemaSummaryEventHandler) OnEvent(evt sd.MongoEvent) {
-	schema, ok := evt.Value.(model.Schema)
-	if !ok {
-		log.Error("failed to assert schema", datasource.ErrAssertFail)
-		return
-	}
-	action := evt.Type
-	switch action {
-	case pb.EVT_INIT, pb.EVT_CREATE:
-		metrics.ReportSchemas(schema.Domain, increaseOne)
-	case pb.EVT_DELETE:
-		metrics.ReportSchemas(schema.Domain, decreaseOne)
-	default:
-	}
-}
diff --git a/datasource/mongo/event/service_event_handler.go b/datasource/mongo/event/service_event_handler.go
index 6e32136..5c7b196 100644
--- a/datasource/mongo/event/service_event_handler.go
+++ b/datasource/mongo/event/service_event_handler.go
@@ -29,7 +29,6 @@
 	"github.com/apache/servicecomb-service-center/datasource/mongo/sd"
 	"github.com/apache/servicecomb-service-center/datasource/mongo/util"
 	"github.com/apache/servicecomb-service-center/pkg/log"
-	"github.com/apache/servicecomb-service-center/server/metrics"
 )
 
 type ServiceEventHandler struct {
@@ -48,7 +47,6 @@
 		log.Error("failed to assert service", datasource.ErrAssertFail)
 		return
 	}
-	fn, fv := getFramework(ms.Service)
 	switch evt.Type {
 	case pb.EVT_INIT, pb.EVT_CREATE:
 		ctx := context.Background()
@@ -60,9 +58,6 @@
 		if err != nil {
 			log.Error(fmt.Sprintf("new project %s failed", ms.Project), err)
 		}
-		metrics.ReportServices(ms.Domain, fn, fv, increaseOne)
-	case pb.EVT_DELETE:
-		metrics.ReportServices(ms.Domain, fn, fv, decreaseOne)
 	default:
 	}
 	if evt.Type == pb.EVT_INIT {
@@ -73,17 +68,6 @@
 		evt.Type, ms.Service.ServiceId, ms.Service.Environment, ms.Service.AppId, ms.Service.ServiceName, ms.Service.Version)
 }
 
-func getFramework(ms *pb.MicroService) (string, string) {
-	if ms.Framework != nil && len(ms.Framework.Name) > 0 {
-		version := ms.Framework.Version
-		if len(ms.Framework.Version) == 0 {
-			version = "UNKNOWN"
-		}
-		return ms.Framework.Name, version
-	}
-	return "UNKNOWN", "UNKNOWN"
-}
-
 func newDomain(ctx context.Context, domain string) error {
 	filter := util.NewFilter(util.Domain(domain))
 	exist, err := dao.ExistDomain(ctx, filter)
diff --git a/datasource/mongo/metrics.go b/datasource/mongo/metrics.go
new file mode 100644
index 0000000..aa394ab
--- /dev/null
+++ b/datasource/mongo/metrics.go
@@ -0,0 +1,113 @@
+/*
+ * 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 mongo
+
+import (
+	"context"
+	"fmt"
+
+	"github.com/apache/servicecomb-service-center/datasource"
+	"github.com/apache/servicecomb-service-center/datasource/mongo/client/dao"
+	"github.com/apache/servicecomb-service-center/datasource/mongo/client/model"
+	mutil "github.com/apache/servicecomb-service-center/datasource/mongo/util"
+	"github.com/apache/servicecomb-service-center/pkg/log"
+	"github.com/apache/servicecomb-service-center/pkg/util"
+	"github.com/go-chassis/cari/discovery"
+)
+
+var globalServiceNames []string
+
+func init() {
+	for name := range datasource.GlobalServiceNames {
+		globalServiceNames = append(globalServiceNames, name)
+	}
+}
+
+type MetricsManager struct {
+}
+
+func (m *MetricsManager) Report(ctx context.Context, r datasource.MetricsReporter) error {
+	reportDomains(ctx, r)
+	reportServices(ctx, r)
+	return nil
+}
+
+func reportDomains(ctx context.Context, r datasource.MetricsReporter) {
+	count, err := dao.CountDomain(ctx)
+	if err != nil {
+		log.Error("count domains failed", err)
+		return
+	}
+	r.DomainAdd(float64(count))
+}
+
+func reportServices(ctx context.Context, r datasource.MetricsReporter) {
+	services, err := dao.GetServices(ctx, mutil.NewFilter())
+	if err != nil {
+		log.Error("query all services failed", err)
+		return
+	}
+	for _, service := range services {
+		key := discovery.MicroServiceToKey(service.Domain+datasource.SPLIT+service.Project, service.Service)
+		if datasource.IsGlobal(key) {
+			continue
+		}
+
+		frameworkName, frameworkVersion := discovery.ToFrameworkLabel(service.Service)
+		labels := datasource.MetricsLabels{
+			Domain:           service.Domain,
+			Project:          service.Project,
+			Framework:        frameworkName,
+			FrameworkVersion: frameworkVersion,
+		}
+		r.ServiceAdd(1, labels)
+		r.FrameworkSet(labels)
+
+		reportInstances(ctx, r, service)
+		reportSchemas(ctx, r, service)
+	}
+}
+
+func reportInstances(ctx context.Context, r datasource.MetricsReporter, service *model.Service) {
+	serviceID := service.Service.ServiceId
+	count, err := dao.CountInstance(ctx, mutil.NewFilter(mutil.InstanceServiceID(serviceID)))
+	if err != nil {
+		log.Error(fmt.Sprintf("count service %s instance failed", serviceID), err)
+		return
+	}
+	frameworkName, frameworkVersion := discovery.ToFrameworkLabel(service.Service)
+	r.InstanceAdd(float64(count), datasource.MetricsLabels{
+		Domain:           service.Domain,
+		Project:          service.Project,
+		Framework:        frameworkName,
+		FrameworkVersion: frameworkVersion,
+	})
+}
+
+func reportSchemas(ctx context.Context, r datasource.MetricsReporter, service *model.Service) {
+	serviceID := service.Service.ServiceId
+	count, err := dao.CountSchema(util.SetDomainProject(ctx, service.Domain, service.Project), serviceID)
+	if err != nil {
+		log.Error(fmt.Sprintf("count service %s schema failed", serviceID), err)
+		return
+	}
+	r.SchemaAdd(float64(count), datasource.MetricsLabels{
+		Domain:  service.Domain,
+		Project: service.Project,
+	})
+}
diff --git a/datasource/mongo/mongo.go b/datasource/mongo/mongo.go
index 311eb19..38d03c6 100644
--- a/datasource/mongo/mongo.go
+++ b/datasource/mongo/mongo.go
@@ -44,6 +44,7 @@
 	sysManager         datasource.SystemManager
 	depManager         datasource.DependencyManager
 	scManager          datasource.SCManager
+	metricsManager     datasource.MetricsManager
 }
 
 func (ds *DataSource) AccountLockManager() datasource.AccountLockManager {
@@ -74,6 +75,10 @@
 	return ds.scManager
 }
 
+func (ds *DataSource) MetricsManager() datasource.MetricsManager {
+	return ds.metricsManager
+}
+
 func NewDataSource(opts datasource.Options) (datasource.DataSource, error) {
 	// TODO: construct a reasonable DataSource instance
 	inst := &DataSource{}
@@ -88,6 +93,7 @@
 	inst.metadataManager = &MetadataManager{SchemaEditable: opts.SchemaEditable, InstanceTTL: opts.InstanceTTL}
 	inst.accountManager = &AccountManager{}
 	inst.accountLockManager = NewAccountLockManager(opts.ReleaseAccountAfter)
+	inst.metricsManager = &MetricsManager{}
 	return inst, nil
 }
 
diff --git a/datasource/mongo/ms.go b/datasource/mongo/ms.go
index ede7578..235452b 100644
--- a/datasource/mongo/ms.go
+++ b/datasource/mongo/ms.go
@@ -189,7 +189,7 @@
 	apps := make([]string, 0, l)
 	hash := make(map[string]struct{}, l)
 	for _, svc := range services {
-		if !request.WithShared && apt.IsGlobal(discovery.MicroServiceToKey(util.ParseDomainProject(ctx), svc)) {
+		if !request.WithShared && datasource.IsGlobal(discovery.MicroServiceToKey(util.ParseDomainProject(ctx), svc)) {
 			continue
 		}
 		if _, ok := hash[svc.AppId]; ok {
@@ -501,7 +501,7 @@
 	allServiceDetails := make([]*discovery.ServiceDetail, 0, len(services))
 	domainProject := util.ParseDomainProject(ctx)
 	for _, mgSvc := range services {
-		if !request.WithShared && apt.IsGlobal(discovery.MicroServiceToKey(domainProject, mgSvc.Service)) {
+		if !request.WithShared && datasource.IsGlobal(discovery.MicroServiceToKey(domainProject, mgSvc.Service)) {
 			continue
 		}
 
@@ -1826,7 +1826,7 @@
 		}, err
 	}
 
-	if apt.IsGlobal(provider) {
+	if datasource.IsGlobal(provider) {
 		return ds.findSharedServiceInstance(ctx, request, provider, rev)
 	}
 
@@ -2738,7 +2738,7 @@
 			return fmt.Errorf("not allow across app access")
 		}
 	}
-	if !apt.IsGlobal(discovery.MicroServiceToKey(util.ParseTargetDomainProject(ctx), providerService.Service)) &&
+	if !datasource.IsGlobal(discovery.MicroServiceToKey(util.ParseTargetDomainProject(ctx), providerService.Service)) &&
 		providerService.Service.Environment != consumerService.Service.Environment {
 		return fmt.Errorf("not allow across environment access")
 	}
diff --git a/datasource/mongo/util/db.go b/datasource/mongo/util/db.go
index f58cc99..c5c4c8f 100644
--- a/datasource/mongo/util/db.go
+++ b/datasource/mongo/util/db.go
@@ -127,7 +127,7 @@
 	}
 }
 
-func NewFilter(options ...func(filter bson.M)) bson.M {
+func NewFilter(options ...Option) bson.M {
 	filter := bson.M{}
 	for _, option := range options {
 		option(filter)
diff --git a/datasource/ms_util.go b/datasource/ms_util.go
index 769e544..16735e4 100644
--- a/datasource/ms_util.go
+++ b/datasource/ms_util.go
@@ -19,10 +19,11 @@
 
 import (
 	"github.com/apache/servicecomb-service-center/pkg/util"
-	"github.com/apache/servicecomb-service-center/server/core"
 	"github.com/go-chassis/cari/discovery"
 )
 
+var GlobalServiceNames = make(map[string]struct{})
+
 type GetInstanceCountByDomainResponse struct {
 	Err           error
 	CountByDomain int64
@@ -50,7 +51,7 @@
 	svcWithNonVersion := make(map[string]struct{}, l)
 	svcIDToNonVerKey := make(map[string]string, l)
 	for index, svc := range svcKeys {
-		if !withShared && core.IsGlobal(svc) {
+		if !withShared && IsGlobal(svc) {
 			continue
 		}
 		if _, ok := app[svc.AppId]; !ok {
@@ -102,3 +103,25 @@
 		Version:     service.Version,
 	}
 }
+
+func RegisterGlobalService(serviceName string) {
+	GlobalServiceNames[serviceName] = struct{}{}
+}
+
+func IsGlobal(key *discovery.MicroServiceKey) bool {
+	if !IsDefaultDomainProject(key.Tenant) {
+		return false
+	}
+	if key.AppId != RegistryAppID {
+		return false
+	}
+	_, ok := GlobalServiceNames[key.ServiceName]
+	if !ok {
+		_, ok = GlobalServiceNames[key.Alias]
+	}
+	return ok
+}
+
+func IsDefaultDomainProject(domainProject string) bool {
+	return domainProject == RegistryDomainProject
+}
diff --git a/datasource/service_test.go b/datasource/service_test.go
index 6d79504..0c84147 100644
--- a/datasource/service_test.go
+++ b/datasource/service_test.go
@@ -53,7 +53,7 @@
 				Schemas:     []string{"service-ms-schema"},
 				Paths:       paths,
 				Properties:  properties,
-				Framework: &pb.FrameWorkProperty{
+				Framework: &pb.FrameWork{
 					Name:    "service-ms-frameworkName",
 					Version: "service-ms-frameworkVersion",
 				},
diff --git a/examples/mongodb_data_struct.yaml b/examples/mongodb_data_struct.yaml
index d82eab9..c30a46f 100644
--- a/examples/mongodb_data_struct.yaml
+++ b/examples/mongodb_data_struct.yaml
@@ -23,7 +23,7 @@
 #  ModTimestamp string             `protobuf:"bytes,15,opt,name=modTimestamp" json:"modTimestamp,omitempty" bson:"mod_timestamp"`
 #  Environment  string             `protobuf:"bytes,16,opt,name=environment" json:"environment,omitempty" bson:"env"`
 #  RegisterBy   string             `protobuf:"bytes,17,opt,name=registerBy" json:"registerBy,omitempty" bson:"register_by"`
-#  Framework    *FrameWorkProperty `protobuf:"bytes,18,opt,name=framework" json:"framework,omitempty"`
+#  Framework    *FrameWork `protobuf:"bytes,18,opt,name=framework" json:"framework,omitempty"`
 #}
 
 #collection: service
diff --git a/go.mod b/go.mod
index 2cf2973..da0cb2d 100644
--- a/go.mod
+++ b/go.mod
@@ -15,10 +15,10 @@
 	github.com/dgrijalva/jwt-go v3.2.0+incompatible
 	github.com/elithrar/simple-scrypt v1.3.0
 	github.com/ghodss/yaml v1.0.0
-	github.com/go-chassis/cari v0.4.1-0.20210601163026-bb6a506e336a
+	github.com/go-chassis/cari v0.5.0
 	github.com/go-chassis/foundation v0.3.1-0.20210513015331-b54416b66bcd
 	github.com/go-chassis/go-archaius v1.5.1
-	github.com/go-chassis/go-chassis/v2 v2.2.1-0.20210624120130-77f4a4157de6
+	github.com/go-chassis/go-chassis/v2 v2.2.1-0.20210630123055-6b4c31c5ad02
 	github.com/go-chassis/kie-client v0.1.0
 	github.com/golang/protobuf v1.4.3
 	github.com/gorilla/websocket v1.4.3-0.20210424162022-e8629af678b7
diff --git a/go.sum b/go.sum
index 93e1175..5deafc7 100644
--- a/go.sum
+++ b/go.sum
@@ -165,6 +165,8 @@
 github.com/go-chassis/cari v0.4.0/go.mod h1:av/19fqwEP4eOC8unL/z67AAbFDwXUCko6SKa4Avrd8=
 github.com/go-chassis/cari v0.4.1-0.20210601163026-bb6a506e336a h1:vIG+7IEYeeswrPK8/SM6rDK312M7/7N7sLlYcJ1j6AQ=
 github.com/go-chassis/cari v0.4.1-0.20210601163026-bb6a506e336a/go.mod h1:av/19fqwEP4eOC8unL/z67AAbFDwXUCko6SKa4Avrd8=
+github.com/go-chassis/cari v0.5.0 h1:KMkHtVJuFeqd9NtlcJm27ZBJYhQja909+rgR5CaCs00=
+github.com/go-chassis/cari v0.5.0/go.mod h1:av/19fqwEP4eOC8unL/z67AAbFDwXUCko6SKa4Avrd8=
 github.com/go-chassis/foundation v0.2.2-0.20201210043510-9f6d3de40234/go.mod h1:2PjwqpVwYEVaAldl5A58a08viH8p27pNeYaiE3ZxOBA=
 github.com/go-chassis/foundation v0.2.2/go.mod h1:2PjwqpVwYEVaAldl5A58a08viH8p27pNeYaiE3ZxOBA=
 github.com/go-chassis/foundation v0.3.0/go.mod h1:2PjwqpVwYEVaAldl5A58a08viH8p27pNeYaiE3ZxOBA=
@@ -174,6 +176,8 @@
 github.com/go-chassis/go-archaius v1.5.1/go.mod h1:QPwvvtBxvwiC48rmydoAqxopqOr93RCQ6syWsIkXPXQ=
 github.com/go-chassis/go-chassis/v2 v2.2.1-0.20210624120130-77f4a4157de6 h1:jya7lekMZBG/2H+PlG79Px5D7DQyITp7gjfi015nf9k=
 github.com/go-chassis/go-chassis/v2 v2.2.1-0.20210624120130-77f4a4157de6/go.mod h1:xB09l3WEWp1gncinwDMo0G7n6j826Dp0UyuJ0Tu8axI=
+github.com/go-chassis/go-chassis/v2 v2.2.1-0.20210630123055-6b4c31c5ad02 h1:biwxeKtaF7Bb9A25YsC6sUCJsYWPEy7E13EnCD87RSo=
+github.com/go-chassis/go-chassis/v2 v2.2.1-0.20210630123055-6b4c31c5ad02/go.mod h1:En6f0eHHR3IfnLjboMjsddhrt/WUqQmFKzNgwbVj7WY=
 github.com/go-chassis/go-restful-swagger20 v1.0.3 h1:kWfeLwMwJZVkXP1zNyFpkmR41UZ55UTcOptTteXhvEs=
 github.com/go-chassis/go-restful-swagger20 v1.0.3/go.mod h1:eW62fYuzlNFDvIacB6AV8bhUDCTy4myfTCv0bT9Gbb0=
 github.com/go-chassis/kie-client v0.0.0-20201210060018-938c7680a9ab/go.mod h1:UTdbtyN5ge/v9DmQzdVRxQP7z51Q4z6hyl+W6ZpUHFM=
diff --git a/pkg/metrics/common.go b/pkg/prometheus/common.go
similarity index 70%
rename from pkg/metrics/common.go
rename to pkg/prometheus/common.go
index 56b4d47..239b602 100644
--- a/pkg/metrics/common.go
+++ b/pkg/prometheus/common.go
@@ -15,23 +15,13 @@
  * limitations under the License.
  */
 
-package metrics
+package prometheus
 
 import (
-	helper "github.com/apache/servicecomb-service-center/pkg/prometheus"
-	"github.com/prometheus/client_golang/prometheus"
 	dto "github.com/prometheus/client_model/go"
 )
 
-// keys of gauge
-const (
-	KeyServiceTotal  = "service_total"
-	KeyInstanceTotal = "instance_total"
-
-	SubSystem = "db"
-)
-
-func getValue(name string, labels prometheus.Labels) float64 {
+func getValue(name string, labels map[string]string, getV func(m *dto.Metric) float64) float64 {
 	f := Family(name)
 	if f == nil {
 		return 0
@@ -42,16 +32,24 @@
 		if !matchAll && !MatchLabels(m, labels) {
 			continue
 		}
-		sum += m.GetGauge().GetValue()
+		sum += getV(m)
 	}
 	return sum
 }
 
-func GaugeValue(name string, labels prometheus.Labels) int64 {
-	return int64(getValue(name, labels))
+func GaugeValue(name string, labels map[string]string) float64 {
+	return getValue(name, labels, func(m *dto.Metric) float64 {
+		return m.GetGauge().GetValue()
+	})
 }
 
-func MatchLabels(m *dto.Metric, labels prometheus.Labels) bool {
+func CounterValue(name string, labels map[string]string) float64 {
+	return getValue(name, labels, func(m *dto.Metric) float64 {
+		return m.GetCounter().GetValue()
+	})
+}
+
+func MatchLabels(m *dto.Metric, labels map[string]string) bool {
 	count := 0
 	for _, label := range m.GetLabel() {
 		v, ok := labels[label.GetName()]
@@ -66,12 +64,12 @@
 }
 
 func Family(name string) *dto.MetricFamily {
-	families, err := helper.Gather()
+	families, err := Gather()
 	if err != nil {
 		return nil
 	}
 	for _, f := range families {
-		if f.GetName() == familyNamePrefix+name {
+		if f.GetName() == name {
 			return f
 		}
 	}
diff --git a/pkg/prometheus/decorator.go b/pkg/prometheus/decorator.go
index 318c456..d7ce170 100644
--- a/pkg/prometheus/decorator.go
+++ b/pkg/prometheus/decorator.go
@@ -18,9 +18,13 @@
 package prometheus
 
 import (
+	"net/http"
+
 	"github.com/apache/servicecomb-service-center/pkg/log"
 	"github.com/apache/servicecomb-service-center/pkg/util"
+	"github.com/go-chassis/go-chassis/v2/pkg/metrics"
 	"github.com/prometheus/client_golang/prometheus"
+	"github.com/prometheus/client_golang/prometheus/promhttp"
 	dto "github.com/prometheus/client_model/go"
 )
 
@@ -31,7 +35,7 @@
 	if _, ok := Vectors[name]; ok {
 		log.Warnf("found duplicate metrics name[%s], override!", name)
 	}
-	if err := prometheus.Register(vec); err != nil {
+	if err := metrics.GetSystemPrometheusRegistry().Register(vec); err != nil {
 		log.Fatalf(err, "register prometheus metrics[%s] failed", name)
 	}
 	Vectors[name] = vec
@@ -59,5 +63,9 @@
 }
 
 func Gather() ([]*dto.MetricFamily, error) {
-	return prometheus.DefaultGatherer.Gather()
+	return metrics.GetSystemPrometheusRegistry().Gather()
+}
+
+func HTTPHandler() http.Handler {
+	return promhttp.HandlerFor(metrics.GetSystemPrometheusRegistry(), promhttp.HandlerOpts{})
 }
diff --git a/scctl/pkg/model/types.go b/scctl/pkg/model/types.go
index c21719e..ec85fd0 100644
--- a/scctl/pkg/model/types.go
+++ b/scctl/pkg/model/types.go
@@ -43,7 +43,7 @@
 	AppId         string
 	ServiceName   string
 	Versions      []string
-	Frameworks    []*discovery.FrameWorkProperty
+	Frameworks    []*discovery.FrameWork
 	Endpoints     []string
 	Timestamp     int64 // the seconds from 0 to now
 }
@@ -52,7 +52,7 @@
 	s.Versions = append(s.Versions, v)
 }
 
-func (s *Service) AppendFramework(property *discovery.FrameWorkProperty) {
+func (s *Service) AppendFramework(property *discovery.FrameWork) {
 	if property == nil || property.Name == "" {
 		return
 	}
@@ -90,7 +90,7 @@
 	AppId         string
 	ServiceName   string
 	Version       string
-	Framework     *discovery.FrameWorkProperty
+	Framework     *discovery.FrameWork
 	Lease         int64 // seconds
 	Timestamp     int64 // the seconds from 0 to now
 }
diff --git a/scctl/pkg/plugin/get/schema/schema_cmd.go b/scctl/pkg/plugin/get/schema/schema_cmd.go
index f1a9bb5..a783a80 100644
--- a/scctl/pkg/plugin/get/schema/schema_cmd.go
+++ b/scctl/pkg/plugin/get/schema/schema_cmd.go
@@ -18,6 +18,7 @@
 import (
 	"context"
 	"fmt"
+	"github.com/apache/servicecomb-service-center/datasource"
 	"io"
 	"io/ioutil"
 	"os"
@@ -33,7 +34,6 @@
 	"github.com/apache/servicecomb-service-center/scctl/pkg/cmd"
 	"github.com/apache/servicecomb-service-center/scctl/pkg/model"
 	"github.com/apache/servicecomb-service-center/scctl/pkg/plugin/get"
-	"github.com/apache/servicecomb-service-center/server/core"
 	"github.com/spf13/cobra"
 )
 
@@ -71,10 +71,10 @@
 		return ""
 	}
 	domain, project := util.FromDomainProject(model.GetDomainProject(ms))
-	if domain == core.RegistryDomain {
+	if domain == datasource.RegistryDomain {
 		domain = ""
 	}
-	if project == core.RegistryDomain {
+	if project == datasource.RegistryDomain {
 		project = ""
 	}
 	return filepath.Join(root, "schemas", domain, project, ms.Value.Environment, ms.Value.AppId, ms.Value.ServiceName+".v"+ms.Value.Version)
diff --git a/server/core/microservice.go b/server/core/microservice.go
index 10e936c..6661dbf 100644
--- a/server/core/microservice.go
+++ b/server/core/microservice.go
@@ -21,6 +21,7 @@
 	"context"
 	"strings"
 
+	"github.com/apache/servicecomb-service-center/datasource"
 	"github.com/apache/servicecomb-service-center/pkg/proto"
 	"github.com/apache/servicecomb-service-center/pkg/util"
 	"github.com/apache/servicecomb-service-center/server/config"
@@ -29,18 +30,12 @@
 )
 
 var (
-	ServiceAPI         proto.ServiceCtrlServer
-	Service            *discovery.MicroService
-	Instance           *discovery.MicroServiceInstance
-	globalServiceNames map[string]struct{}
+	ServiceAPI proto.ServiceCtrlServer
+	Service    *discovery.MicroService
+	Instance   *discovery.MicroServiceInstance
 )
 
 const (
-	RegistryDomain        = "default"
-	RegistryProject       = "default"
-	RegistryDomainProject = "default/default"
-
-	RegistryAppID        = "default"
 	RegistryServiceName  = "SERVICECENTER"
 	RegistryServiceAlias = "SERVICECENTER"
 
@@ -57,7 +52,7 @@
 func prepareSelfRegistration() {
 	Service = &discovery.MicroService{
 		Environment: discovery.ENV_PROD,
-		AppId:       RegistryAppID,
+		AppId:       datasource.RegistryAppID,
 		ServiceName: RegistryServiceName,
 		Alias:       RegistryServiceAlias,
 		Version:     version.Ver().Version,
@@ -87,36 +82,17 @@
 
 func AddDefaultContextValue(ctx context.Context) context.Context {
 	return util.WithNoCache(util.SetContext(util.SetDomainProject(ctx,
-		RegistryDomain, RegistryProject),
+		datasource.RegistryDomain, datasource.RegistryProject),
 		CtxScSelf, true))
 }
 
-func IsDefaultDomainProject(domainProject string) bool {
-	return domainProject == RegistryDomainProject
-}
-
 func RegisterGlobalServices() {
-	globalServiceNames = make(map[string]struct{})
 	for _, s := range strings.Split(config.GetRegistry().GlobalVisible, ",") {
 		if len(s) > 0 {
-			globalServiceNames[s] = struct{}{}
+			datasource.RegisterGlobalService(s)
 		}
 	}
-	globalServiceNames[Service.ServiceName] = struct{}{}
-}
-
-func IsGlobal(key *discovery.MicroServiceKey) bool {
-	if !IsDefaultDomainProject(key.Tenant) {
-		return false
-	}
-	if key.AppId != RegistryAppID {
-		return false
-	}
-	_, ok := globalServiceNames[key.ServiceName]
-	if !ok {
-		_, ok = globalServiceNames[key.Alias]
-	}
-	return ok
+	datasource.RegisterGlobalService(Service.ServiceName)
 }
 
 func IsSCInstance(ctx context.Context) bool {
diff --git a/server/core/microservice_test.go b/server/core/microservice_test.go
index 5e57650..ecf6f52 100644
--- a/server/core/microservice_test.go
+++ b/server/core/microservice_test.go
@@ -17,6 +17,7 @@
 
 import (
 	"context"
+	"github.com/apache/servicecomb-service-center/datasource"
 	"testing"
 
 	"github.com/apache/servicecomb-service-center/server/config"
@@ -58,28 +59,28 @@
 
 func TestSetSharedMode(t *testing.T) {
 	RegisterGlobalServices()
-	if IsGlobal(&discovery.MicroServiceKey{}) {
+	if datasource.IsGlobal(&discovery.MicroServiceKey{}) {
 		t.Fatalf("TestSetSharedMode failed")
 	}
-	if IsGlobal(&discovery.MicroServiceKey{Tenant: "default"}) {
+	if datasource.IsGlobal(&discovery.MicroServiceKey{Tenant: "default"}) {
 		t.Fatalf("TestSetSharedMode failed")
 	}
-	if IsGlobal(&discovery.MicroServiceKey{Tenant: "default/default"}) {
+	if datasource.IsGlobal(&discovery.MicroServiceKey{Tenant: "default/default"}) {
 		t.Fatalf("TestSetSharedMode failed")
 	}
-	if IsGlobal(&discovery.MicroServiceKey{Tenant: "default/default", AppId: "default"}) {
+	if datasource.IsGlobal(&discovery.MicroServiceKey{Tenant: "default/default", AppId: "default"}) {
 		t.Fatalf("TestSetSharedMode failed")
 	}
 
 	config.Server.Config.GlobalVisible = "shared"
 	RegisterGlobalServices()
-	if IsGlobal(&discovery.MicroServiceKey{Tenant: "default/default", AppId: "default", ServiceName: "no-shared"}) {
+	if datasource.IsGlobal(&discovery.MicroServiceKey{Tenant: "default/default", AppId: "default", ServiceName: "no-shared"}) {
 		t.Fatalf("TestSetSharedMode failed")
 	}
-	if !IsGlobal(&discovery.MicroServiceKey{Tenant: "default/default", AppId: "default", ServiceName: "shared"}) {
+	if !datasource.IsGlobal(&discovery.MicroServiceKey{Tenant: "default/default", AppId: "default", ServiceName: "shared"}) {
 		t.Fatalf("TestSetSharedMode failed")
 	}
-	if !IsGlobal(&discovery.MicroServiceKey{Tenant: "default/default", AppId: "default", Alias: "shared"}) {
+	if !datasource.IsGlobal(&discovery.MicroServiceKey{Tenant: "default/default", AppId: "default", Alias: "shared"}) {
 		t.Fatalf("TestSetSharedMode failed")
 	}
 }
diff --git a/server/handler/context/v3.go b/server/handler/context/v3.go
index 14f9bae..4190ed1 100644
--- a/server/handler/context/v3.go
+++ b/server/handler/context/v3.go
@@ -21,8 +21,8 @@
 	"net/http"
 	"strings"
 
+	"github.com/apache/servicecomb-service-center/datasource"
 	"github.com/apache/servicecomb-service-center/pkg/util"
-	"github.com/apache/servicecomb-service-center/server/core"
 )
 
 type v3Context struct {
@@ -50,6 +50,6 @@
 	}
 
 	if len(project) == 0 {
-		util.SetRequestContext(r, util.CtxProject, core.RegistryProject)
+		util.SetRequestContext(r, util.CtxProject, datasource.RegistryProject)
 	}
 }
diff --git a/server/handler/context/v4.go b/server/handler/context/v4.go
index 8ffca5f..f953c2c 100644
--- a/server/handler/context/v4.go
+++ b/server/handler/context/v4.go
@@ -21,8 +21,8 @@
 	"net/http"
 	"strings"
 
+	"github.com/apache/servicecomb-service-center/datasource"
 	"github.com/apache/servicecomb-service-center/pkg/util"
-	"github.com/apache/servicecomb-service-center/server/core"
 )
 
 type v4Context struct {
@@ -48,7 +48,7 @@
 	if len(project) == 0 {
 		project = r.URL.Query().Get(":project")
 		if len(project) == 0 {
-			project = core.RegistryProject
+			project = datasource.RegistryProject
 		}
 		util.SetRequestContext(r, util.CtxProject, project)
 	}
diff --git a/server/metrics/meta.go b/server/metrics/meta.go
index 7d17744..eaf7903 100644
--- a/server/metrics/meta.go
+++ b/server/metrics/meta.go
@@ -18,144 +18,136 @@
 package metrics
 
 import (
-	"strings"
 	"time"
 
-	"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/pkg/log"
+	metricsvc "github.com/apache/servicecomb-service-center/pkg/metrics"
+	promutil "github.com/apache/servicecomb-service-center/pkg/prometheus"
+	"github.com/go-chassis/go-chassis/v2/pkg/metrics"
 	"github.com/prometheus/client_golang/prometheus"
 )
 
-// keys of gauge
 const (
-	KeyDomainTotal    = "domain_total"
-	KeySchemaTotal    = "schema_total"
-	KeyFrameworkTotal = "framework_total"
+	SubSystem            = "db"
+	KeyServiceTotal      = metricsvc.FamilyName + "_" + SubSystem + "_" + "service_total"
+	KeyInstanceTotal     = metricsvc.FamilyName + "_" + SubSystem + "_" + "instance_total"
+	KeyDomainTotal       = metricsvc.FamilyName + "_" + SubSystem + "_" + "domain_total"
+	KeySchemaTotal       = metricsvc.FamilyName + "_" + SubSystem + "_" + "schema_total"
+	KeyFrameworkTotal    = metricsvc.FamilyName + "_" + SubSystem + "_" + "framework_total"
+	KeyHeartbeatTotal    = metricsvc.FamilyName + "_" + SubSystem + "_" + "heartbeat_total"
+	KeyHeartbeatDuration = metricsvc.FamilyName + "_" + SubSystem + "_" + "heartbeat_durations_microseconds"
+	KeySCTotal           = metricsvc.FamilyName + "_" + SubSystem + "_" + "sc_total"
 )
 
-// Key return metrics key
-func Key(name string) string {
-	return util.StringJoin([]string{metrics.SubSystem, name}, "_")
+var metaEnabled = false
+
+func InitMetaMetrics() (err error) {
+	defer func() {
+		if err != nil {
+			log.Error("init metadata metrics failed", err)
+		} else {
+			metaEnabled = true
+		}
+	}()
+	if err = metrics.CreateGauge(metrics.GaugeOpts{
+		Key:    KeyDomainTotal,
+		Help:   "Gauge of domain created in Service Center",
+		Labels: []string{"instance"},
+	}); err != nil {
+		return
+	}
+	if err = metrics.CreateGauge(metrics.GaugeOpts{
+		Key:    KeyServiceTotal,
+		Help:   "Gauge of microservice created in Service Center",
+		Labels: []string{"instance", "framework", "frameworkVersion", "domain", "project"},
+	}); err != nil {
+		return
+	}
+	if err = metrics.CreateGauge(metrics.GaugeOpts{
+		Key:    KeyInstanceTotal,
+		Help:   "Gauge of microservice instance created in Service Center",
+		Labels: []string{"instance", "framework", "frameworkVersion", "domain", "project"},
+	}); err != nil {
+		return
+	}
+	if err = metrics.CreateGauge(metrics.GaugeOpts{
+		Key:    KeySchemaTotal,
+		Help:   "Counter of schema created in Service Center",
+		Labels: []string{"instance", "domain", "project"},
+	}); err != nil {
+		return
+	}
+	if err = metrics.CreateGauge(metrics.GaugeOpts{
+		Key:    KeyFrameworkTotal,
+		Help:   "Gauge of client framework info in Service Center",
+		Labels: []string{"instance", "framework", "frameworkVersion", "domain", "project"},
+	}); err != nil {
+		return
+	}
+	if err = metrics.CreateGauge(metrics.GaugeOpts{
+		Key:    KeySCTotal,
+		Help:   "Counter of the Service Center instance",
+		Labels: []string{"instance"},
+	}); err != nil {
+		return
+	}
+	if err = metrics.CreateCounter(metrics.CounterOpts{
+		Key:    KeyHeartbeatTotal,
+		Help:   "Counter of heartbeat renew",
+		Labels: []string{"instance", "status"},
+	}); err != nil {
+		return
+	}
+	if err = metrics.CreateSummary(metrics.SummaryOpts{
+		Key:        KeyHeartbeatDuration,
+		Help:       "Latency of heartbeat renew",
+		Labels:     []string{"instance", "status"},
+		Objectives: metricsvc.Pxx,
+	}); err != nil {
+		return
+	}
+	return
 }
 
-var (
-	domainCounter = helper.NewGaugeVec(
-		prometheus.GaugeOpts{
-			Namespace: metrics.FamilyName,
-			Subsystem: metrics.SubSystem,
-			Name:      KeyDomainTotal,
-			Help:      "Gauge of domain created in Service Center",
-		}, []string{"instance"})
-
-	serviceCounter = helper.NewGaugeVec(
-		prometheus.GaugeOpts{
-			Namespace: metrics.FamilyName,
-			Subsystem: "db",
-			Name:      metrics.KeyServiceTotal,
-			Help:      "Gauge of microservice created in Service Center",
-		}, []string{"instance", "framework", "frameworkVersion", "domain"})
-
-	instanceCounter = helper.NewGaugeVec(
-		prometheus.GaugeOpts{
-			Namespace: metrics.FamilyName,
-			Subsystem: metrics.SubSystem,
-			Name:      metrics.KeyInstanceTotal,
-			Help:      "Gauge of microservice created in Service Center",
-		}, []string{"instance", "domain"})
-
-	schemaCounter = helper.NewGaugeVec(
-		prometheus.GaugeOpts{
-			Namespace: metrics.FamilyName,
-			Subsystem: metrics.SubSystem,
-			Name:      KeySchemaTotal,
-			Help:      "Gauge of schema created in Service Center",
-		}, []string{"instance", "domain"})
-
-	frameworkCounter = helper.NewGaugeVec(
-		prometheus.GaugeOpts{
-			Namespace: metrics.FamilyName,
-			Subsystem: metrics.SubSystem,
-			Name:      KeyFrameworkTotal,
-			Help:      "Gauge of client framework info in Service Center",
-		}, 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.
-type Framework struct {
-	DomainName       string `json:"domainName"`
-	ProjectName      string `json:"projectName"`
-	FrameWork        string `json:"framework"`
-	FrameworkVersion string `json:"frameworkVersion"`
+func GetTotalService(domain, project string) int64 {
+	labels := prometheus.Labels{"domain": domain}
+	if len(project) > 0 {
+		labels["project"] = project
+	}
+	return int64(promutil.GaugeValue(KeyServiceTotal, labels))
 }
 
-func ReportDomains(c float64) {
-	instance := metrics.InstanceName()
-	domainCounter.WithLabelValues(instance).Add(c)
-}
-
-func ReportServices(domain, framework, frameworkVersion string, c float64) {
-	instance := metrics.InstanceName()
-	serviceCounter.WithLabelValues(instance, framework, frameworkVersion, domain).Add(c)
-}
-func GetTotalService(domain string) int64 {
-	return metrics.GaugeValue(strings.Join([]string{metrics.SubSystem, metrics.KeyServiceTotal}, "_"), prometheus.Labels{"domain": domain})
-}
-func ReportInstances(domain string, c float64) {
-	instance := metrics.InstanceName()
-	instanceCounter.WithLabelValues(instance, domain).Add(c)
-}
-func GetTotalInstance(domain string) int64 {
-	mn := strings.Join([]string{metrics.SubSystem, metrics.KeyInstanceTotal}, "_")
-	usage := metrics.GaugeValue(mn, prometheus.Labels{"domain": domain})
-	return usage
-}
-func ReportSchemas(domain string, c float64) {
-	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 GetTotalInstance(domain, project string) int64 {
+	labels := prometheus.Labels{"domain": domain}
+	if len(project) > 0 {
+		labels["project"] = project
+	}
+	return int64(promutil.GaugeValue(KeyInstanceTotal, labels))
 }
 
 func ReportScInstance() {
-	instance := metrics.InstanceName()
-	scCounter.WithLabelValues(instance).Add(1)
+	instance := metricsvc.InstanceName()
+	labels := map[string]string{"instance": instance}
+	if err := metrics.GaugeSet(KeySCTotal, 1, labels); err != nil {
+		log.Error("gauge set failed", err)
+	}
 }
 
 func ReportHeartbeatCompleted(err error, start time.Time) {
-	instance := metrics.InstanceName()
+	if !metaEnabled {
+		return
+	}
+	instance := metricsvc.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()
+	labels := map[string]string{"instance": instance, "status": status}
+	if err := metrics.SummaryObserve(KeyHeartbeatDuration, elapsed, labels); err != nil {
+		log.Error("summary observe failed", err)
+	}
+	if err = metrics.CounterAdd(KeyHeartbeatTotal, 1, labels); err != nil {
+		log.Error("counter add failed", err)
+	}
 }
diff --git a/server/metrics/metrics.go b/server/metrics/metrics.go
new file mode 100644
index 0000000..629421c
--- /dev/null
+++ b/server/metrics/metrics.go
@@ -0,0 +1,46 @@
+/*
+ * 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 (
+	metricsvc "github.com/apache/servicecomb-service-center/pkg/metrics"
+	"github.com/go-chassis/go-chassis/v2/pkg/metrics"
+)
+
+func Init(options Options) error {
+	if err := metrics.Init(); err != nil {
+		return err
+	}
+	if err := metricsvc.Init(metricsvc.Options{
+		Interval:     options.Interval,
+		InstanceName: options.Instance,
+		SysMetrics: []string{
+			"process_resident_memory_bytes",
+			"process_cpu_seconds_total",
+			"go_threads",
+			"go_goroutines",
+		},
+	}); err != nil {
+		return err
+	}
+
+	if err := InitMetaMetrics(); err != nil {
+		return err
+	}
+	return nil
+}
diff --git a/server/metrics/options.go b/server/metrics/options.go
new file mode 100644
index 0000000..701eb81
--- /dev/null
+++ b/server/metrics/options.go
@@ -0,0 +1,25 @@
+/*
+ * 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 "time"
+
+type Options struct {
+	Instance string
+	Interval time.Duration
+}
diff --git a/server/metrics/reporter.go b/server/metrics/reporter.go
new file mode 100644
index 0000000..fe29d07
--- /dev/null
+++ b/server/metrics/reporter.go
@@ -0,0 +1,42 @@
+/*
+ * 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/datasource"
+	"github.com/apache/servicecomb-service-center/pkg/log"
+	"github.com/apache/servicecomb-service-center/pkg/metrics"
+)
+
+func init() {
+	metrics.RegisterReporter("job", &Reporter{})
+}
+
+type Reporter struct {
+}
+
+func (r *Reporter) Report() {
+	ResetMetaMetrics()
+	err := datasource.GetMetricsManager().Report(context.Background(), GetMetaReporter())
+	if err != nil {
+		log.Error("report metrics failed", err)
+		return
+	}
+}
diff --git a/server/metrics/reporter_meta.go b/server/metrics/reporter_meta.go
new file mode 100644
index 0000000..d8e7cca
--- /dev/null
+++ b/server/metrics/reporter_meta.go
@@ -0,0 +1,116 @@
+/*
+ * 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/datasource"
+	"github.com/apache/servicecomb-service-center/pkg/log"
+	metricsvc "github.com/apache/servicecomb-service-center/pkg/metrics"
+	"github.com/go-chassis/go-chassis/v2/pkg/metrics"
+)
+
+var metaReporter = &MetaReporter{}
+
+type MetaReporter struct {
+}
+
+func (m *MetaReporter) DomainAdd(delta float64) {
+	instance := metricsvc.InstanceName()
+	labels := map[string]string{
+		"instance": instance,
+	}
+	if err := metrics.GaugeAdd(KeyDomainTotal, delta, labels); err != nil {
+		log.Error("gauge add failed", err)
+	}
+}
+func (m *MetaReporter) ServiceAdd(delta float64, ml datasource.MetricsLabels) {
+	instance := metricsvc.InstanceName()
+	labels := map[string]string{
+		"instance":         instance,
+		"framework":        ml.Framework,
+		"frameworkVersion": ml.FrameworkVersion,
+		"domain":           ml.Domain,
+		"project":          ml.Project,
+	}
+	if err := metrics.GaugeAdd(KeyServiceTotal, delta, labels); err != nil {
+		log.Error("gauge add failed", err)
+	}
+}
+func (m *MetaReporter) InstanceAdd(delta float64, ml datasource.MetricsLabels) {
+	instance := metricsvc.InstanceName()
+	labels := map[string]string{
+		"instance":         instance,
+		"framework":        ml.Framework,
+		"frameworkVersion": ml.FrameworkVersion,
+		"domain":           ml.Domain,
+		"project":          ml.Project,
+	}
+	if err := metrics.GaugeAdd(KeyInstanceTotal, delta, labels); err != nil {
+		log.Error("gauge add failed", err)
+	}
+}
+func (m *MetaReporter) SchemaAdd(delta float64, ml datasource.MetricsLabels) {
+	instance := metricsvc.InstanceName()
+	labels := map[string]string{
+		"instance": instance,
+		"domain":   ml.Domain,
+		"project":  ml.Project,
+	}
+	if err := metrics.GaugeAdd(KeySchemaTotal, delta, labels); err != nil {
+		log.Error("gauge add failed", err)
+	}
+}
+func (m *MetaReporter) FrameworkSet(ml datasource.MetricsLabels) {
+	instance := metricsvc.InstanceName()
+	labels := map[string]string{
+		"instance":         instance,
+		"framework":        ml.Framework,
+		"frameworkVersion": ml.FrameworkVersion,
+		"domain":           ml.Domain,
+		"project":          ml.Project,
+	}
+	if err := metrics.GaugeSet(KeyFrameworkTotal, 1, labels); err != nil {
+		log.Error("gauge set failed", err)
+	}
+}
+func GetMetaReporter() *MetaReporter {
+	return metaReporter
+}
+
+func ResetMetaMetrics() {
+	err := metrics.Reset(KeyDomainTotal)
+	if err != nil {
+		log.Error("reset metrics failed", err)
+		return
+	}
+	err = metrics.Reset(KeyServiceTotal)
+	if err != nil {
+		log.Error("reset metrics failed", err)
+		return
+	}
+	err = metrics.Reset(KeyInstanceTotal)
+	if err != nil {
+		log.Error("reset metrics failed", err)
+		return
+	}
+	err = metrics.Reset(KeySchemaTotal)
+	if err != nil {
+		log.Error("reset metrics failed", err)
+		return
+	}
+}
diff --git a/server/plugin/quota/quota.go b/server/plugin/quota/quota.go
index 1de41f3..b378ce7 100644
--- a/server/plugin/quota/quota.go
+++ b/server/plugin/quota/quota.go
@@ -150,9 +150,9 @@
 	serviceID := res.ServiceID
 	switch res.QuotaType {
 	case TypeService:
-		return metrics.GetTotalService(util.ParseDomain(ctx)), nil
+		return metrics.GetTotalService(util.ParseDomain(ctx), ""), nil
 	case TypeInstance:
-		usage := metrics.GetTotalInstance(util.ParseDomain(ctx))
+		usage := metrics.GetTotalInstance(util.ParseDomain(ctx), "")
 		return usage, nil
 	case TypeRule:
 		{
diff --git a/server/rest/admin/service.go b/server/rest/admin/service.go
index 728c606..7986957 100644
--- a/server/rest/admin/service.go
+++ b/server/rest/admin/service.go
@@ -25,7 +25,6 @@
 	"github.com/apache/servicecomb-service-center/pkg/log"
 	"github.com/apache/servicecomb-service-center/pkg/util"
 	"github.com/apache/servicecomb-service-center/server/alarm"
-	"github.com/apache/servicecomb-service-center/server/core"
 	"github.com/apache/servicecomb-service-center/version"
 	"github.com/go-chassis/cari/discovery"
 	"github.com/go-chassis/go-archaius"
@@ -41,7 +40,7 @@
 func (service *Service) Dump(ctx context.Context, in *dump.Request) (*dump.Response, error) {
 	domainProject := util.ParseDomainProject(ctx)
 
-	if !core.IsDefaultDomainProject(domainProject) {
+	if !datasource.IsDefaultDomainProject(domainProject) {
 		return &dump.Response{
 			Response: discovery.CreateResponse(discovery.ErrForbidden, "Required admin permission"),
 		}, nil
diff --git a/server/rest/govern/controller_v4.go b/server/rest/govern/controller_v4.go
index 75dd986..db07436 100644
--- a/server/rest/govern/controller_v4.go
+++ b/server/rest/govern/controller_v4.go
@@ -19,9 +19,9 @@
 
 import (
 	"net/http"
-
 	"strings"
 
+	"github.com/apache/servicecomb-service-center/datasource"
 	"github.com/apache/servicecomb-service-center/pkg/log"
 	"github.com/apache/servicecomb-service-center/pkg/rest"
 	"github.com/apache/servicecomb-service-center/pkg/util"
@@ -121,7 +121,7 @@
 }
 
 func (governService *ResourceV4) isSkipped(withShared bool, domainProject string, service *pb.MicroService) bool {
-	return !withShared && core.IsGlobal(pb.MicroServiceToKey(domainProject, service))
+	return !withShared && datasource.IsGlobal(pb.MicroServiceToKey(domainProject, service))
 }
 
 // GetServiceDetail 查询服务详细信息
diff --git a/server/rest/metrics/prometheus.go b/server/rest/metrics/prometheus.go
index c96cd70..5e2869a 100644
--- a/server/rest/metrics/prometheus.go
+++ b/server/rest/metrics/prometheus.go
@@ -18,9 +18,9 @@
 package metrics
 
 import (
+	promutil "github.com/apache/servicecomb-service-center/pkg/prometheus"
 	"github.com/apache/servicecomb-service-center/server/config"
 	"github.com/apache/servicecomb-service-center/server/rest"
-	"github.com/prometheus/client_golang/prometheus/promhttp"
 )
 
 const exporterPrometheus = "prometheus"
@@ -29,5 +29,5 @@
 	if config.GetString("metrics.exporter", "") != exporterPrometheus {
 		return
 	}
-	rest.RegisterServerHandler("/metrics", promhttp.Handler())
+	rest.RegisterServerHandler("/metrics", promutil.HTTPHandler())
 }
diff --git a/server/server.go b/server/server.go
index 7f3954f..61ce4d6 100644
--- a/server/server.go
+++ b/server/server.go
@@ -24,19 +24,18 @@
 	"strings"
 	"time"
 
-	"github.com/apache/servicecomb-service-center/server/event"
-
 	"github.com/apache/servicecomb-service-center/datasource"
 	nf "github.com/apache/servicecomb-service-center/pkg/event"
 	"github.com/apache/servicecomb-service-center/pkg/gopool"
 	"github.com/apache/servicecomb-service-center/pkg/log"
-	"github.com/apache/servicecomb-service-center/pkg/metrics"
 	"github.com/apache/servicecomb-service-center/pkg/plugin"
 	"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/event"
+	"github.com/apache/servicecomb-service-center/server/metrics"
 	"github.com/apache/servicecomb-service-center/server/plugin/security/tlsconf"
 	"github.com/apache/servicecomb-service-center/server/service/gov"
 	"github.com/apache/servicecomb-service-center/server/service/rbac"
@@ -150,14 +149,8 @@
 	}
 
 	if err := metrics.Init(metrics.Options{
-		Interval:     interval,
-		InstanceName: instance,
-		SysMetrics: []string{
-			"process_resident_memory_bytes",
-			"process_cpu_seconds_total",
-			"go_threads",
-			"go_goroutines",
-		},
+		Interval: interval,
+		Instance: instance,
 	}); err != nil {
 		log.Fatal("init metrics failed", err)
 	}
diff --git a/server/service/disco/instance.go b/server/service/disco/instance.go
index 201ecd4..d9cd324 100644
--- a/server/service/disco/instance.go
+++ b/server/service/disco/instance.go
@@ -185,7 +185,7 @@
 			Response: pb.CreateResponse(pb.ErrUnhealthy, err.Error()),
 		}, nil
 	}
-	cloneContext := util.SetDomainProject(util.CloneContext(ctx), apt.RegistryDomain, apt.RegistryProject)
+	cloneContext := util.SetDomainProject(util.CloneContext(ctx), datasource.RegistryDomain, datasource.RegistryProject)
 	svcResp, err := datasource.GetMetadataManager().ExistService(cloneContext, &pb.GetExistenceRequest{
 		Type:        pb.ExistenceMicroservice,
 		AppId:       apt.Service.AppId,
diff --git a/server/service/disco/microservice_test.go b/server/service/disco/microservice_test.go
index ee8eb3f..5677224 100644
--- a/server/service/disco/microservice_test.go
+++ b/server/service/disco/microservice_test.go
@@ -73,7 +73,7 @@
 						Schemas:     []string{TOO_LONG_SCHEMAID[:len(TOO_LONG_SCHEMAID)-1]},
 						Paths:       paths,
 						Properties:  properties,
-						Framework: &pb.FrameWorkProperty{
+						Framework: &pb.FrameWork{
 							Name:    TOO_LONG_FRAMEWORK[:len(TOO_LONG_FRAMEWORK)-1],
 							Version: TOO_LONG_FRAMEWORK[:len(TOO_LONG_FRAMEWORK)-1],
 						},
@@ -592,7 +592,7 @@
 						AppId:       "default",
 						Version:     "1.0.4",
 						Level:       "BACK",
-						Framework: &pb.FrameWorkProperty{
+						Framework: &pb.FrameWork{
 							Version: TOO_LONG_FRAMEWORK,
 						},
 						Properties: make(map[string]string),
@@ -610,7 +610,7 @@
 						AppId:       "default",
 						Version:     "1.0.5",
 						Level:       "BACK",
-						Framework: &pb.FrameWorkProperty{
+						Framework: &pb.FrameWork{
 							Name: TOO_LONG_FRAMEWORK,
 						},
 						Properties: make(map[string]string),
@@ -628,7 +628,7 @@
 						AppId:       "default",
 						Version:     "1.0.5",
 						Level:       "BACK",
-						Framework: &pb.FrameWorkProperty{
+						Framework: &pb.FrameWork{
 							Name: "test@$",
 						},
 						Properties: make(map[string]string),
@@ -724,7 +724,7 @@
 						AppId:       "default",
 						Version:     "1.0.1",
 						Level:       "BACK",
-						Framework: &pb.FrameWorkProperty{
+						Framework: &pb.FrameWork{
 							Version: "1.0.0",
 						},
 						Properties: make(map[string]string),
@@ -742,7 +742,7 @@
 						AppId:       "default",
 						Version:     "1.0.2",
 						Level:       "BACK",
-						Framework: &pb.FrameWorkProperty{
+						Framework: &pb.FrameWork{
 							Name: "framework",
 						},
 						Properties: make(map[string]string),
diff --git a/syncer/plugins/servicecenter/transform.go b/syncer/plugins/servicecenter/transform.go
index 3680970..b4f7d32 100644
--- a/syncer/plugins/servicecenter/transform.go
+++ b/syncer/plugins/servicecenter/transform.go
@@ -319,9 +319,9 @@
 				providers[i].Version = provider.Version
 			}
 		}
-		var frameWorkProperty pbsc.FrameWorkProperty
+		var frameWorkProperty pbsc.FrameWork
 		if service.Framework != nil {
-			frameWorkProperty = pbsc.FrameWorkProperty{
+			frameWorkProperty = pbsc.FrameWork{
 				Name:    service.Framework.Name,
 				Version: service.Framework.Version,
 			}
@@ -371,9 +371,9 @@
 				providers[i].Version = provider.Version
 			}
 		}
-		var frameWorkProperty scpb.FrameWorkProperty
+		var frameWorkProperty scpb.FrameWork
 		if service.Framework != nil {
-			frameWorkProperty = scpb.FrameWorkProperty{
+			frameWorkProperty = scpb.FrameWork{
 				Name:    service.Framework.Name,
 				Version: service.Framework.Version,
 			}
diff --git a/syncer/proto/sc/servicecenter.pb.go b/syncer/proto/sc/servicecenter.pb.go
index 897fba4..1a2864f 100644
--- a/syncer/proto/sc/servicecenter.pb.go
+++ b/syncer/proto/sc/servicecenter.pb.go
@@ -130,7 +130,7 @@
 	ModTimestamp string             `protobuf:"bytes,15,opt,name=modTimestamp,proto3" json:"modTimestamp,omitempty"`
 	Environment  string             `protobuf:"bytes,16,opt,name=environment,proto3" json:"environment,omitempty"`
 	RegisterBy   string             `protobuf:"bytes,17,opt,name=registerBy,proto3" json:"registerBy,omitempty"`
-	Framework    *FrameWorkProperty `protobuf:"bytes,18,opt,name=framework,proto3" json:"framework,omitempty"`
+	Framework    *FrameWork         `protobuf:"bytes,18,opt,name=framework,proto3" json:"framework,omitempty"`
 }
 
 func (x *MicroService) Reset() {
@@ -284,7 +284,7 @@
 	return ""
 }
 
-func (x *MicroService) GetFramework() *FrameWorkProperty {
+func (x *MicroService) GetFramework() *FrameWork {
 	if x != nil {
 		return x.Framework
 	}
@@ -560,7 +560,7 @@
 	return ""
 }
 
-type FrameWorkProperty struct {
+type FrameWork struct {
 	state         protoimpl.MessageState
 	sizeCache     protoimpl.SizeCache
 	unknownFields protoimpl.UnknownFields
@@ -569,8 +569,8 @@
 	Version string `protobuf:"bytes,2,opt,name=version,proto3" json:"version,omitempty"`
 }
 
-func (x *FrameWorkProperty) Reset() {
-	*x = FrameWorkProperty{}
+func (x *FrameWork) Reset() {
+	*x = FrameWork{}
 	if protoimpl.UnsafeEnabled {
 		mi := &file_servicecenter_proto_msgTypes[5]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
@@ -578,13 +578,13 @@
 	}
 }
 
-func (x *FrameWorkProperty) String() string {
+func (x *FrameWork) String() string {
 	return protoimpl.X.MessageStringOf(x)
 }
 
-func (*FrameWorkProperty) ProtoMessage() {}
+func (*FrameWork) ProtoMessage() {}
 
-func (x *FrameWorkProperty) ProtoReflect() protoreflect.Message {
+func (x *FrameWork) ProtoReflect() protoreflect.Message {
 	mi := &file_servicecenter_proto_msgTypes[5]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
@@ -596,19 +596,19 @@
 	return mi.MessageOf(x)
 }
 
-// Deprecated: Use FrameWorkProperty.ProtoReflect.Descriptor instead.
-func (*FrameWorkProperty) Descriptor() ([]byte, []int) {
+// Deprecated: Use FrameWork.ProtoReflect.Descriptor instead.
+func (*FrameWork) Descriptor() ([]byte, []int) {
 	return file_servicecenter_proto_rawDescGZIP(), []int{5}
 }
 
-func (x *FrameWorkProperty) GetName() string {
+func (x *FrameWork) GetName() string {
 	if x != nil {
 		return x.Name
 	}
 	return ""
 }
 
-func (x *FrameWorkProperty) GetVersion() string {
+func (x *FrameWork) GetVersion() string {
 	if x != nil {
 		return x.Version
 	}
@@ -910,7 +910,7 @@
 	(*MicroServiceInstance)(nil), // 2: sc.MicroServiceInstance
 	(*ServicePath)(nil),          // 3: sc.ServicePath
 	(*MicroServiceKey)(nil),      // 4: sc.MicroServiceKey
-	(*FrameWorkProperty)(nil),    // 5: sc.FrameWorkProperty
+	(*FrameWork)(nil),            // 5: sc.FrameWork
 	(*HealthCheck)(nil),          // 6: sc.HealthCheck
 	(*DataCenterInfo)(nil),       // 7: sc.DataCenterInfo
 	nil,                          // 8: sc.MicroService.PropertiesEntry
@@ -923,7 +923,7 @@
 	8,  // 1: sc.MicroService.properties:type_name -> sc.MicroService.PropertiesEntry
 	4,  // 2: sc.MicroService.providers:type_name -> sc.MicroServiceKey
 	9,  // 3: sc.MicroService.LBStrategy:type_name -> sc.MicroService.LBStrategyEntry
-	5,  // 4: sc.MicroService.framework:type_name -> sc.FrameWorkProperty
+	5,  // 4: sc.MicroService.framework:type_name -> sc.FrameWork
 	10, // 5: sc.MicroServiceInstance.properties:type_name -> sc.MicroServiceInstance.PropertiesEntry
 	6,  // 6: sc.MicroServiceInstance.healthCheck:type_name -> sc.HealthCheck
 	7,  // 7: sc.MicroServiceInstance.dataCenterInfo:type_name -> sc.DataCenterInfo
@@ -1002,7 +1002,7 @@
 			}
 		}
 		file_servicecenter_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*FrameWorkProperty); i {
+			switch v := v.(*FrameWork); i {
 			case 0:
 				return &v.state
 			case 1:
diff --git a/syncer/proto/sc/servicecenter.proto b/syncer/proto/sc/servicecenter.proto
index 1f42673..6738642 100644
--- a/syncer/proto/sc/servicecenter.proto
+++ b/syncer/proto/sc/servicecenter.proto
@@ -26,7 +26,7 @@
   string modTimestamp = 15;
   string environment = 16;
   string registerBy = 17;
-  FrameWorkProperty framework = 18;
+  FrameWork framework = 18;
 }
 
 message MicroServiceInstance {
@@ -57,7 +57,7 @@
     string version = 6;
 }
 
-message FrameWorkProperty {
+message FrameWork {
   string name = 1;
   string version = 2;
 }
diff --git a/ux/package-lock.json b/ux/package-lock.json
index 46466a1..9431ed0 100644
--- a/ux/package-lock.json
+++ b/ux/package-lock.json
@@ -14000,6 +14000,7 @@
           "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz",
           "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==",
           "dev": true,
+          "optional": true,
           "requires": {
             "arr-flatten": "^1.1.0",
             "array-unique": "^0.3.2",
@@ -14018,6 +14019,7 @@
               "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
               "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
               "dev": true,
+              "optional": true,
               "requires": {
                 "is-extendable": "^0.1.0"
               }
@@ -14050,6 +14052,7 @@
           "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz",
           "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=",
           "dev": true,
+          "optional": true,
           "requires": {
             "extend-shallow": "^2.0.1",
             "is-number": "^3.0.0",
@@ -14062,6 +14065,7 @@
               "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
               "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
               "dev": true,
+              "optional": true,
               "requires": {
                 "is-extendable": "^0.1.0"
               }
@@ -14117,6 +14121,7 @@
           "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
           "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=",
           "dev": true,
+          "optional": true,
           "requires": {
             "kind-of": "^3.0.2"
           },
@@ -14126,6 +14131,7 @@
               "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
               "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
               "dev": true,
+              "optional": true,
               "requires": {
                 "is-buffer": "^1.1.5"
               }
@@ -14137,6 +14143,7 @@
           "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz",
           "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==",
           "dev": true,
+          "optional": true,
           "requires": {
             "arr-diff": "^4.0.0",
             "array-unique": "^0.3.2",
@@ -14196,6 +14203,7 @@
           "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz",
           "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=",
           "dev": true,
+          "optional": true,
           "requires": {
             "is-number": "^3.0.0",
             "repeat-string": "^1.6.1"