You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dubbo.apache.org by li...@apache.org on 2023/07/31 03:25:16 UTC

[dubbo-go] branch feature-metrics updated: add registry metrics (#2366)

This is an automated email from the ASF dual-hosted git repository.

liujun pushed a commit to branch feature-metrics
in repository https://gitbox.apache.org/repos/asf/dubbo-go.git


The following commit(s) were added to refs/heads/feature-metrics by this push:
     new 82e9849fc add registry metrics (#2366)
82e9849fc is described below

commit 82e9849fc019f93459baf8faf3449d13c51bd9e8
Author: finalt <fi...@163.com>
AuthorDate: Mon Jul 31 11:25:11 2023 +0800

    add registry metrics (#2366)
---
 metrics/registry/collector.go                      | 153 +++++++++++++++++++++
 metrics/registry/event.go                          |  78 ++++++++---
 metrics/registry/listener.go                       |  98 -------------
 metrics/registry/metric_set.go                     | 101 ++++++++++++++
 registry/base_registry.go                          |   6 +-
 registry/directory/directory.go                    |  12 +-
 registry/nacos/registry.go                         |   5 +
 .../servicediscovery/service_discovery_registry.go |   5 +
 8 files changed, 341 insertions(+), 117 deletions(-)

diff --git a/metrics/registry/collector.go b/metrics/registry/collector.go
new file mode 100644
index 000000000..7479fd23d
--- /dev/null
+++ b/metrics/registry/collector.go
@@ -0,0 +1,153 @@
+/*
+ * 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 registry
+
+import (
+	"time"
+)
+
+import (
+	"dubbo.apache.org/dubbo-go/v3/common/constant"
+	"dubbo.apache.org/dubbo-go/v3/metrics"
+)
+
+var (
+	registryChan = make(chan metrics.MetricsEvent, 128)
+)
+
+func init() {
+	metrics.AddCollector("registry", func(m metrics.MetricRegistry, c *metrics.ReporterConfig) {
+		rc := &registryCollector{regRegistry: m}
+		go rc.start()
+	})
+}
+
+// registryCollector is the registry's metrics collector
+type registryCollector struct {
+	regRegistry metrics.MetricRegistry
+}
+
+func (rc *registryCollector) start() {
+	metrics.Subscribe(constant.MetricsRegistry, registryChan)
+	for event := range registryChan {
+		if registryEvent, ok := event.(*RegistryMetricsEvent); ok {
+			switch registryEvent.Name {
+			case Reg:
+				rc.regHandler(registryEvent)
+			case Sub:
+				rc.subHandler(registryEvent)
+			case Notify:
+				rc.notifyHandler(registryEvent)
+			case ServerReg:
+				rc.serverRegHandler(registryEvent)
+			case ServerSub:
+				rc.serverSubHandler(registryEvent)
+			default:
+			}
+		}
+	}
+}
+
+func newStatesMetricFunc(total *metrics.MetricKey, succ *metrics.MetricKey, fail *metrics.MetricKey,
+	level metrics.MetricLevel, reg metrics.MetricRegistry) metrics.StatesMetrics {
+	return metrics.NewStatesMetrics(metrics.NewMetricId(total, level), metrics.NewMetricId(succ, level),
+		metrics.NewMetricId(fail, level), reg)
+}
+
+func newTimeMetrics(min, max, avg, sum, last *metrics.MetricKey, level metrics.MetricLevel, mr metrics.MetricRegistry) metrics.TimeMetric {
+	return metrics.NewTimeMetric(metrics.NewMetricId(min, level), metrics.NewMetricId(max, level), metrics.NewMetricId(avg, level),
+		metrics.NewMetricId(sum, level), metrics.NewMetricId(last, level), mr)
+}
+
+// regHandler handles register metrics
+func (rc *registryCollector) regHandler(event *RegistryMetricsEvent) {
+	// Event is converted to metrics
+	// Save metrics to the MetricRegistry
+	m := metrics.ComputeIfAbsentCache(dubboRegNum, func() interface{} {
+		return newStatesMetricFunc(RegisterMetricRequests, RegisterMetricRequestsSucceed, RegisterMetricRequestsFailed, metrics.GetApplicationLevel(), rc.regRegistry)
+	}).(metrics.StatesMetrics)
+	m.Inc(event.Succ)
+	metric := metrics.ComputeIfAbsentCache(dubboRegRt, func() interface{} {
+		return newTimeMetrics(RegisterRtMillisecondsMin, RegisterRtMillisecondsMax, RegisterRtMillisecondsAvg, RegisterRtMillisecondsSum, RegisterRtMillisecondsLast, metrics.GetApplicationLevel(), rc.regRegistry)
+	}).(metrics.TimeMetric)
+	metric.Record(event.CostMs())
+}
+
+// subHandler handles subscribe metrics
+func (rc *registryCollector) subHandler(event *RegistryMetricsEvent) {
+	// Event is converted to metrics
+	// Save metrics to the MetricRegistry
+	m := newStatesMetricFunc(SubscribeMetricNum, SubscribeMetricNumSucceed, SubscribeMetricNumFailed, metrics.GetApplicationLevel(), rc.regRegistry)
+	m.Inc(event.Succ)
+}
+
+// notifyHandler handles notify metrics
+func (rc *registryCollector) notifyHandler(event *RegistryMetricsEvent) {
+	// Event is converted to metrics
+	// Save metrics to the MetricRegistry
+	rc.regRegistry.Counter(metrics.NewMetricId(NotifyMetricRequests, metrics.GetApplicationLevel())).Inc()
+	rc.regRegistry.Histogram(metrics.NewMetricId(NotifyMetricNumLast, metrics.GetApplicationLevel())).Record(float64(event.End.UnixNano()) / float64(time.Second))
+	metric := metrics.ComputeIfAbsentCache(dubboNotifyRt, func() interface{} {
+		return newTimeMetrics(NotifyRtMillisecondsMin, NotifyRtMillisecondsMax, NotifyRtMillisecondsAvg, NotifyRtMillisecondsSum, NotifyRtMillisecondsLast, metrics.GetApplicationLevel(), rc.regRegistry)
+	}).(metrics.TimeMetric)
+	metric.Record(event.CostMs())
+}
+
+// directoryHandler handles directory metrics
+func (rc *registryCollector) directoryHandler(event *RegistryMetricsEvent) {
+	// Event is converted to metrics
+	// Save metrics to the MetricRegistry
+	level := metrics.GetApplicationLevel()
+	typ := event.Attachment["DirTyp"]
+	switch typ {
+	case NumAllInc:
+		rc.regRegistry.Counter(metrics.NewMetricId(DirectoryMetricNumAll, level)).Inc()
+	case NumAllDec:
+		rc.regRegistry.Counter(metrics.NewMetricId(DirectoryMetricNumAll, level)).Add(-1)
+	case NumDisableTotal:
+		rc.regRegistry.Counter(metrics.NewMetricId(DirectoryMetricNumDisable, level)).Inc()
+	case NumToReconnectTotal:
+		rc.regRegistry.Counter(metrics.NewMetricId(DirectoryMetricNumToReconnect, level)).Inc()
+	case NumValidTotal:
+		rc.regRegistry.Counter(metrics.NewMetricId(DirectoryMetricNumValid, level)).Inc()
+	default:
+	}
+
+}
+
+// serverRegHandler handles server register metrics
+func (rc *registryCollector) serverRegHandler(event *RegistryMetricsEvent) {
+	// Event is converted to metrics
+	// Save metrics to the MetricRegistry
+	m := metrics.ComputeIfAbsentCache(dubboRegServerNum, func() interface{} {
+		return newStatesMetricFunc(ServiceRegisterMetricRequests, ServiceRegisterMetricRequestsSucceed, ServiceRegisterMetricRequestsFailed, metrics.GetApplicationLevel(), rc.regRegistry)
+	}).(metrics.StatesMetrics)
+	m.Inc(event.Succ)
+	metric := metrics.ComputeIfAbsentCache(dubboRegServerRt, func() interface{} {
+		return newTimeMetrics(RegisterServiceRtMillisecondsMin, RegisterServiceRtMillisecondsMax, RegisterServiceRtMillisecondsAvg, RegisterServiceRtMillisecondsSum, RegisterServiceRtMillisecondsLast, metrics.GetApplicationLevel(), rc.regRegistry)
+	}).(metrics.TimeMetric)
+	metric.Record(event.CostMs())
+}
+
+// serverSubHandler handles server subscribe metrics
+func (rc *registryCollector) serverSubHandler(event *RegistryMetricsEvent) {
+	// Event is converted to metrics
+	// Save metrics to the MetricRegistry
+	m := newStatesMetricFunc(ServiceSubscribeMetricNum, ServiceSubscribeMetricNumSucceed, ServiceSubscribeMetricNumFailed, metrics.GetApplicationLevel(), rc.regRegistry)
+	m.Inc(event.Succ)
+}
diff --git a/metrics/registry/event.go b/metrics/registry/event.go
index 825974763..87b135aab 100644
--- a/metrics/registry/event.go
+++ b/metrics/registry/event.go
@@ -17,35 +17,81 @@
 
 package registry
 
+import (
+	"time"
+)
+
 import (
 	"dubbo.apache.org/dubbo-go/v3/common/constant"
+	"dubbo.apache.org/dubbo-go/v3/metrics"
 )
 
+// RegistryMetricsEvent contains info about register metrics
 type RegistryMetricsEvent struct {
-	//Contains some information, such as time, success, failure
-
-	// PostType MetricKey
-	// FinishType MetricKey
-	// ErrorType MetricKey
-	// Level MetricsLevel
-
-	// Time
-	// Start time.time
-	// End time.time
+	Name       MetricName
+	Succ       bool
+	Start      time.Time
+	End        time.Time
+	Attachment map[string]string
 }
 
 func (r RegistryMetricsEvent) Type() string {
 	return constant.MetricsRegistry
 }
 
-// NewRegistryEvent
+func (r *RegistryMetricsEvent) CostMs() float64 {
+	return float64(r.End.Sub(r.Start)) / float64(time.Millisecond)
+}
 
-// NewSubscribeEvent
+// NewRegisterEvent for register metrics
+func NewRegisterEvent(succ bool, start time.Time) metrics.MetricsEvent {
+	return &RegistryMetricsEvent{
+		Name:  Reg,
+		Succ:  succ,
+		Start: start,
+		End:   time.Now(),
+	}
+}
 
-// NewNotifyEvent
+// NewSubscribeEvent for subscribe metrics
+func NewSubscribeEvent(succ bool) metrics.MetricsEvent {
+	return &RegistryMetricsEvent{
+		Name: Sub,
+		Succ: succ,
+	}
+}
+
+// NewNotifyEvent for notify metrics
+func NewNotifyEvent(start time.Time) metrics.MetricsEvent {
+	return &RegistryMetricsEvent{
+		Name:  Notify,
+		Start: start,
+		End:   time.Now(),
+	}
+}
 
-// NewDirectoryEvent
+// NewDirectoryEvent for directory metrics
+func NewDirectoryEvent(dirTyp string) metrics.MetricsEvent {
+	return &RegistryMetricsEvent{
+		Name:       Directory,
+		Attachment: map[string]string{"DirTyp": dirTyp},
+	}
+}
 
-// NewServerRegistryEvent
+// NewServerRegisterEvent for server register metrics
+func NewServerRegisterEvent(succ bool, start time.Time) metrics.MetricsEvent {
+	return &RegistryMetricsEvent{
+		Name:  ServerReg,
+		Succ:  succ,
+		Start: start,
+		End:   time.Now(),
+	}
+}
 
-// NewServerSubscribeEvent
+// NewServerSubscribeEvent for server subscribe metrics
+func NewServerSubscribeEvent(succ bool) metrics.MetricsEvent {
+	return &RegistryMetricsEvent{
+		Name: ServerSub,
+		Succ: succ,
+	}
+}
diff --git a/metrics/registry/listener.go b/metrics/registry/listener.go
deleted file mode 100644
index a12d8064d..000000000
--- a/metrics/registry/listener.go
+++ /dev/null
@@ -1,98 +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 registry
-
-import (
-	"dubbo.apache.org/dubbo-go/v3/common/constant"
-	"dubbo.apache.org/dubbo-go/v3/metrics"
-)
-
-var (
-	//regRegistry  metrics.MetricRegistry
-	registryChan = make(chan metrics.MetricsEvent, 128)
-	handlers     []func(event *RegistryMetricsEvent)
-)
-
-//	func Collector(m metrics.MetricRegistry, r *metrics.ReporterConfig) {
-//		regRegistry = m
-//
-//		// init related metrics
-//	}
-func init() {
-	AddHandler(regHandler, subHandler, notifyHandler, directoryHandler, serverSubHandler, serverRegHandler)
-	//metrics.AddCollector(Collector)
-	metrics.Subscribe(constant.MetricsRegistry, registryChan)
-	go receiveEvent()
-}
-
-func receiveEvent() {
-	for event := range registryChan {
-		registryEvent, ok := event.(*RegistryMetricsEvent)
-		if !ok {
-			continue
-		}
-		for _, handler := range handlers {
-			go func(handler func(event *RegistryMetricsEvent)) {
-				handler(registryEvent)
-			}(handler)
-		}
-	}
-}
-
-func AddHandler(handler ...func(event *RegistryMetricsEvent)) {
-	for _, h := range handler {
-		handlers = append(handlers, h)
-	}
-}
-
-func regHandler(event *RegistryMetricsEvent) {
-	// Event is converted to metrics
-
-	// Save metrics to the MetricRegistry
-}
-
-func subHandler(event *RegistryMetricsEvent) {
-	// Event is converted to metrics
-
-	// Save metrics to the MetricRegistry
-
-}
-
-func notifyHandler(event *RegistryMetricsEvent) {
-	// Event is converted to metrics
-
-	// Save metrics to the MetricRegistry
-}
-
-func directoryHandler(event *RegistryMetricsEvent) {
-	// Event is converted to metrics
-
-	// Save metrics to the MetricRegistry
-}
-
-func serverRegHandler(event *RegistryMetricsEvent) {
-	// Event is converted to metrics
-
-	// Save metrics to the MetricRegistry
-}
-
-func serverSubHandler(event *RegistryMetricsEvent) {
-	// Event is converted to metrics
-
-	// Save metrics to the MetricRegistry
-}
diff --git a/metrics/registry/metric_set.go b/metrics/registry/metric_set.go
new file mode 100644
index 000000000..02408bd15
--- /dev/null
+++ b/metrics/registry/metric_set.go
@@ -0,0 +1,101 @@
+/*
+ * 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 registry
+
+import (
+	"dubbo.apache.org/dubbo-go/v3/metrics"
+)
+
+type MetricName int8
+
+const (
+	Reg MetricName = iota
+	Sub
+	Notify
+	Directory
+	ServerReg
+	ServerSub
+)
+
+const (
+	NumAllInc           = "numAllInc"
+	NumAllDec           = "numAllDec"
+	NumDisableTotal     = "numDisableTotal"
+	NumToReconnectTotal = "numToReconnectTotal"
+	NumValidTotal       = "numValidTotal"
+)
+
+const (
+	dubboRegNum       = "dubbo_registry_register_metrics_num"
+	dubboRegRt        = "dubbo_registry_register_metrics_rt"
+	dubboRegServerNum = "dubbo_registry_register_server_metrics_num"
+	dubboRegServerRt  = "dubbo_registry_register_server_metrics_rt"
+	dubboNotifyRt     = "dubbo_notify_rt"
+)
+
+var (
+	// register metrics key
+	RegisterMetricRequests        = metrics.NewMetricKey("dubbo_registry_register_requests_total", "Total Register Requests")
+	RegisterMetricRequestsSucceed = metrics.NewMetricKey("dubbo_registry_register_requests_succeed_total", "Succeed Register Requests")
+	RegisterMetricRequestsFailed  = metrics.NewMetricKey("dubbo_registry_register_requests_failed_total", "Failed Register Requests")
+
+	// subscribe metrics key
+	SubscribeMetricNum        = metrics.NewMetricKey("dubbo_registry_subscribe_num_total", "Total Subscribe Num")
+	SubscribeMetricNumSucceed = metrics.NewMetricKey("dubbo_registry_subscribe_num_succeed_total", "Succeed Subscribe Num")
+	SubscribeMetricNumFailed  = metrics.NewMetricKey("dubbo_registry_subscribe_num_failed_total", "Failed Subscribe Num")
+
+	// directory metrics key
+	DirectoryMetricNumAll         = metrics.NewMetricKey("dubbo_registry_directory_num_all", "All Directory Urls")
+	DirectoryMetricNumValid       = metrics.NewMetricKey("dubbo_registry_directory_num_valid_total", "Valid Directory Urls")
+	DirectoryMetricNumToReconnect = metrics.NewMetricKey("dubbo_registry_directory_num_to_reconnect_total", "ToReconnect Directory Urls")
+	DirectoryMetricNumDisable     = metrics.NewMetricKey("dubbo_registry_directory_num_disable_total", "Disable Directory Urls")
+
+	NotifyMetricRequests = metrics.NewMetricKey("dubbo_registry_notify_requests_total", "Total Notify Requests")
+	NotifyMetricNumLast  = metrics.NewMetricKey("dubbo_registry_notify_num_last", "Last Notify Nums")
+
+	// register service metrics key
+	ServiceRegisterMetricRequests        = metrics.NewMetricKey("dubbo_registry_register_service_total", "Total Service-Level Register Requests")
+	ServiceRegisterMetricRequestsSucceed = metrics.NewMetricKey("dubbo_registry_register_service_succeed_total", "Succeed Service-Level Register Requests")
+	ServiceRegisterMetricRequestsFailed  = metrics.NewMetricKey("dubbo_registry_register_service_failed_total", "Failed Service-Level Register Requests")
+
+	// subscribe metrics key
+	ServiceSubscribeMetricNum        = metrics.NewMetricKey("dubbo_registry_subscribe_service_num_total", "Total Service-Level Subscribe Num")
+	ServiceSubscribeMetricNumSucceed = metrics.NewMetricKey("dubbo_registry_subscribe_service_num_succeed_total", "Succeed Service-Level Num")
+	ServiceSubscribeMetricNumFailed  = metrics.NewMetricKey("dubbo_registry_subscribe_service_num_failed_total", "Failed Service-Level Num")
+
+	// register metrics server rt key
+	RegisterServiceRtMillisecondsAvg  = metrics.NewMetricKey("dubbo_register_service_rt_milliseconds_avg", "Average Service Register Time")
+	RegisterServiceRtMillisecondsLast = metrics.NewMetricKey("dubbo_register_service_rt_milliseconds_last", "Last Service Register Time")
+	RegisterServiceRtMillisecondsMax  = metrics.NewMetricKey("dubbo_register_service_rt_milliseconds_max", "Max Service Register Time")
+	RegisterServiceRtMillisecondsMin  = metrics.NewMetricKey("dubbo_register_service_rt_milliseconds_min", "Min Service Register Time")
+	RegisterServiceRtMillisecondsSum  = metrics.NewMetricKey("dubbo_register_service_rt_milliseconds_sum", "Sum Service Register Time")
+
+	// register metrics rt key
+	RegisterRtMillisecondsMax  = metrics.NewMetricKey("dubbo_register_rt_milliseconds_max", "Max Response Time")
+	RegisterRtMillisecondsLast = metrics.NewMetricKey("dubbo_register_rt_milliseconds_last", "Last Response Time")
+	RegisterRtMillisecondsAvg  = metrics.NewMetricKey("dubbo_register_rt_milliseconds_avg", "Average Response Time")
+	RegisterRtMillisecondsSum  = metrics.NewMetricKey("dubbo_register_rt_milliseconds_sum", "Sum Response Time")
+	RegisterRtMillisecondsMin  = metrics.NewMetricKey("dubbo_register_rt_milliseconds_min", "Min Response Time")
+
+	// notify rt key
+	NotifyRtMillisecondsAvg  = metrics.NewMetricKey("dubbo_notify_rt_milliseconds_avg", "Average Notify Time")
+	NotifyRtMillisecondsLast = metrics.NewMetricKey("dubbo_notify_rt_milliseconds_last", "Last Notify Time")
+	NotifyRtMillisecondsMax  = metrics.NewMetricKey("dubbo_notify_rt_milliseconds_max", "Max Notify Time")
+	NotifyRtMillisecondsMin  = metrics.NewMetricKey("dubbo_notify_rt_milliseconds_min", "Min Notify Time")
+	NotifyRtMillisecondsSum  = metrics.NewMetricKey("dubbo_notify_rt_milliseconds_sum", "Sum Notify Time")
+)
diff --git a/registry/base_registry.go b/registry/base_registry.go
index 0fa643c21..a41e967d6 100644
--- a/registry/base_registry.go
+++ b/registry/base_registry.go
@@ -36,6 +36,8 @@ import (
 import (
 	"dubbo.apache.org/dubbo-go/v3/common"
 	"dubbo.apache.org/dubbo-go/v3/common/constant"
+	"dubbo.apache.org/dubbo-go/v3/metrics"
+	metricsRegistry "dubbo.apache.org/dubbo-go/v3/metrics/registry"
 )
 
 const (
@@ -132,6 +134,7 @@ func (r *BaseRegistry) Destroy() {
 // Register implement interface registry to register
 func (r *BaseRegistry) Register(url *common.URL) error {
 	// if developer define registry port and ip, use it first.
+	start := time.Now()
 	if ipToRegistry := os.Getenv(constant.DubboIpToRegistryKey); len(ipToRegistry) > 0 {
 		url.Ip = ipToRegistry
 	} else {
@@ -146,6 +149,7 @@ func (r *BaseRegistry) Register(url *common.URL) error {
 	}
 
 	err := r.register(url)
+	defer metrics.Publish(metricsRegistry.NewRegisterEvent(err == nil, start))
 	if err == nil {
 		r.registered.Store(url.Key(), url)
 
@@ -161,8 +165,8 @@ func (r *BaseRegistry) UnRegister(url *common.URL) error {
 	if _, ok := r.registered.Load(url.Key()); !ok {
 		return perrors.Errorf("Service {%s} has not registered", url.Key())
 	}
-
 	err := r.unregister(url)
+	metrics.Publish(metricsRegistry.NewSubscribeEvent(err == nil))
 	if err == nil {
 		r.registered.Delete(url.Key())
 	} else {
diff --git a/registry/directory/directory.go b/registry/directory/directory.go
index 7ba8ace94..903fbdb11 100644
--- a/registry/directory/directory.go
+++ b/registry/directory/directory.go
@@ -22,6 +22,7 @@ import (
 	"net/url"
 	"os"
 	"sync"
+	"time"
 )
 
 import (
@@ -41,6 +42,8 @@ import (
 	"dubbo.apache.org/dubbo-go/v3/config"
 	"dubbo.apache.org/dubbo-go/v3/config_center"
 	_ "dubbo.apache.org/dubbo-go/v3/config_center/configurator"
+	"dubbo.apache.org/dubbo-go/v3/metrics"
+	metricsRegistry "dubbo.apache.org/dubbo-go/v3/metrics/registry"
 	"dubbo.apache.org/dubbo-go/v3/protocol"
 	"dubbo.apache.org/dubbo-go/v3/protocol/protocolwrapper"
 	"dubbo.apache.org/dubbo-go/v3/registry"
@@ -97,7 +100,7 @@ func NewRegistryDirectory(url *common.URL, registry registry.Registry) (director
 	if err := dir.registry.LoadSubscribeInstances(url.SubURL, dir); err != nil {
 		return nil, err
 	}
-
+	metrics.Publish(metricsRegistry.NewDirectoryEvent(metricsRegistry.NumAllInc))
 	return dir, nil
 }
 
@@ -114,7 +117,9 @@ func (dir *RegistryDirectory) Notify(event *registry.ServiceEvent) {
 	if event == nil {
 		return
 	}
+	start := time.Now()
 	dir.refreshInvokers(event)
+	metrics.Publish(metricsRegistry.NewNotifyEvent(start))
 }
 
 // NotifyAll notify the events that are complete Service Event List.
@@ -336,6 +341,7 @@ func (dir *RegistryDirectory) uncacheInvokerWithClusterID(clusterID string) []pr
 
 // uncacheInvoker will return abandoned Invoker, if no Invoker to be abandoned, return nil
 func (dir *RegistryDirectory) uncacheInvoker(event *registry.ServiceEvent) []protocol.Invoker {
+	defer metrics.Publish(metricsRegistry.NewDirectoryEvent(metricsRegistry.NumDisableTotal))
 	if clusterID := event.Service.GetParam(constant.MeshClusterIDKey, ""); event.Service.Location == constant.MeshAnyAddrMatcher && clusterID != "" {
 		dir.uncacheInvokerWithClusterID(clusterID)
 	}
@@ -389,6 +395,7 @@ func (dir *RegistryDirectory) doCacheInvoker(newUrl *common.URL, event *registry
 			logger.Warnf("service will be added in cache invokers fail, result is null, invokers url is %+v", newUrl.String())
 		}
 	} else {
+		metrics.Publish(metricsRegistry.NewDirectoryEvent(metricsRegistry.NumValidTotal))
 		// if cached invoker has the same URL with the new URL, then no need to re-refer, and no need to destroy
 		// the old invoker.
 		if common.GetCompareURLEqualFunc()(newUrl, cacheInvoker.(protocol.Invoker).GetURL()) {
@@ -430,7 +437,7 @@ func (dir *RegistryDirectory) IsAvailable() bool {
 			return true
 		}
 	}
-
+	metrics.Publish(metricsRegistry.NewDirectoryEvent(metricsRegistry.NumToReconnectTotal))
 	return false
 }
 
@@ -444,6 +451,7 @@ func (dir *RegistryDirectory) Destroy() {
 			ivk.Destroy()
 		}
 	})
+	metrics.Publish(metricsRegistry.NewDirectoryEvent(metricsRegistry.NumAllDec))
 }
 
 func (dir *RegistryDirectory) overrideUrl(targetUrl *common.URL) {
diff --git a/registry/nacos/registry.go b/registry/nacos/registry.go
index 911d26ba5..bfb45754c 100644
--- a/registry/nacos/registry.go
+++ b/registry/nacos/registry.go
@@ -38,6 +38,8 @@ import (
 	"dubbo.apache.org/dubbo-go/v3/common"
 	"dubbo.apache.org/dubbo-go/v3/common/constant"
 	"dubbo.apache.org/dubbo-go/v3/common/extension"
+	"dubbo.apache.org/dubbo-go/v3/metrics"
+	metricsRegistry "dubbo.apache.org/dubbo-go/v3/metrics/registry"
 	"dubbo.apache.org/dubbo-go/v3/registry"
 	"dubbo.apache.org/dubbo-go/v3/remoting"
 	"dubbo.apache.org/dubbo-go/v3/remoting/nacos"
@@ -112,11 +114,13 @@ func createRegisterParam(url *common.URL, serviceName string, groupName string)
 
 // Register will register the service @url to its nacos registry center.
 func (nr *nacosRegistry) Register(url *common.URL) error {
+	start := time.Now()
 	serviceName := getServiceName(url)
 	groupName := nr.URL.GetParam(constant.NacosGroupKey, defaultGroup)
 	param := createRegisterParam(url, serviceName, groupName)
 	logger.Infof("[Nacos Registry] Registry instance with param = %+v", param)
 	isRegistry, err := nr.namingClient.Client().RegisterInstance(param)
+	metrics.Publish(metricsRegistry.NewRegisterEvent(err == nil && isRegistry, start))
 	if err != nil {
 		return err
 	}
@@ -173,6 +177,7 @@ func (nr *nacosRegistry) Subscribe(url *common.URL, notifyListener registry.Noti
 		}
 
 		listener, err := nr.subscribe(url)
+		defer metrics.Publish(metricsRegistry.NewSubscribeEvent(err == nil))
 		if err != nil {
 			if !nr.IsAvailable() {
 				logger.Warnf("event listener game over.")
diff --git a/registry/servicediscovery/service_discovery_registry.go b/registry/servicediscovery/service_discovery_registry.go
index 53b60500c..db0986df5 100644
--- a/registry/servicediscovery/service_discovery_registry.go
+++ b/registry/servicediscovery/service_discovery_registry.go
@@ -42,6 +42,7 @@ import (
 	"dubbo.apache.org/dubbo-go/v3/metadata/service/local"
 	"dubbo.apache.org/dubbo-go/v3/metrics"
 	metricMetadata "dubbo.apache.org/dubbo-go/v3/metrics/metadata"
+	metricsRegistry "dubbo.apache.org/dubbo-go/v3/metrics/registry"
 	"dubbo.apache.org/dubbo-go/v3/registry"
 	_ "dubbo.apache.org/dubbo-go/v3/registry/event"
 	"dubbo.apache.org/dubbo-go/v3/registry/servicediscovery/synthesizer"
@@ -178,7 +179,10 @@ func (s *ServiceDiscoveryRegistry) Register(url *common.URL) error {
 		return nil
 	}
 	common.HandleRegisterIPAndPort(url)
+
+	start := time.Now()
 	ok, err := s.metaDataService.ExportURL(url)
+	metrics.Publish(metricsRegistry.NewServerRegisterEvent(ok && err == nil, start))
 
 	if err != nil {
 		logger.Errorf("The URL[%s] registry catch error:%s!", url.String(), err.Error())
@@ -253,6 +257,7 @@ func (s *ServiceDiscoveryRegistry) SubscribeURL(url *common.URL, notify registry
 	event.End = time.Now()
 	event.Attachment[constant.InterfaceKey] = url.Interface()
 	metrics.Publish(event)
+	metrics.Publish(metricsRegistry.NewServerSubscribeEvent(err == nil))
 	if err != nil {
 		logger.Errorf("add instance listener catch error,url:%s err:%s", url.String(), err.Error())
 	}