From 14a9b34fba70e40c28d8aafaab1f8286d81261ab Mon Sep 17 00:00:00 2001 From: foghost Date: Fri, 25 Aug 2023 10:10:19 +0800 Subject: [PATCH 01/22] migrate old RT metric impl to new RT impl (#2390) --- metrics/api.go | 111 +++------------------------------ metrics/common.go | 2 +- metrics/metadata/collector.go | 59 ++++-------------- metrics/metadata/metric_set.go | 43 ++++--------- metrics/registry/collector.go | 69 +++++++------------- metrics/registry/metric_set.go | 26 +------- 6 files changed, 56 insertions(+), 254 deletions(-) diff --git a/metrics/api.go b/metrics/api.go index 7dbcc7a198..4c19e63cfd 100644 --- a/metrics/api.go +++ b/metrics/api.go @@ -17,14 +17,6 @@ package metrics -import ( - "sync" -) - -import ( - "dubbo.apache.org/dubbo-go/v3/metrics/util/aggregate" -) - var ( registries = make(map[string]func(*ReporterConfig) MetricRegistry) collectors = make([]CollectorFunc, 0) @@ -145,104 +137,15 @@ type ObservableMetric interface { Observe(float64) } -// StatesMetrics multi metrics,include total,success num, fail num,call MetricsRegistry save data -type StatesMetrics interface { - Success() - AddSuccess(float64) - Fail() - AddFailed(float64) - Inc(succ bool) +type BaseCollector struct { + R MetricRegistry } -func NewStatesMetrics(total *MetricId, succ *MetricId, fail *MetricId, reg MetricRegistry) StatesMetrics { - return &DefaultStatesMetric{total: total, succ: succ, fail: fail, r: reg} -} - -type DefaultStatesMetric struct { - r MetricRegistry - total, succ, fail *MetricId -} - -func (c DefaultStatesMetric) Inc(succ bool) { - if succ { - c.Success() +func (c *BaseCollector) StateCount(total, succ, fail *MetricKey, level MetricLevel, succed bool) { + c.R.Counter(NewMetricId(total, level)).Inc() + if succed { + c.R.Counter(NewMetricId(succ, level)).Inc() } else { - c.Fail() - } -} -func (c DefaultStatesMetric) Success() { - c.r.Counter(c.total).Inc() - c.r.Counter(c.succ).Inc() -} - -func (c DefaultStatesMetric) AddSuccess(v float64) { - c.r.Counter(c.total).Add(v) - c.r.Counter(c.succ).Add(v) -} - -func (c DefaultStatesMetric) Fail() { - c.r.Counter(c.total).Inc() - c.r.Counter(c.fail).Inc() -} - -func (c DefaultStatesMetric) AddFailed(v float64) { - c.r.Counter(c.total).Add(v) - c.r.Counter(c.fail).Add(v) -} - -// TimeMetric muliti metrics, include min(Gauge)、max(Gauge)、avg(Gauge)、sum(Gauge)、last(Gauge),call MetricRegistry to expose -// see dubbo-java org.apache.dubbo.metrics.aggregate.TimeWindowAggregator -type TimeMetric interface { - Record(float64) -} - -const ( - defaultBucketNum = 10 - defaultTimeWindowSeconds = 120 -) - -// NewTimeMetric init and write all data to registry -func NewTimeMetric(min, max, avg, sum, last *MetricId, mr MetricRegistry) TimeMetric { - return &DefaultTimeMetric{r: mr, min: min, max: max, avg: avg, sum: sum, last: last, - agg: aggregate.NewTimeWindowAggregator(defaultBucketNum, defaultTimeWindowSeconds)} -} - -type DefaultTimeMetric struct { - r MetricRegistry - agg *aggregate.TimeWindowAggregator - min, max, avg, sum, last *MetricId -} - -func (m *DefaultTimeMetric) Record(v float64) { - m.agg.Add(v) - result := m.agg.Result() - m.r.Gauge(m.max).Set(result.Max) - m.r.Gauge(m.min).Set(result.Min) - m.r.Gauge(m.avg).Set(result.Avg) - m.r.Gauge(m.sum).Set(result.Total) - m.r.Gauge(m.last).Set(v) -} - -// cache if needed, TimeMetrics must cached -var metricsCache map[string]interface{} = make(map[string]interface{}) -var metricsCacheMutex sync.RWMutex - -func ComputeIfAbsentCache(key string, supplier func() interface{}) interface{} { - metricsCacheMutex.RLock() - v, ok := metricsCache[key] - metricsCacheMutex.RUnlock() - if ok { - return v - } else { - metricsCacheMutex.Lock() - defer metricsCacheMutex.Unlock() - v, ok = metricsCache[key] // double check,avoid overwriting - if ok { - return v - } else { - n := supplier() - metricsCache[key] = n - return n - } + c.R.Counter(NewMetricId(fail, level)).Inc() } } diff --git a/metrics/common.go b/metrics/common.go index f0ce9cf9d7..3dbe51bd1a 100644 --- a/metrics/common.go +++ b/metrics/common.go @@ -66,7 +66,7 @@ func (m *ApplicationMetricLevel) Tags() map[string]string { tags := make(map[string]string) tags[constant.IpKey] = m.Ip tags[constant.HostnameKey] = m.HostName - tags[constant.ApplicationKey] = m.ApplicationName + tags[constant.ApplicationNameKey] = m.ApplicationName tags[constant.ApplicationVersionKey] = m.Version tags[constant.GitCommitIdKey] = m.GitCommitId return tags diff --git a/metrics/metadata/collector.go b/metrics/metadata/collector.go index 16740d3567..23921242f1 100644 --- a/metrics/metadata/collector.go +++ b/metrics/metadata/collector.go @@ -32,13 +32,13 @@ var ch = make(chan metrics.MetricsEvent, 10) func init() { metrics.AddCollector("metadata", func(mr metrics.MetricRegistry, rc *metrics.ReporterConfig) { - l := &MetadataMetricCollector{r: mr} + l := &MetadataMetricCollector{metrics.BaseCollector{R: mr}} l.start() }) } type MetadataMetricCollector struct { - r metrics.MetricRegistry + metrics.BaseCollector } func (c *MetadataMetricCollector) start() { @@ -63,59 +63,26 @@ func (c *MetadataMetricCollector) start() { } func (c *MetadataMetricCollector) handleMetadataPush(event *MetadataMetricEvent) { - m := metrics.ComputeIfAbsentCache(dubboMetadataPush, func() interface{} { - return newStatesMetricFunc(metadataPushNum, metadataPushNumSucceed, metadataPushNumFailed, metrics.GetApplicationLevel(), c.r) - }).(metrics.StatesMetrics) - m.Inc(event.Succ) - metric := metrics.ComputeIfAbsentCache(dubboPushRt, func() interface{} { - return newTimeMetrics(pushRtMin, pushRtMax, pushRtAvg, pushRtSum, pushRtLast, metrics.GetApplicationLevel(), c.r) - }).(metrics.TimeMetric) - metric.Record(event.CostMs()) + level := metrics.GetApplicationLevel() + c.StateCount(metadataPushNum, metadataPushSucceed, metadataPushFailed, level, event.Succ) + c.R.Rt(metrics.NewMetricId(pushRt, level), &metrics.RtOpts{}).Observe(event.CostMs()) } func (c *MetadataMetricCollector) handleMetadataSub(event *MetadataMetricEvent) { - m := metrics.ComputeIfAbsentCache(dubboMetadataSubscribe, func() interface{} { - return newStatesMetricFunc(metadataSubNum, metadataSubNumSucceed, metadataSubNumFailed, metrics.GetApplicationLevel(), c.r) - }).(metrics.StatesMetrics) - m.Inc(event.Succ) - metric := metrics.ComputeIfAbsentCache(dubboSubscribeRt, func() interface{} { - return newTimeMetrics(subscribeRtMin, subscribeRtMax, subscribeRtAvg, subscribeRtSum, subscribeRtLast, metrics.GetApplicationLevel(), c.r) - }).(metrics.TimeMetric) - metric.Record(event.CostMs()) + level := metrics.GetApplicationLevel() + c.StateCount(metadataSubNum, metadataSubSucceed, metadataSubFailed, level, event.Succ) + c.R.Rt(metrics.NewMetricId(subscribeRt, level), &metrics.RtOpts{}).Observe(event.CostMs()) } func (c *MetadataMetricCollector) handleStoreProvider(event *MetadataMetricEvent) { - interfaceName := event.Attachment[constant.InterfaceKey] - m := metrics.ComputeIfAbsentCache(dubboMetadataStoreProvider+":"+interfaceName, func() interface{} { - return newStatesMetricFunc(metadataStoreProvider, metadataStoreProviderSucceed, metadataStoreProviderFailed, - metrics.NewServiceMetric(interfaceName), c.r) - }).(metrics.StatesMetrics) - m.Inc(event.Succ) - metric := metrics.ComputeIfAbsentCache(dubboStoreProviderInterfaceRt+":"+interfaceName, func() interface{} { - return newTimeMetrics(storeProviderInterfaceRtMin, storeProviderInterfaceRtMax, storeProviderInterfaceRtAvg, - storeProviderInterfaceRtSum, storeProviderInterfaceRtLast, metrics.NewServiceMetric(interfaceName), c.r) - }).(metrics.TimeMetric) - metric.Record(event.CostMs()) + level := metrics.NewServiceMetric(event.Attachment[constant.InterfaceKey]) + c.StateCount(metadataStoreProviderNum, metadataStoreProviderSucceed, metadataStoreProviderFailed, level, event.Succ) + c.R.Rt(metrics.NewMetricId(storeProviderInterfaceRt, level), &metrics.RtOpts{}).Observe(event.CostMs()) } func (c *MetadataMetricCollector) handleSubscribeService(event *MetadataMetricEvent) { - interfaceName := event.Attachment[constant.InterfaceKey] - metric := metrics.ComputeIfAbsentCache(dubboSubscribeServiceRt+":"+interfaceName, func() interface{} { - return newTimeMetrics(subscribeServiceRtMin, subscribeServiceRtMax, subscribeServiceRtAvg, subscribeServiceRtSum, - subscribeServiceRtLast, metrics.NewServiceMetric(interfaceName), c.r) - }).(metrics.TimeMetric) - metric.Record(event.CostMs()) -} - -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) + level := metrics.NewServiceMetric(event.Attachment[constant.InterfaceKey]) + c.R.Rt(metrics.NewMetricId(subscribeServiceRt, level), &metrics.RtOpts{}).Observe(event.CostMs()) } type MetadataMetricEvent struct { diff --git a/metrics/metadata/metric_set.go b/metrics/metadata/metric_set.go index e7ade6e57c..20d76a36f2 100644 --- a/metrics/metadata/metric_set.go +++ b/metrics/metadata/metric_set.go @@ -47,34 +47,21 @@ const ( totalSuffix = "_total" succSuffix = "_succeed_total" failedSuffix = "_failed_total" - sumSuffix = "_sum" - lastSuffix = "_last" - minSuffix = "_min" - maxSuffix = "_max" - avgSuffix = "_avg" ) var ( // app level - metadataPushNum = metrics.NewMetricKey(dubboMetadataPush+totalSuffix, "Total Num") - metadataPushNumSucceed = metrics.NewMetricKey(dubboMetadataPush+succSuffix, "Succeed Push Num") - metadataPushNumFailed = metrics.NewMetricKey(dubboMetadataPush+failedSuffix, "Failed Push Num") + metadataPushNum = metrics.NewMetricKey(dubboMetadataPush+totalSuffix, "Total Num") + metadataPushSucceed = metrics.NewMetricKey(dubboMetadataPush+succSuffix, "Succeed Push Num") + metadataPushFailed = metrics.NewMetricKey(dubboMetadataPush+failedSuffix, "Failed Push Num") // app level - metadataSubNum = metrics.NewMetricKey(dubboMetadataSubscribe+totalSuffix, "Total Metadata Subscribe Num") - metadataSubNumSucceed = metrics.NewMetricKey(dubboMetadataSubscribe+succSuffix, "Succeed Metadata Subscribe Num") - metadataSubNumFailed = metrics.NewMetricKey(dubboMetadataSubscribe+failedSuffix, "Failed Metadata Subscribe Num") + metadataSubNum = metrics.NewMetricKey(dubboMetadataSubscribe+totalSuffix, "Total Metadata Subscribe Num") + metadataSubSucceed = metrics.NewMetricKey(dubboMetadataSubscribe+succSuffix, "Succeed Metadata Subscribe Num") + metadataSubFailed = metrics.NewMetricKey(dubboMetadataSubscribe+failedSuffix, "Failed Metadata Subscribe Num") // app level - pushRtSum = metrics.NewMetricKey(dubboPushRt+sumSuffix, "Sum Response Time") - pushRtLast = metrics.NewMetricKey(dubboPushRt+lastSuffix, "Last Response Time") - pushRtMin = metrics.NewMetricKey(dubboPushRt+minSuffix, "Min Response Time") - pushRtMax = metrics.NewMetricKey(dubboPushRt+maxSuffix, "Max Response Time") - pushRtAvg = metrics.NewMetricKey(dubboPushRt+avgSuffix, "Average Response Time") + pushRt = metrics.NewMetricKey(dubboPushRt, "Response Time") // app level - subscribeRtSum = metrics.NewMetricKey(dubboSubscribeRt+sumSuffix, "Sum Response Time") - subscribeRtLast = metrics.NewMetricKey(dubboSubscribeRt+lastSuffix, "Last Response Time") - subscribeRtMin = metrics.NewMetricKey(dubboSubscribeRt+minSuffix, "Min Response Time") - subscribeRtMax = metrics.NewMetricKey(dubboSubscribeRt+maxSuffix, "Max Response Time") - subscribeRtAvg = metrics.NewMetricKey(dubboSubscribeRt+avgSuffix, "Average Response Time") + subscribeRt = metrics.NewMetricKey(dubboSubscribeRt, "Response Time") /* # HELP dubbo_metadata_store_provider_succeed_total Succeed Store Provider Metadata @@ -85,7 +72,7 @@ var ( // service level metadataStoreProviderFailed = metrics.NewMetricKey(dubboMetadataStoreProvider+failedSuffix, "Total Failed Provider Metadata Store") metadataStoreProviderSucceed = metrics.NewMetricKey(dubboMetadataStoreProvider+succSuffix, "Total Succeed Provider Metadata Store") - metadataStoreProvider = metrics.NewMetricKey(dubboMetadataStoreProvider+totalSuffix, "Total Provider Metadata Store") + metadataStoreProviderNum = metrics.NewMetricKey(dubboMetadataStoreProvider+totalSuffix, "Total Provider Metadata Store") /* # HELP dubbo_store_provider_interface_rt_milliseconds_avg Average Response Time @@ -94,15 +81,7 @@ var ( dubbo_store_provider_interface_rt_milliseconds_avg{application_name="metrics-provider",application_version="3.2.1",git_commit_id="20de8b22ffb2a23531f6d9494a4963fcabd52561",hostname="localhost",interface="org.apache.dubbo.samples.metrics.prometheus.api.DemoService2",ip="10.252.156.213",} 10837.0 */ // service level - storeProviderInterfaceRtAvg = metrics.NewMetricKey(dubboStoreProviderInterfaceRt+avgSuffix, "Average Store Provider Interface Time") - storeProviderInterfaceRtLast = metrics.NewMetricKey(dubboStoreProviderInterfaceRt+lastSuffix, "Last Store Provider Interface Time") - storeProviderInterfaceRtMax = metrics.NewMetricKey(dubboStoreProviderInterfaceRt+maxSuffix, "Max Store Provider Interface Time") - storeProviderInterfaceRtMin = metrics.NewMetricKey(dubboStoreProviderInterfaceRt+minSuffix, "Min Store Provider Interface Time") - storeProviderInterfaceRtSum = metrics.NewMetricKey(dubboStoreProviderInterfaceRt+sumSuffix, "Sum Store Provider Interface Time") + storeProviderInterfaceRt = metrics.NewMetricKey(dubboStoreProviderInterfaceRt, "Store Provider Interface Time") - subscribeServiceRtLast = metrics.NewMetricKey(dubboSubscribeServiceRt+lastSuffix, "Last Subscribe Service Time") - subscribeServiceRtMax = metrics.NewMetricKey(dubboSubscribeServiceRt+maxSuffix, "Max Subscribe Service Time") - subscribeServiceRtMin = metrics.NewMetricKey(dubboSubscribeServiceRt+minSuffix, "Min Subscribe Service Time") - subscribeServiceRtSum = metrics.NewMetricKey(dubboSubscribeServiceRt+sumSuffix, "Sum Subscribe Service Time") - subscribeServiceRtAvg = metrics.NewMetricKey(dubboSubscribeServiceRt+avgSuffix, "Average Subscribe Service Time") + subscribeServiceRt = metrics.NewMetricKey(dubboSubscribeServiceRt, "Subscribe Service Time") ) diff --git a/metrics/registry/collector.go b/metrics/registry/collector.go index 63840ed7de..fcd94b9740 100644 --- a/metrics/registry/collector.go +++ b/metrics/registry/collector.go @@ -17,10 +17,6 @@ package registry -import ( - "time" -) - import ( "dubbo.apache.org/dubbo-go/v3/common/constant" "dubbo.apache.org/dubbo-go/v3/metrics" @@ -32,14 +28,14 @@ var ( func init() { metrics.AddCollector("registry", func(m metrics.MetricRegistry, c *metrics.ReporterConfig) { - rc := ®istryCollector{regRegistry: m} + rc := ®istryCollector{metrics.BaseCollector{R: m}} go rc.start() }) } // registryCollector is the registry's metrics collector type registryCollector struct { - regRegistry metrics.MetricRegistry + metrics.BaseCollector } func (rc *registryCollector) start() { @@ -63,49 +59,31 @@ func (rc *registryCollector) start() { } } -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()) + level := metrics.GetApplicationLevel() + rc.StateCount(RegisterMetricRequests, RegisterMetricRequestsSucceed, RegisterMetricRequestsFailed, level, event.Succ) + rc.R.Rt(metrics.NewMetricId(RegisterRt, level), &metrics.RtOpts{}).Observe(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) + level := metrics.GetApplicationLevel() + rc.StateCount(SubscribeMetricNum, SubscribeMetricNumSucceed, SubscribeMetricNumFailed, level, 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())).Observe(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()) + level := metrics.GetApplicationLevel() + rc.R.Counter(metrics.NewMetricId(NotifyMetricRequests, level)).Inc() + rc.R.Gauge(metrics.NewMetricId(NotifyMetricNumLast, level)).Set(event.CostMs()) + rc.R.Rt(metrics.NewMetricId(NotifyRt, level), &metrics.RtOpts{}).Observe(event.CostMs()) } // directoryHandler handles directory metrics @@ -116,15 +94,15 @@ func (rc *registryCollector) directoryHandler(event *RegistryMetricsEvent) { typ := event.Attachment["DirTyp"] switch typ { case NumAllInc: - rc.regRegistry.Counter(metrics.NewMetricId(DirectoryMetricNumAll, level)).Inc() + rc.R.Counter(metrics.NewMetricId(DirectoryMetricNumAll, level)).Inc() case NumAllDec: - rc.regRegistry.Counter(metrics.NewMetricId(DirectoryMetricNumAll, level)).Add(-1) + rc.R.Counter(metrics.NewMetricId(DirectoryMetricNumAll, level)).Add(-1) case NumDisableTotal: - rc.regRegistry.Counter(metrics.NewMetricId(DirectoryMetricNumDisable, level)).Inc() + rc.R.Counter(metrics.NewMetricId(DirectoryMetricNumDisable, level)).Inc() case NumToReconnectTotal: - rc.regRegistry.Counter(metrics.NewMetricId(DirectoryMetricNumToReconnect, level)).Inc() + rc.R.Counter(metrics.NewMetricId(DirectoryMetricNumToReconnect, level)).Inc() case NumValidTotal: - rc.regRegistry.Counter(metrics.NewMetricId(DirectoryMetricNumValid, level)).Inc() + rc.R.Counter(metrics.NewMetricId(DirectoryMetricNumValid, level)).Inc() default: } @@ -134,20 +112,15 @@ func (rc *registryCollector) directoryHandler(event *RegistryMetricsEvent) { 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()) + level := metrics.GetApplicationLevel() + rc.StateCount(ServiceRegisterMetricRequests, ServiceRegisterMetricRequestsSucceed, ServiceRegisterMetricRequestsFailed, level, event.Succ) + rc.R.Rt(metrics.NewMetricId(RegisterServiceRt, level), &metrics.RtOpts{}).Observe(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) + level := metrics.GetApplicationLevel() + rc.StateCount(ServiceSubscribeMetricNum, ServiceSubscribeMetricNumSucceed, ServiceSubscribeMetricNumFailed, level, event.Succ) } diff --git a/metrics/registry/metric_set.go b/metrics/registry/metric_set.go index 02408bd153..27ea475510 100644 --- a/metrics/registry/metric_set.go +++ b/metrics/registry/metric_set.go @@ -40,14 +40,6 @@ const ( 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") @@ -79,23 +71,11 @@ var ( 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") + RegisterServiceRt = metrics.NewMetricKey("dubbo_register_service_rt_milliseconds", "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") + RegisterRt = metrics.NewMetricKey("dubbo_register_rt_milliseconds", "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") + NotifyRt = metrics.NewMetricKey("dubbo_notify_rt_milliseconds", "Notify Time") ) From 98188e4c198d36c0872a407cb3fd4d5b248f9a41 Mon Sep 17 00:00:00 2001 From: wudong5 <63356845+wudong5@users.noreply.github.com> Date: Mon, 28 Aug 2023 11:12:57 +0800 Subject: [PATCH 02/22] fix registry primitiveURL (#2385) fixes #2348 --- common/url.go | 3 +++ config/registry_config_test.go | 3 +++ 2 files changed, 6 insertions(+) diff --git a/common/url.go b/common/url.go index 2824ec68dd..6590ebfe9d 100644 --- a/common/url.go +++ b/common/url.go @@ -279,6 +279,9 @@ func NewURL(urlString string, opts ...Option) (*URL, error) { for _, opt := range opts { opt(&s) } + if s.params.Get(constant.RegistryGroupKey) != "" { + s.PrimitiveURL = strings.Join([]string{s.PrimitiveURL, s.params.Get(constant.RegistryGroupKey)}, constant.PathSeparator) + } return &s, nil } diff --git a/config/registry_config_test.go b/config/registry_config_test.go index cf9ff61d05..fdd3b2aa8e 100644 --- a/config/registry_config_test.go +++ b/config/registry_config_test.go @@ -46,6 +46,7 @@ func TestLoadRegistries(t *testing.T) { urls := loadRegistries(target, regs, common.CONSUMER) t.Logf("loadRegistries() = urls:%v", urls) assert.Equal(t, "127.0.0.2:2181,128.0.0.1:2181", urls[0].Location) + assert.Equal(t, "service-discovery-registry://127.0.0.2:2181,128.0.0.1:2181/shanghai_idc", urls[0].PrimitiveURL) } func TestLoadRegistries1(t *testing.T) { @@ -64,6 +65,7 @@ func TestLoadRegistries1(t *testing.T) { urls := loadRegistries(target, regs, common.CONSUMER) t.Logf("loadRegistries() = urls:%v", urls) assert.Equal(t, "127.0.0.2:2181", urls[0].Location) + assert.Equal(t, "service-discovery-registry://127.0.0.2:2181/shanghai_idc", urls[0].PrimitiveURL) } func TestRegistryTypeAll(t *testing.T) { @@ -77,6 +79,7 @@ func TestRegistryTypeAll(t *testing.T) { } urls := loadRegistries(target, regs, common.PROVIDER) assert.Equal(t, 2, len(urls)) + assert.Equal(t, "service-discovery-registry://127.0.0.2:2181", urls[0].PrimitiveURL) } func TestTranslateRegistryAddress(t *testing.T) { From 2e4f4b10a3346210391d18834c0143b7782af565 Mon Sep 17 00:00:00 2001 From: finalt Date: Mon, 28 Aug 2023 11:13:30 +0800 Subject: [PATCH 03/22] Nacos support subscribe to all with '*' (#2374) --- registry/nacos/listener.go | 31 ++++++++++ registry/nacos/registry.go | 119 ++++++++++++++++++++++++++++++------- 2 files changed, 130 insertions(+), 20 deletions(-) diff --git a/registry/nacos/listener.go b/registry/nacos/listener.go index a8e8f96557..5201b2d38f 100644 --- a/registry/nacos/listener.go +++ b/registry/nacos/listener.go @@ -75,6 +75,20 @@ func NewNacosListener(url, regURL *common.URL, namingClient *nacosClient.NacosNa return listener, err } +// NewNacosListener creates a data listener for nacos +func NewNacosListenerWithServiceName(serviceName string, url, regURL *common.URL, namingClient *nacosClient.NacosNamingClient) (*nacosListener, error) { + listener := &nacosListener{ + namingClient: namingClient, + listenURL: url, + regURL: regURL, + events: gxchan.NewUnboundedChan(32), + instanceMap: map[string]model.Instance{}, + done: make(chan struct{}), + } + err := listener.startListenWithServiceName(serviceName) + return listener, err +} + func generateUrl(instance model.Instance) *common.URL { if instance.Metadata == nil { logger.Errorf("nacos instance metadata is empty,instance:%+v", instance) @@ -191,6 +205,23 @@ func (nl *nacosListener) startListen() error { return nil } +func (nl *nacosListener) startListenWithServiceName(serviceName string) error { + if nl.namingClient == nil { + return perrors.New("nacos naming namingClient stopped") + } + nl.subscribeParam = createSubscribeParamWithServiceName(serviceName, nl.regURL, nl.Callback) + if nl.subscribeParam == nil { + return perrors.New("create nacos subscribeParam failed") + } + go func() { + err := nl.namingClient.Client().Subscribe(nl.subscribeParam) + if err == nil { + listenerCache.Store(nl.subscribeParam.ServiceName+nl.subscribeParam.GroupName, nl) + } + }() + return nil +} + func (nl *nacosListener) stopListen() error { return nl.namingClient.Client().Unsubscribe(nl.subscribeParam) } diff --git a/registry/nacos/registry.go b/registry/nacos/registry.go index bfb45754c8..42f1730949 100644 --- a/registry/nacos/registry.go +++ b/registry/nacos/registry.go @@ -169,36 +169,95 @@ func (nr *nacosRegistry) Subscribe(url *common.URL, notifyListener registry.Noti if role != common.CONSUMER { return nil } + serviceName := getServiceName(url) + if serviceName == "*" { + // Subscribe to all services + for { + if !nr.IsAvailable() { + logger.Warnf("event listener game over.") + return perrors.New("nacosRegistry is not available.") + } - for { - if !nr.IsAvailable() { - logger.Warnf("event listener game over.") - return perrors.New("nacosRegistry is not available.") - } + services, err := nr.getAllSubscribeServiceNames() + if err != nil { + if !nr.IsAvailable() { + logger.Warnf("event listener game over.") + return err + } + logger.Warnf("getAllServices() = err:%v", perrors.WithStack(err)) + time.Sleep(time.Duration(RegistryConnDelay) * time.Second) + continue + } - listener, err := nr.subscribe(url) - defer metrics.Publish(metricsRegistry.NewSubscribeEvent(err == nil)) - if err != nil { + for _, service := range services { + listener, err := nr.subscribeToService(url, service) + metrics.Publish(metricsRegistry.NewSubscribeEvent(err == nil)) + if err != nil { + logger.Warnf("Failed to subscribe to service '%s': %v", service, err) + continue + } + + nr.handleServiceEvents(listener, notifyListener) + } + } + } else { + // Subscribe to a specific service + for { if !nr.IsAvailable() { logger.Warnf("event listener game over.") - return err + return perrors.New("nacosRegistry is not available.") } - logger.Warnf("getListener() = err:%v", perrors.WithStack(err)) - time.Sleep(time.Duration(RegistryConnDelay) * time.Second) - continue - } - for { - serviceEvent, err := listener.Next() + listener, err := nr.subscribe(url) + metrics.Publish(metricsRegistry.NewSubscribeEvent(err == nil)) if err != nil { - logger.Warnf("Selector.watch() = error{%v}", perrors.WithStack(err)) - listener.Close() - return err + if !nr.IsAvailable() { + logger.Warnf("event listener game over.") + return err + } + logger.Warnf("getListener() = err:%v", perrors.WithStack(err)) + time.Sleep(time.Duration(RegistryConnDelay) * time.Second) + continue } - logger.Infof("[Nacos Registry] Update begin, service event: %v", serviceEvent.String()) - notifyListener.Notify(serviceEvent) + nr.handleServiceEvents(listener, notifyListener) + } + } +} + +// getAllServices retrieves the list of all services from the registry +func (nr *nacosRegistry) getAllSubscribeServiceNames() ([]string, error) { + services, err := nr.namingClient.Client().GetAllServicesInfo(vo.GetAllServiceInfoParam{ + GroupName: nr.GetParam(constant.RegistryGroupKey, defaultGroup), + PageNo: 1, + PageSize: 10, + }) + subScribeServiceNames := []string{} + for _, dom := range services.Doms { + if strings.HasPrefix(dom, "providers:") { + subScribeServiceNames = append(subScribeServiceNames, dom) } } + + return subScribeServiceNames, err +} + +// subscribeToService subscribes to a specific service in the registry +func (nr *nacosRegistry) subscribeToService(url *common.URL, service string) (listener registry.Listener, err error) { + return NewNacosListenerWithServiceName(service, url, nr.URL, nr.namingClient) +} + +// handleServiceEvents receives service events from the listener and notifies the notifyListener +func (nr *nacosRegistry) handleServiceEvents(listener registry.Listener, notifyListener registry.NotifyListener) { + for { + serviceEvent, err := listener.Next() + if err != nil { + logger.Warnf("Selector.watch() = error{%v}", perrors.WithStack(err)) + listener.Close() + return + } + logger.Infof("[Nacos Registry] Update begin, service event: %v", serviceEvent.String()) + notifyListener.Notify(serviceEvent) + } } // UnSubscribe : @@ -256,6 +315,26 @@ func createSubscribeParam(url, regUrl *common.URL, cb callback) *vo.SubscribePar } } +func createSubscribeParamWithServiceName(serviceName string, regUrl *common.URL, cb callback) *vo.SubscribeParam { + groupName := regUrl.GetParam(constant.RegistryGroupKey, defaultGroup) + if cb == nil { + v, ok := listenerCache.Load(serviceName + groupName) + if !ok { + return nil + } + listener, ok := v.(*nacosListener) + if !ok { + return nil + } + cb = listener.Callback + } + return &vo.SubscribeParam{ + ServiceName: serviceName, + SubscribeCallback: cb, + GroupName: groupName, + } +} + // GetURL gets its registration URL func (nr *nacosRegistry) GetURL() *common.URL { return nr.URL From 727a2d8bf4e3eb1becb1095589fb5326c4fa5c40 Mon Sep 17 00:00:00 2001 From: Wang Guan Date: Mon, 28 Aug 2023 11:24:49 +0800 Subject: [PATCH 04/22] feat: optimize the integration of otel tracing (#2387) fixes #2386 --- .../version.go => common/constant/otel.go | 17 +- common/extension/otel_trace.go | 58 +++++++ config/otel_config.go | 115 +++++++++++++ .../otel_config_test.go | 46 ++--- config/root_config.go | 10 ++ filter/otel/trace/attachment.go | 2 +- filter/otel/trace/filter.go | 13 +- go.mod | 32 ++-- go.sum | 160 +++++++++++++++--- imports/imports.go | 4 + otel/trace/exporter.go | 110 ++++++++++++ otel/trace/jaeger/exporter.go | 70 ++++++++ otel/trace/otlp/exporter.go | 104 ++++++++++++ otel/trace/stdout/exporter.go | 69 ++++++++ otel/trace/zipkin/exporter.go | 70 ++++++++ 15 files changed, 785 insertions(+), 95 deletions(-) rename filter/otel/trace/version.go => common/constant/otel.go (70%) create mode 100644 common/extension/otel_trace.go create mode 100644 config/otel_config.go rename filter/otel/trace/version_test.go => config/otel_config_test.go (54%) create mode 100644 otel/trace/exporter.go create mode 100644 otel/trace/jaeger/exporter.go create mode 100644 otel/trace/otlp/exporter.go create mode 100644 otel/trace/stdout/exporter.go create mode 100644 otel/trace/zipkin/exporter.go diff --git a/filter/otel/trace/version.go b/common/constant/otel.go similarity index 70% rename from filter/otel/trace/version.go rename to common/constant/otel.go index d266fcee4a..9bfeb27b45 100644 --- a/filter/otel/trace/version.go +++ b/common/constant/otel.go @@ -15,18 +15,9 @@ * limitations under the License. */ -package trace +package constant -import ( - "dubbo.apache.org/dubbo-go/v3/common/constant" +const ( + OtelPackageName = "go.opentelemetry.io/otel" + OtelPackageVersion = "v1.10.0" ) - -// Version is the current release version of the dubbogo instrumentation. -func Version() string { - return constant.Version -} - -// SemVersion is the semantic version to be supplied to tracer/meter creation. -func SemVersion() string { - return "semver:" + Version() -} diff --git a/common/extension/otel_trace.go b/common/extension/otel_trace.go new file mode 100644 index 0000000000..f8023d7a09 --- /dev/null +++ b/common/extension/otel_trace.go @@ -0,0 +1,58 @@ +/* + * 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 extension + +import ( + "context" +) + +import ( + "dubbo.apache.org/dubbo-go/v3/otel/trace" +) + +import ( + "github.com/dubbogo/gost/log/logger" +) + +var traceExporterMap = make(map[string]func(config *trace.ExporterConfig) (trace.Exporter, error), 4) + +func SetTraceExporter(name string, createFunc func(config *trace.ExporterConfig) (trace.Exporter, error)) { + traceExporterMap[name] = createFunc +} + +func GetTraceExporter(name string, config *trace.ExporterConfig) (trace.Exporter, error) { + createFunc, ok := traceExporterMap[name] + if !ok { + panic("Cannot find the trace provider with name " + name) + } + return createFunc(config) +} + +func GetTraceShutdownCallback() func() { + return func() { + for name, createFunc := range traceExporterMap { + if exporter, err := createFunc(nil); err == nil { + if err := exporter.GetTracerProvider().Shutdown(context.Background()); err != nil { + logger.Errorf("Graceful shutdown --- Failed to shutdown trace provider %s, error: %s", name, err.Error()) + } else { + logger.Infof("Graceful shutdown --- Tracer provider of %s", name) + } + } + } + } +} diff --git a/config/otel_config.go b/config/otel_config.go new file mode 100644 index 0000000000..6c819fffd8 --- /dev/null +++ b/config/otel_config.go @@ -0,0 +1,115 @@ +/* + * 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 config + +import ( + "github.com/creasty/defaults" + "github.com/dubbogo/gost/log/logger" + "github.com/pkg/errors" + "go.opentelemetry.io/otel" +) + +import ( + "dubbo.apache.org/dubbo-go/v3/common/extension" + "dubbo.apache.org/dubbo-go/v3/otel/trace" +) + +type OtelConfig struct { + TraceConfig *OtelTraceConfig `yaml:"trace" json:"trace,omitempty" property:"trace"` +} + +type OtelTraceConfig struct { + Enable *bool `default:"false" yaml:"enable" json:"enable,omitempty" property:"enable"` + Exporter string `default:"stdout" yaml:"exporter" json:"exporter,omitempty" property:"exporter"` // stdout, jaeger, zipkin, otlp-http, otlp-grpc + Endpoint string `default:"" yaml:"endpoint" json:"endpoint,omitempty" property:"endpoint"` + Propagator string `default:"w3c" yaml:"propagator" json:"propagator,omitempty" property:"propagator"` // one of w3c(standard), b3(for zipkin), + SampleMode string `default:"ratio" yaml:"sample-mode" json:"sample-mode,omitempty" property:"sample-mode"` // one of always, never, ratio + SampleRatio float64 `default:"0.5" yaml:"sample-ratio" json:"sample-ratio,omitempty" property:"sample-ratio"` // [0.0, 1.0] +} + +func (oc *OtelConfig) Init(appConfig *ApplicationConfig) error { + if oc == nil { + return errors.New("otel config is nil") + } + if err := defaults.Set(oc); err != nil { + return err + } + if err := verify(oc); err != nil { + return err + } + if *oc.TraceConfig.Enable { + extension.AddCustomShutdownCallback(extension.GetTraceShutdownCallback()) + return oc.TraceConfig.init(appConfig) + } + + return nil +} + +func (c *OtelTraceConfig) init(appConfig *ApplicationConfig) error { + exporter, err := extension.GetTraceExporter(c.Exporter, c.toTraceProviderConfig(appConfig)) + if err != nil { + return err + } + otel.SetTracerProvider(exporter.GetTracerProvider()) + otel.SetTextMapPropagator(exporter.GetPropagator()) + + // print trace exporter configuration + if c.Exporter == "stdout" { + logger.Infof("enable %s trace provider with propagator: %s", c.Exporter, c.Propagator) + } else { + logger.Infof("enable %s trace provider with endpoint: %s, propagator: %s", c.Exporter, c.Endpoint, c.Propagator) + } + logger.Infof("sample mode: %s", c.SampleMode) + if c.SampleMode == "ratio" { + logger.Infof("sample ratio: %.2f", c.SampleRatio) + } + + return nil +} + +func (c *OtelTraceConfig) toTraceProviderConfig(a *ApplicationConfig) *trace.ExporterConfig { + tpc := &trace.ExporterConfig{ + Exporter: c.Exporter, + Endpoint: c.Endpoint, + SampleMode: c.SampleMode, + SampleRatio: c.SampleRatio, + Propagator: c.Propagator, + ServiceNamespace: a.Organization, + ServiceName: a.Name, + ServiceVersion: a.Version, + } + return tpc +} + +type OtelConfigBuilder struct { + otelConfig *OtelConfig +} + +func NewOtelConfigBuilder() *OtelConfigBuilder { + return &OtelConfigBuilder{ + otelConfig: &OtelConfig{ + TraceConfig: &OtelTraceConfig{}, + }, + } +} + +func (ocb *OtelConfigBuilder) Build() *OtelConfig { + return ocb.otelConfig +} + +// TODO: dynamic config diff --git a/filter/otel/trace/version_test.go b/config/otel_config_test.go similarity index 54% rename from filter/otel/trace/version_test.go rename to config/otel_config_test.go index 332be01ba3..af1b302926 100644 --- a/filter/otel/trace/version_test.go +++ b/config/otel_config_test.go @@ -15,49 +15,25 @@ * limitations under the License. */ -package trace +package config import ( "testing" ) import ( - "dubbo.apache.org/dubbo-go/v3/common/constant" + "github.com/stretchr/testify/assert" ) -type filed struct { - name string - want string -} +func TestNewOtelConfigBuilder(t *testing.T) { + config := NewOtelConfigBuilder().Build() + assert.NotNil(t, config) + assert.NotNil(t, config.TraceConfig) -func TestSemVersion(t *testing.T) { - tests := []filed{ - { - name: "test", - want: "semver:" + constant.Version, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if got := SemVersion(); got != tt.want { - t.Errorf("SemVersion() = %v, want %v", got, tt.want) - } - }) - } -} + ac := NewApplicationConfigBuilder().Build() + err := config.Init(ac) + assert.NoError(t, err) -func TestVersion(t *testing.T) { - tests := []filed{ - { - name: "test", - want: constant.Version, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if got := Version(); got != tt.want { - t.Errorf("Version() = %v, want %v", got, tt.want) - } - }) - } + tpc := config.TraceConfig.toTraceProviderConfig(ac) + assert.NotNil(t, tpc) } diff --git a/config/root_config.go b/config/root_config.go index 751770244f..724af48ab0 100644 --- a/config/root_config.go +++ b/config/root_config.go @@ -55,6 +55,7 @@ type RootConfig struct { MetadataReport *MetadataReportConfig `yaml:"metadata-report" json:"metadata-report,omitempty" property:"metadata-report"` Provider *ProviderConfig `yaml:"provider" json:"provider" property:"provider"` Consumer *ConsumerConfig `yaml:"consumer" json:"consumer" property:"consumer"` + Otel *OtelConfig `yaml:"otel" json:"otel,omitempty" property:"otel"` Metric *MetricConfig `yaml:"metrics" json:"metrics,omitempty" property:"metrics"` Tracing map[string]*TracingConfig `yaml:"tracing" json:"tracing,omitempty" property:"tracing"` Logger *LoggerConfig `yaml:"logger" json:"logger,omitempty" property:"logger"` @@ -178,6 +179,9 @@ func (rc *RootConfig) Init() error { if err := rc.MetadataReport.Init(rc); err != nil { return err } + if err := rc.Otel.Init(rc.Application); err != nil { + return err + } if err := rc.Metric.Init(); err != nil { return err } @@ -227,6 +231,7 @@ func newEmptyRootConfig() *RootConfig { Tracing: make(map[string]*TracingConfig), Provider: NewProviderConfigBuilder().Build(), Consumer: NewConsumerConfigBuilder().Build(), + Otel: NewOtelConfigBuilder().Build(), Metric: NewMetricConfigBuilder().Build(), Logger: NewLoggerConfigBuilder().Build(), Custom: NewCustomConfigBuilder().Build(), @@ -284,6 +289,11 @@ func (rb *RootConfigBuilder) SetConsumer(consumer *ConsumerConfig) *RootConfigBu return rb } +func (rb *RootConfigBuilder) SetOtel(otel *OtelConfig) *RootConfigBuilder { + rb.rootConfig.Otel = otel + return rb +} + func (rb *RootConfigBuilder) SetMetric(metric *MetricConfig) *RootConfigBuilder { rb.rootConfig.Metric = metric return rb diff --git a/filter/otel/trace/attachment.go b/filter/otel/trace/attachment.go index 6d84eff267..1bda20321a 100644 --- a/filter/otel/trace/attachment.go +++ b/filter/otel/trace/attachment.go @@ -73,7 +73,7 @@ func Inject(ctx context.Context, metadata map[string]interface{}, propagators pr }) } -// Extract returns the correlation context and span context that +// Extract returns the baggage and span context that // another service encoded in the dubbo metadata object with Inject. // This function is meant to be used on incoming requests. func Extract(ctx context.Context, metadata map[string]interface{}, propagators propagation.TextMapPropagator) (baggage.Baggage, trace.SpanContext) { diff --git a/filter/otel/trace/filter.go b/filter/otel/trace/filter.go index bf3da78258..1b9c960f16 100644 --- a/filter/otel/trace/filter.go +++ b/filter/otel/trace/filter.go @@ -37,11 +37,8 @@ import ( "dubbo.apache.org/dubbo-go/v3/protocol" ) -const ( - instrumentationName = "dubbo.apache.org/dubbo-go/v3/oteldubbo" -) - func init() { + // TODO: use single filter to simplify filter field in configuration extension.SetFilter(constant.OTELServerTraceKey, func() filter.Filter { return &otelServerFilter{ Propagators: otel.GetTextMapPropagator(), @@ -71,8 +68,8 @@ func (f *otelServerFilter) Invoke(ctx context.Context, invoker protocol.Invoker, ctx = baggage.ContextWithBaggage(ctx, bags) tracer := f.TracerProvider.Tracer( - instrumentationName, - trace.WithInstrumentationVersion(SemVersion()), + constant.OtelPackageName, + trace.WithInstrumentationVersion(constant.OtelPackageVersion), ) ctx, span := tracer.Start( @@ -108,8 +105,8 @@ func (f *otelClientFilter) OnResponse(ctx context.Context, result protocol.Resul func (f *otelClientFilter) Invoke(ctx context.Context, invoker protocol.Invoker, invocation protocol.Invocation) protocol.Result { tracer := f.TracerProvider.Tracer( - instrumentationName, - trace.WithInstrumentationVersion(SemVersion()), + constant.OtelPackageName, + trace.WithInstrumentationVersion(constant.OtelPackageVersion), ) var span trace.Span diff --git a/go.mod b/go.mod index 89764c71f2..6c534697d1 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,7 @@ module dubbo.apache.org/dubbo-go/v3 go 1.15 require ( + cloud.google.com/go/compute/metadata v0.2.3 // indirect github.com/RoaringBitmap/roaring v1.2.3 github.com/Workiva/go-datastructures v1.0.52 github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5 @@ -10,8 +11,8 @@ require ( github.com/apache/dubbo-getty v1.4.9 github.com/apache/dubbo-go-hessian2 v1.12.2 github.com/cespare/xxhash/v2 v2.2.0 - github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4 - github.com/cncf/xds/go v0.0.0-20220314180256-7f1daf1720fc + github.com/cncf/udpa/go v0.0.0-20220112060539-c52dc94e7fbe + github.com/cncf/xds/go v0.0.0-20230310173818-32f1caf87195 github.com/creasty/defaults v1.5.2 github.com/dubbogo/go-zookeeper v1.0.4-0.20211212162352-f9d2183d89d5 github.com/dubbogo/gost v1.14.0 @@ -20,12 +21,15 @@ require ( github.com/dustin/go-humanize v1.0.1 github.com/emicklei/go-restful/v3 v3.10.1 github.com/envoyproxy/go-control-plane v0.11.0 + github.com/envoyproxy/protoc-gen-validate v0.10.0 // indirect github.com/fsnotify/fsnotify v1.6.0 github.com/go-co-op/gocron v1.9.0 + github.com/go-logr/logr v1.2.4 // indirect github.com/go-playground/validator/v10 v10.12.0 github.com/go-resty/resty/v2 v2.7.0 + github.com/golang/glog v1.1.0 // indirect github.com/golang/mock v1.6.0 - github.com/golang/protobuf v1.5.2 + github.com/golang/protobuf v1.5.3 github.com/google/go-cmp v0.5.9 github.com/google/uuid v1.3.0 github.com/gopherjs/gopherjs v0.0.0-20190910122728-9d188e94fb99 // indirect @@ -35,7 +39,6 @@ require ( github.com/influxdata/tdigest v0.0.1 github.com/jinzhu/copier v0.3.5 github.com/knadh/koanf v1.5.0 - github.com/kr/pretty v0.3.0 // indirect github.com/magiconair/properties v1.8.1 github.com/mattn/go-colorable v0.1.13 github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect @@ -49,21 +52,28 @@ require ( github.com/polarismesh/polaris-go v1.3.0 github.com/prometheus/client_golang v1.13.0 github.com/prometheus/common v0.37.0 - github.com/rogpeppe/go-internal v1.8.0 // indirect - github.com/sirupsen/logrus v1.7.0 - github.com/stretchr/testify v1.8.2 + github.com/sirupsen/logrus v1.8.1 + github.com/stretchr/testify v1.8.3 go.etcd.io/etcd/api/v3 v3.5.7 go.etcd.io/etcd/client/v2 v2.305.0 // indirect go.etcd.io/etcd/client/v3 v3.5.7 - go.opentelemetry.io/otel v1.11.0 - go.opentelemetry.io/otel/trace v1.11.0 + go.opentelemetry.io/contrib/propagators/b3 v1.10.0 + go.opentelemetry.io/otel v1.10.0 + go.opentelemetry.io/otel/exporters/jaeger v1.10.0 + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.10.0 + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.10.0 + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.10.0 + go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.10.0 + go.opentelemetry.io/otel/exporters/zipkin v1.10.0 + go.opentelemetry.io/otel/sdk v1.10.0 + go.opentelemetry.io/otel/trace v1.10.0 go.uber.org/atomic v1.10.0 go.uber.org/multierr v1.8.0 // indirect go.uber.org/zap v1.21.0 - google.golang.org/genproto v0.0.0-20221118155620-16455021b5e6 + golang.org/x/oauth2 v0.6.0 // indirect + google.golang.org/genproto v0.0.0-20221227171554-f9683d7f8bef google.golang.org/grpc v1.52.0 google.golang.org/protobuf v1.30.0 - gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect gopkg.in/natefinch/lumberjack.v2 v2.2.1 gopkg.in/yaml.v2 v2.4.0 ) diff --git a/go.sum b/go.sum index 3c47c9d14f..8a4f0a63b4 100644 --- a/go.sum +++ b/go.sum @@ -28,6 +28,7 @@ cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+Y cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4= cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc= cloud.google.com/go v0.99.0/go.mod h1:w0Xx2nLzqWJPuozYQX+hFfCSI8WioryfRDzkoI/Y2ZA= +cloud.google.com/go v0.100.1/go.mod h1:fs4QogzfH5n2pBXBP9vRiU+eCny7lD2vmFZy79Iuw1U= cloud.google.com/go v0.100.2/go.mod h1:4Xra9TjzAeYHrl5+oeLlzbM2k3mjVhZh4UqTZ//w99A= cloud.google.com/go v0.102.0/go.mod h1:oWcCzKlqJ5zgHQt9YsaeTY9KzIvjyy0ArmiBUgpQ+nc= cloud.google.com/go v0.102.1/go.mod h1:XZ77E9qnTEnrgEOvr4xzfdX5TRo7fB4T2F4O6+34hIU= @@ -40,6 +41,7 @@ cloud.google.com/go/accesscontextmanager v1.3.0/go.mod h1:TgCBehyr5gNMz7ZaH9xubp cloud.google.com/go/accesscontextmanager v1.4.0/go.mod h1:/Kjh7BBu/Gh83sv+K60vN9QE5NJcd80sU33vIe2IFPE= cloud.google.com/go/aiplatform v1.22.0/go.mod h1:ig5Nct50bZlzV6NvKaTwmplLLddFx0YReh9WfTO5jKw= cloud.google.com/go/aiplatform v1.24.0/go.mod h1:67UUvRBKG6GTayHKV8DBv2RtR1t93YRu5B1P3x99mYY= +cloud.google.com/go/aiplatform v1.27.0/go.mod h1:Bvxqtl40l0WImSb04d0hXFU7gDOiq9jQmorivIiWcKg= cloud.google.com/go/analytics v0.11.0/go.mod h1:DjEWCu41bVbYcKyvlws9Er60YE4a//bK6mnhWvQeFNI= cloud.google.com/go/analytics v0.12.0/go.mod h1:gkfj9h6XRf9+TS4bmuhPEShsh3hH8PAZzm/41OOhQd4= cloud.google.com/go/apigateway v1.3.0/go.mod h1:89Z8Bhpmxu6AmUxuVRg/ECRGReEdiP3vQtk4Z1J9rJk= @@ -82,6 +84,7 @@ cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4g cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= cloud.google.com/go/bigquery v1.42.0/go.mod h1:8dRTJxhtG+vwBKzE5OseQn/hiydoQN3EedCaOdYmxRA= cloud.google.com/go/bigquery v1.43.0/go.mod h1:ZMQcXHsl+xmU1z36G2jNGZmKp9zNY5BUua5wDgmNCfw= +cloud.google.com/go/bigquery v1.44.0/go.mod h1:0Y33VqXTEsbamHJvJHdFmtqHvMIY28aK1+dFsvaChGc= cloud.google.com/go/billing v1.4.0/go.mod h1:g9IdKBEFlItS8bTtlrZdVLWSSdSyFUZKXNS02zKMOZY= cloud.google.com/go/billing v1.5.0/go.mod h1:mztb1tBc3QekhjSgmpf/CV4LzWXLzCArwpLmP2Gm88s= cloud.google.com/go/billing v1.6.0/go.mod h1:WoXzguj+BeHXPbKfNWkqVtDdzORazmCjraY+vrxcyvI= @@ -110,11 +113,15 @@ cloud.google.com/go/compute v1.6.1/go.mod h1:g85FgpzFvNULZ+S8AYq87axRKuf2Kh7deLq cloud.google.com/go/compute v1.7.0/go.mod h1:435lt8av5oL9P3fv1OEzSbSUe+ybHXGMPQHHZWZxy9U= cloud.google.com/go/compute v1.10.0/go.mod h1:ER5CLbMxl90o2jtNbGSbtfOpQKR0t15FOtRsugnLrlU= cloud.google.com/go/compute v1.12.0/go.mod h1:e8yNOBcBONZU1vJKCvCoDw/4JQsA0dpM4x/6PIIOocU= -cloud.google.com/go/compute v1.12.1 h1:gKVJMEyqV5c/UnpzjjQbo3Rjvvqpr9B1DFSbJC4OXr0= cloud.google.com/go/compute v1.12.1/go.mod h1:e8yNOBcBONZU1vJKCvCoDw/4JQsA0dpM4x/6PIIOocU= +cloud.google.com/go/compute v1.13.0/go.mod h1:5aPTS0cUNMIc1CE546K+Th6weJUNQErARyZtRXDJ8GE= +cloud.google.com/go/compute v1.14.0 h1:hfm2+FfxVmnRlh6LpB7cg1ZNU+5edAHmW679JePztk0= +cloud.google.com/go/compute v1.14.0/go.mod h1:YfLtxrj9sU4Yxv+sXzZkyPjEyPBZfXHUvjxega5vAdo= cloud.google.com/go/compute/metadata v0.1.0/go.mod h1:Z1VN+bulIf6bt4P/C37K4DyZYZEXYonfTBHHFPO/4UU= -cloud.google.com/go/compute/metadata v0.2.1 h1:efOwf5ymceDhK6PKMnnrTHP4pppY5L22mle96M1yP48= +cloud.google.com/go/compute/metadata v0.2.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= cloud.google.com/go/compute/metadata v0.2.1/go.mod h1:jgHgmJd2RKBGzXqF5LR2EZMGxBkeanZ9wwa75XHJgOM= +cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= +cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= cloud.google.com/go/contactcenterinsights v1.3.0/go.mod h1:Eu2oemoePuEFc/xKFPjbTuPSj0fYJcPls9TFlPNnHHY= cloud.google.com/go/contactcenterinsights v1.4.0/go.mod h1:L2YzkGbPsv+vMQMCADxJoT9YiTTnSEd6fEvCeHTYVck= cloud.google.com/go/container v1.6.0/go.mod h1:Xazp7GjJSeUYo688S+6J5V+n/t+G5sKBTFkKNudGRxg= @@ -143,6 +150,7 @@ cloud.google.com/go/dataqna v0.5.0/go.mod h1:90Hyk596ft3zUQ8NkFfvICSIfHFh1Bc7C4c cloud.google.com/go/dataqna v0.6.0/go.mod h1:1lqNpM7rqNLVgWBJyk5NF6Uen2PHym0jtVJonplVsDA= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= +cloud.google.com/go/datastore v1.10.0/go.mod h1:PC5UzAmDEkAmkfaknstTYbNpgE49HAgW2J1gcgUfmdM= cloud.google.com/go/datastream v1.2.0/go.mod h1:i/uTP8/fZwgATHS/XFu0TcNUhuA0twZxxQ3EyCUQMwo= cloud.google.com/go/datastream v1.3.0/go.mod h1:cqlOX8xlyYF/uxhiKn6Hbv6WjwPPuI9W2M9SAXwaLLQ= cloud.google.com/go/datastream v1.4.0/go.mod h1:h9dpzScPhDTs5noEMQVWP8Wx8AFBRyS0s8KWPx/9r0g= @@ -164,6 +172,7 @@ cloud.google.com/go/domains v0.6.0/go.mod h1:T9Rz3GasrpYk6mEGHh4rymIhjlnIuB4ofT1 cloud.google.com/go/domains v0.7.0/go.mod h1:PtZeqS1xjnXuRPKE/88Iru/LdfoRyEHYA9nFQf4UKpg= cloud.google.com/go/edgecontainer v0.1.0/go.mod h1:WgkZ9tp10bFxqO8BLPqv2LlfmQF1X8lZqwW4r1BTajk= cloud.google.com/go/edgecontainer v0.2.0/go.mod h1:RTmLijy+lGpQ7BXuTDa4C4ssxyXT34NIuHIgKuP4s5w= +cloud.google.com/go/errorreporting v0.3.0/go.mod h1:xsP2yaAp+OAW4OIm60An2bbLpqIhKXdWR/tawvl7QzU= cloud.google.com/go/essentialcontacts v1.3.0/go.mod h1:r+OnHa5jfj90qIfZDO/VztSFqbQan7HV75p8sA+mdGI= cloud.google.com/go/essentialcontacts v1.4.0/go.mod h1:8tRldvHYsmnBCHdFpvU+GL75oWiBKl80BiqlFh9tp+8= cloud.google.com/go/eventarc v1.7.0/go.mod h1:6ctpF3zTnaQCxUjHUdcfgcA1A2T309+omHZth7gDfmc= @@ -171,6 +180,7 @@ cloud.google.com/go/eventarc v1.8.0/go.mod h1:imbzxkyAU4ubfsaKYdQg04WS1NvncblHEu cloud.google.com/go/filestore v1.3.0/go.mod h1:+qbvHGvXU1HaKX2nD0WEPo92TP/8AQuCVEBXNY9z0+w= cloud.google.com/go/filestore v1.4.0/go.mod h1:PaG5oDfo9r224f8OYXURtAsY+Fbyq/bLYoINEK8XQAI= cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= +cloud.google.com/go/firestore v1.9.0/go.mod h1:HMkjKHNTtRyZNiMzu7YAsLr9K3X2udY2AMwDaMEQiiE= cloud.google.com/go/functions v1.6.0/go.mod h1:3H1UA3qiIPRWD7PeZKLvHZ9SaQhR26XIJcC0A5GbvAk= cloud.google.com/go/functions v1.7.0/go.mod h1:+d+QBcWM+RsrgZfV9xo6KfA1GlzJfxcfZcRPEhDDfzg= cloud.google.com/go/functions v1.8.0/go.mod h1:RTZ4/HsQjIqIYP9a9YPbU+QFoQsAlYgrwOXJWHn1POY= @@ -190,16 +200,19 @@ cloud.google.com/go/gkemulticloud v0.4.0/go.mod h1:E9gxVBnseLWCk24ch+P9+B2CoDFJZ cloud.google.com/go/grafeas v0.2.0/go.mod h1:KhxgtF2hb0P191HlY5besjYm6MqTSTj3LSI+M+ByZHc= cloud.google.com/go/gsuiteaddons v1.3.0/go.mod h1:EUNK/J1lZEZO8yPtykKxLXI6JSVN2rg9bN8SXOa0bgM= cloud.google.com/go/gsuiteaddons v1.4.0/go.mod h1:rZK5I8hht7u7HxFQcFei0+AtfS9uSushomRlg+3ua1o= +cloud.google.com/go/iam v0.1.0/go.mod h1:vcUNEa0pEm0qRVpmWepWaFMIAI8/hjB9mO8rNCJtF6c= cloud.google.com/go/iam v0.3.0/go.mod h1:XzJPvDayI+9zsASAFO68Hk07u3z+f+JrT2xXNdp4bnY= cloud.google.com/go/iam v0.5.0/go.mod h1:wPU9Vt0P4UmCux7mqtRu6jcpPAb74cP1fh50J3QpkUc= cloud.google.com/go/iam v0.6.0/go.mod h1:+1AH33ueBne5MzYccyMHtEKqLE4/kJOibtffMHDMFMc= cloud.google.com/go/iam v0.7.0/go.mod h1:H5Br8wRaDGNc8XP3keLc4unfUUZeyH3Sfl9XpQEYOeg= +cloud.google.com/go/iam v0.8.0/go.mod h1:lga0/y3iH6CX7sYqypWJ33hf7kkfXJag67naqGESjkE= cloud.google.com/go/iap v1.4.0/go.mod h1:RGFwRJdihTINIe4wZ2iCP0zF/qu18ZwyKxrhMhygBEc= cloud.google.com/go/iap v1.5.0/go.mod h1:UH/CGgKd4KyohZL5Pt0jSKE4m3FR51qg6FKQ/z/Ix9A= cloud.google.com/go/ids v1.1.0/go.mod h1:WIuwCaYVOzHIj2OhN9HAwvW+DBdmUAdcWlFxRl+KubM= cloud.google.com/go/ids v1.2.0/go.mod h1:5WXvp4n25S0rA/mQWAg1YEEBBq6/s+7ml1RDCW1IrcY= cloud.google.com/go/iot v1.3.0/go.mod h1:r7RGh2B61+B8oz0AGE+J72AhA0G7tdXItODWsaA2oLs= cloud.google.com/go/iot v1.4.0/go.mod h1:dIDxPOn0UvNDUMD8Ger7FIaTuvMkj+aGk94RPP0iV+g= +cloud.google.com/go/kms v1.4.0/go.mod h1:fajBHndQ+6ubNw6Ss2sSd+SWvjL26RNo/dr7uxsnnOA= cloud.google.com/go/kms v1.5.0/go.mod h1:QJS2YY0eJGBg3mnDfuaCyLauWwBJiHRboYxJ++1xJNg= cloud.google.com/go/kms v1.6.0/go.mod h1:Jjy850yySiasBUDi6KFUwUv2n1+o7QZFyuUJg6OgjA0= cloud.google.com/go/language v1.4.0/go.mod h1:F9dRpNFQmJbkaop6g0JhSBXCNlO90e1KWx5iDdxbWic= @@ -208,10 +221,12 @@ cloud.google.com/go/language v1.7.0/go.mod h1:DJ6dYN/W+SQOjF8e1hLQXMF21AkH2w9wiP cloud.google.com/go/language v1.8.0/go.mod h1:qYPVHf7SPoNNiCL2Dr0FfEFNil1qi3pQEyygwpgVKB8= cloud.google.com/go/lifesciences v0.5.0/go.mod h1:3oIKy8ycWGPUyZDR/8RNnTOYevhaMLqh5vLUXs9zvT8= cloud.google.com/go/lifesciences v0.6.0/go.mod h1:ddj6tSX/7BOnhxCSd3ZcETvtNr8NZ6t/iPhY2Tyfu08= +cloud.google.com/go/logging v1.6.1/go.mod h1:5ZO0mHHbvm8gEmeEUHrmDlTDSu5imF6MUP9OfilNXBw= cloud.google.com/go/longrunning v0.1.1/go.mod h1:UUFxuDWkv22EuY93jjmDMFT5GPQKeFVJBIF6QlTqdsE= cloud.google.com/go/longrunning v0.3.0/go.mod h1:qth9Y41RRSUE69rDcOn6DdK3HfQfsUI0YSmW3iIlLJc= cloud.google.com/go/managedidentities v1.3.0/go.mod h1:UzlW3cBOiPrzucO5qWkNkh0w33KFtBJU281hacNvsdE= cloud.google.com/go/managedidentities v1.4.0/go.mod h1:NWSBYbEMgqmbZsLIyKvxrYbtqOsxY1ZrGM+9RgDqInM= +cloud.google.com/go/maps v0.1.0/go.mod h1:BQM97WGyfw9FWEmQMpZ5T6cpovXXSd1cGmFma94eubI= cloud.google.com/go/mediatranslation v0.5.0/go.mod h1:jGPUhGTybqsPQn91pNXw0xVHfuJ3leR1wj37oU3y1f4= cloud.google.com/go/mediatranslation v0.6.0/go.mod h1:hHdBCTYNigsBxshbznuIMFNe5QXEowAuNmmC7h8pu5w= cloud.google.com/go/memcache v1.4.0/go.mod h1:rTOfiGZtJX1AaFUrOgsMHX5kAzaTQ8azHiuDoTPzNsE= @@ -260,6 +275,9 @@ cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2k cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= +cloud.google.com/go/pubsub v1.26.0/go.mod h1:QgBH3U/jdJy/ftjPhTkyXNj543Tin1pRYcdcPRnFIRI= +cloud.google.com/go/pubsub v1.27.1/go.mod h1:hQN39ymbV9geqBnfQq6Xf63yNhUAhv9CZhzp5O6qsW0= +cloud.google.com/go/pubsublite v1.5.0/go.mod h1:xapqNQ1CuLfGi23Yda/9l4bBCKz/wC3KIJ5gKcxveZg= cloud.google.com/go/recaptchaenterprise v1.3.1/go.mod h1:OdD+q+y4XGeAlxRaMn1Y7/GveP6zmq76byL6tjPE7d4= cloud.google.com/go/recaptchaenterprise/v2 v2.1.0/go.mod h1:w9yVqajwroDNTfGuhmOjPDN//rZGySaf6PtFVcSCa7o= cloud.google.com/go/recaptchaenterprise/v2 v2.2.0/go.mod h1:/Zu5jisWGeERrd5HnlS3EUGb/D335f9k51B/FVil0jk= @@ -314,6 +332,7 @@ cloud.google.com/go/serviceusage v1.3.0/go.mod h1:Hya1cozXM4SeSKTAgGXgj97GlqUvF5 cloud.google.com/go/serviceusage v1.4.0/go.mod h1:SB4yxXSaYVuUBYUml6qklyONXNLt83U0Rb+CXyhjEeU= cloud.google.com/go/shell v1.3.0/go.mod h1:VZ9HmRjZBsjLGXusm7K5Q5lzzByZmJHf1d0IWHEN5X4= cloud.google.com/go/shell v1.4.0/go.mod h1:HDxPzZf3GkDdhExzD/gs8Grqk+dmYcEjGShZgYa9URw= +cloud.google.com/go/spanner v1.41.0/go.mod h1:MLYDBJR/dY4Wt7ZaMIQ7rXOTLjYrmxLE/5ve9vFfWos= cloud.google.com/go/speech v1.6.0/go.mod h1:79tcr4FHCimOp56lwC01xnt/WPJZc4v3gzyT7FoBkCM= cloud.google.com/go/speech v1.7.0/go.mod h1:KptqL+BAQIhMsj1kOP2la5DSEEerPDuOP/2mmkhHhZQ= cloud.google.com/go/speech v1.8.0/go.mod h1:9bYIl1/tjsAnMgKGHKmBZzXKEkGgtU+MpdDPTE9f7y0= @@ -354,6 +373,7 @@ cloud.google.com/go/vision/v2 v2.4.0/go.mod h1:VtI579ll9RpVTrdKdkMzckdnwMyX2JILb cloud.google.com/go/vision/v2 v2.5.0/go.mod h1:MmaezXOOE+IWa+cS7OhRRLK2cNv1ZL98zhqFFZaaH2E= cloud.google.com/go/vmmigration v1.2.0/go.mod h1:IRf0o7myyWFSmVR1ItrBSFLFD/rJkfDCUTO4vLlJvsE= cloud.google.com/go/vmmigration v1.3.0/go.mod h1:oGJ6ZgGPQOFdjHuocGcLqX4lc98YQ7Ygq8YQwHh9A7g= +cloud.google.com/go/vmwareengine v0.1.0/go.mod h1:RsdNEf/8UDvKllXhMz5J40XxDrNJNN4sagiox+OI208= cloud.google.com/go/vpcaccess v1.4.0/go.mod h1:aQHVbTWDYUR1EbTApSVvMq1EnT57ppDmQzZ3imqIk4w= cloud.google.com/go/vpcaccess v1.5.0/go.mod h1:drmg4HLk9NkZpGfCmZ3Tz0Bwnm2+DKqViEpeEpOq0m8= cloud.google.com/go/webrisk v1.4.0/go.mod h1:Hn8X6Zr+ziE2aNd8SliSDWpEnSS1u4R9+xXZmFiHmGE= @@ -378,7 +398,9 @@ github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAE github.com/RoaringBitmap/roaring v1.2.3 h1:yqreLINqIrX22ErkKI0vY47/ivtJr6n+kMhVOVmhWBY= github.com/RoaringBitmap/roaring v1.2.3/go.mod h1:plvDsJQpxOC5bw8LRteu/MLWHsHez/3y6cubLI4/1yE= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= +github.com/Shopify/sarama v1.30.0/go.mod h1:zujlQQx1kzHsh4jfV1USnptCQrHAEZ2Hk8fTKCulPVs= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= +github.com/Shopify/toxiproxy/v2 v2.1.6-0.20210914104332-15ea381dcdae/go.mod h1:/cvHQkZ1fst0EmZnA5dFtiQdWCNCFYzb+uE2vqVgvx0= github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= github.com/Workiva/go-datastructures v1.0.52 h1:PLSK6pwn8mYdaoaCZEMsXBpBotr4HHn9abU0yMQt0NI= @@ -440,8 +462,12 @@ github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7 github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs= github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= +github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4= github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= +github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8UtC4= +github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/census-instrumentation/opencensus-proto v0.4.1 h1:iKLQ0xPNFxR/2hzXZMrBo8f1j86j5WHzznCCQxV/b8g= github.com/census-instrumentation/opencensus-proto v0.4.1/go.mod h1:4T9NM4+4Vw91VeyqjLS6ao50K5bOcLKN6Q42XnYaRYw= github.com/certifi/gocertifi v0.0.0-20191021191039-0944d244cd40 h1:xvUo53O5MRZhVMJAxWCJcS5HHrqAiAG9SJ1LpMu6aAI= @@ -462,15 +488,17 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4 h1:hzAQntlaYRkVSFEfj9OTWlVV1H155FMD8BTKktLv0QI= github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= +github.com/cncf/udpa/go v0.0.0-20220112060539-c52dc94e7fbe h1:QQ3GSy+MqSHxm/d8nCtnAiZdYFd45cYZPs8vOOIYKfk= +github.com/cncf/udpa/go v0.0.0-20220112060539-c52dc94e7fbe/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20220314180256-7f1daf1720fc h1:PYXxkRUBGUMa5xgMVMDl62vEklZvKpVaxQeN9ie7Hfk= github.com/cncf/xds/go v0.0.0-20220314180256-7f1daf1720fc/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20230310173818-32f1caf87195 h1:58f1tJ1ra+zFINPlwLWvQsR9CzAKt2e+EWV2yX9oXQ4= +github.com/cncf/xds/go v0.0.0-20230310173818-32f1caf87195/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5 h1:xD/lrqdvwsc+O2bjSSi3YqY73Ke3LAiSCx49aCesA0E= github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5/go.mod h1:h6jFvWxBdQXxjopDMZyH2UVceIRfR84bdzbkoKrsWNo= @@ -528,6 +556,7 @@ github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25Kn github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= +github.com/eapache/go-resiliency v1.2.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= @@ -548,8 +577,9 @@ github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go. github.com/envoyproxy/go-control-plane v0.11.0 h1:jtLewhRR2vMRNnq2ZZUoCjUlgut+Y0+sDDWPOfwOi1o= github.com/envoyproxy/go-control-plane v0.11.0/go.mod h1:VnHyVMpzcLvCFt9yUz1UnCwHLhwx1WguiVDV7pTG/tI= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/envoyproxy/protoc-gen-validate v0.9.1 h1:PS7VIOgmSVhWUEeZwTe7z7zouA22Cr590PzXKbZHOVY= github.com/envoyproxy/protoc-gen-validate v0.9.1/go.mod h1:OKNgG7TCp5pF4d6XftA0++PMirau2/yoOwVac3AbF2w= +github.com/envoyproxy/protoc-gen-validate v0.10.0 h1:oIfnZFdC0YhpNNEX+SuIqko4cqqVZeN9IGTrhZje83Y= +github.com/envoyproxy/protoc-gen-validate v0.10.0/go.mod h1:DRjgyB0I43LtJapqN6NiRwroiAU2PaFuvk/vjgh61ss= github.com/evanphx/json-patch/v5 v5.5.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4= github.com/fastly/go-utils v0.0.0-20180712184237-d95a45783239/go.mod h1:Gdwt2ce0yfBxPvZrHkprdPPTTS3N5rwmLE8T22KBXlw= github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc= @@ -559,10 +589,12 @@ github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= github.com/form3tech-oss/jwt-go v3.2.2+incompatible h1:TcekIExNqud5crz4xD2pavyTgWiPvpYe4Xau31I0PRk= github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= +github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= -github.com/frankban/quicktest v1.10.0 h1:Gfh+GAJZOAoKZsIZeZbdn2JF10kN1XHNvjsvQK8gVkE= github.com/frankban/quicktest v1.10.0/go.mod h1:ui7WezCLWMWxVWr1GETZY3smRy0G4KWq9vcPtJmFl7Y= +github.com/frankban/quicktest v1.11.3 h1:8sXhOn0uLys67V8EsXLc6eszDs8VXWxL3iRvebPhedY= +github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= @@ -589,8 +621,9 @@ github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= +github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM= @@ -608,6 +641,7 @@ github.com/go-resty/resty/v2 v2.7.0 h1:me+K9p3uhSmXtrBZ4k9jcEAfJmuC8IivWHwaLZwPr github.com/go-resty/resty/v2 v2.7.0/go.mod h1:9PWDzw47qPphMRFfhsyk0NnSgvluHcljSMVIq3w7q0I= github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/go-test/deep v1.0.2-0.20181118220953-042da051cf31/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= github.com/go-test/deep v1.0.2/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= @@ -623,6 +657,8 @@ github.com/goji/httpauth v0.0.0-20160601135302-2da839ab0f4d/go.mod h1:nnjvkQ9ptG github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= +github.com/golang/glog v1.1.0 h1:/d3pCKDPWNnvIWe0vVUpNP32qc8U3PDVxySP/y360qE= +github.com/golang/glog v1.1.0/go.mod h1:pfYeQZ3JWZoXTV5sFc986z3HTpwQs9At6P4ImfuP3NQ= github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -654,8 +690,9 @@ github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= -github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= @@ -725,6 +762,7 @@ github.com/googleapis/gax-go/v2 v2.3.0/go.mod h1:b8LNqSzNabLiUpXKkY7HAR5jr6bIT99 github.com/googleapis/gax-go/v2 v2.4.0/go.mod h1:XOTVJ59hdnfJLIP/dh8n5CGryZR2LxK9wbMD5+iXC6c= github.com/googleapis/gax-go/v2 v2.5.1/go.mod h1:h6B0KMMFNtI2ddbGJn3T3ZbwkeT6yqEF02fYlzkUCyo= github.com/googleapis/gax-go/v2 v2.6.0/go.mod h1:1mjbznJAPHFpesgE5ucqfYEscaz5kMdcIDwU/6+DDoY= +github.com/googleapis/gax-go/v2 v2.7.0/go.mod h1:TEop28CZZQ2y+c0VxMUmu1lV+fQx57QpBWsYpwqHJx8= github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+cLsWGBF62rFAi7WjWO4= github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= @@ -733,6 +771,9 @@ github.com/gopherjs/gopherjs v0.0.0-20190910122728-9d188e94fb99/go.mod h1:wJfORR github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= +github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= +github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM= github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= @@ -748,6 +789,7 @@ github.com/grpc-ecosystem/grpc-gateway v1.14.6/go.mod h1:zdiPV4Yse/1gnckTHtghG4G github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0/go.mod h1:hgWBS7lorOAVIJEQMi4ZsPv9hVvWI6+ch50m39Pf2Ks= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.3 h1:lLT7ZLSzGLI08vc9cpd+tYmNWjdKDqyr/2L+f6U12Fk= github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.3/go.mod h1:o//XUCC/F+yRGJoPO/VU0GSB0f8Nhgmxx0VIRUvaC0w= github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645 h1:MJG/KsmcqMwFAkh8mTnAwhyKoB+sTAnY4CACC110tbU= github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645/go.mod h1:6iZfnjpejD4L/4DwD7NryNaJyCQdzwWwH2MWhCA90Kw= @@ -829,6 +871,12 @@ github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANyt github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= github.com/influxdata/tdigest v0.0.1 h1:XpFptwYmnEKUqmkcDjrzffswZ3nvNeevbUSLPP/ZzIY= github.com/influxdata/tdigest v0.0.1/go.mod h1:Z0kXnxzbTC2qrx4NaIzYkE1k66+6oEDQTvL95hQFh5Y= +github.com/jcmturner/aescts/v2 v2.0.0/go.mod h1:AiaICIRyfYg35RUkr8yESTqvSy7csK90qZ5xfvvsoNs= +github.com/jcmturner/dnsutils/v2 v2.0.0/go.mod h1:b0TnjGOvI/n42bZa+hmXL+kFJZsFT7G4t3HTlQ184QM= +github.com/jcmturner/gofork v1.0.0/go.mod h1:MK8+TM0La+2rjBD4jE12Kj1pCCxK7d2LK/UM3ncEo0o= +github.com/jcmturner/goidentity/v6 v6.0.1/go.mod h1:X1YW3bgtvwAXju7V3LCIMpY0Gbxyjn/mY9zx4tFonSg= +github.com/jcmturner/gokrb5/v8 v8.4.2/go.mod h1:sb+Xq/fTY5yktf/VxLsE3wlfPqQjp0aWNYyvBVK62bc= +github.com/jcmturner/rpc/v2 v2.0.3/go.mod h1:VUJYCIDm3PVOEHw8sgt091/20OJjskO/YJki3ELg/Hc= github.com/jehiah/go-strftime v0.0.0-20171201141054-1d33003b3869/go.mod h1:cJ6Cj7dQo+O6GJNiMx+Pa94qKj+TG8ONdKHgMNIyyag= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jhump/protoreflect v1.6.0/go.mod h1:eaTn3RZAmMBcV0fifFvlm6VHNz3wSkYyXYWUh7ymB74= @@ -869,6 +917,7 @@ github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvW github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/knadh/koanf v1.5.0 h1:q2TSd/3Pyc/5yP9ldIrSdIz26MCcyNQzW0pEAugLPNs= github.com/knadh/koanf v1.5.0/go.mod h1:Hgyjp4y8v44hpZtPzs7JZfRAW5AhN7KfZcwv1RYggDs= github.com/koding/multiconfig v0.0.0-20171124222453-69c27309b2d7/go.mod h1:Y2SaZf2Rzd0pXkLVhLlCiAXFCLSXAIbTKDivVgff/AM= @@ -878,9 +927,8 @@ github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= -github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= @@ -895,6 +943,7 @@ github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0U github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= github.com/lyft/protoc-gen-star v0.6.1/go.mod h1:TGAoBVkt8w7MPG72TrKIu85MIdXwDuzJYeZuUPFPNwA= +github.com/lyft/protoc-gen-star/v2 v2.0.1/go.mod h1:RcCdONR2ScXaYnQC5tUzxzlpA3WVYF7/opLeUgcQs/o= github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4= github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= @@ -969,6 +1018,8 @@ github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxzi github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/npillmayer/nestext v0.1.3/go.mod h1:h2lrijH8jpicr25dFY+oAJLyzlya6jhnuG+zWp9L0Uk= +github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= @@ -977,7 +1028,13 @@ github.com/oliveagle/jsonpath v0.0.0-20180606110733-2e52cf6e6852 h1:Yl0tPBa8QPjG github.com/oliveagle/jsonpath v0.0.0-20180606110733-2e52cf6e6852/go.mod h1:eqOVx5Vwu4gd2mmMZvVZsgIqNSaW3xxRThUJ0k/TPk4= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= +github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/onsi/gomega v1.16.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis= github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= @@ -989,6 +1046,8 @@ github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxS github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= +github.com/openzipkin/zipkin-go v0.4.0 h1:CtfRrOVZtbDj8rt1WXjklw0kqqJQwICrCKmlfUuBUUw= +github.com/openzipkin/zipkin-go v0.4.0/go.mod h1:4c3sLeE8xjNqehmF5RpAFLPLJxXscc0R4l6Zg0P1tTQ= github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= @@ -1000,9 +1059,9 @@ github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCko github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= -github.com/pierrec/lz4 v2.5.2+incompatible h1:WCjObylUIOlKy/+7Abdn34TLIkXiA4UWUMhxq9m9ZXI= github.com/pierrec/lz4 v2.5.2+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= -github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= +github.com/pierrec/lz4 v2.6.1+incompatible h1:9UY3+iC23yxF0UfGaYrGplQ+79Rg+h/q9FV9ix19jjM= +github.com/pierrec/lz4 v2.6.1+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= @@ -1065,16 +1124,15 @@ github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1 github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo= github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= +github.com/rabbitmq/amqp091-go v1.1.0/go.mod h1:ogQDLSOACsLPsIq0NpbtiifNZi2YOz0VTJ0kHRghqbM= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= +github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rhnvrm/simples3 v0.6.1/go.mod h1:Y+3vYm2V7Y4VijFoJHHTrja6OgPrJ2cBti8dPGkC3sA= github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs= github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= -github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8= -github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/rwtodd/Go.Sed v0.0.0-20210816025313-55464686f9ef/go.mod h1:8AEUvGVi2uQ5b24BIhcr0GCcpd/RNAFWaN2CJFrWIIQ= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= @@ -1091,8 +1149,9 @@ github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeV github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= -github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= @@ -1134,8 +1193,9 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY= +github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/tebeka/strftime v0.1.3/go.mod h1:7wJm3dZlpr4l/oVK0t1HYIc4rMzQ2XJlOMIUJUJH6XQ= github.com/tklauser/go-sysconf v0.3.6/go.mod h1:MkWzOF4RMCshBAMXuhXJs64Rte09mITnppBXY/rYEFI= @@ -1163,6 +1223,10 @@ github.com/ugorji/go/codec v1.2.6 h1:7kbGefxLoDBuYXOms4yD7223OpNMMPNPZxXk5TvFcyQ github.com/ugorji/go/codec v1.2.6/go.mod h1:V6TCNZ4PHqoHGFZuSG1W8nrCzzdgA2DozYxWFFpvxTw= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= +github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= +github.com/xdg-go/scram v1.0.2/go.mod h1:1WAq6h33pAW+iRreB34OORO2Nf7qel3VV3fjBj+hCSs= +github.com/xdg-go/stringprep v1.0.2/go.mod h1:8F9zXuvzgwmyT5DUm4GUfZGDdT3W+LCvS6+da4O5kxM= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -1210,11 +1274,31 @@ go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= -go.opentelemetry.io/otel v1.11.0 h1:kfToEGMDq6TrVrJ9Vht84Y8y9enykSZzDDZglV0kIEk= -go.opentelemetry.io/otel v1.11.0/go.mod h1:H2KtuEphyMvlhZ+F7tg9GRhAOe60moNx61Ex+WmiKkk= -go.opentelemetry.io/otel/trace v1.11.0 h1:20U/Vj42SX+mASlXLmSGBg6jpI1jQtv682lZtTAOVFI= -go.opentelemetry.io/otel/trace v1.11.0/go.mod h1:nyYjis9jy0gytE9LXGU+/m1sHTKbRY0fX0hulNNDP1U= +go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= +go.opentelemetry.io/contrib/propagators/b3 v1.10.0 h1:6AD2VV8edRdEYNaD8cNckpzgdMLU2kbV9OYyxt2kvCg= +go.opentelemetry.io/contrib/propagators/b3 v1.10.0/go.mod h1:oxvamQ/mTDFQVugml/uFS59+aEUnFLhmd1wsG+n5MOE= +go.opentelemetry.io/otel v1.10.0 h1:Y7DTJMR6zs1xkS/upamJYk0SxxN4C9AqRd77jmZnyY4= +go.opentelemetry.io/otel v1.10.0/go.mod h1:NbvWjCthWHKBEUMpf0/v8ZRZlni86PpGFEMA9pnQSnQ= +go.opentelemetry.io/otel/exporters/jaeger v1.10.0 h1:7W3aVVjEYayu/GOqOVF4mbTvnCuxF1wWu3eRxFGQXvw= +go.opentelemetry.io/otel/exporters/jaeger v1.10.0/go.mod h1:n9IGyx0fgyXXZ/i0foLHNxtET9CzXHzZeKCucvRBFgA= +go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.10.0 h1:TaB+1rQhddO1sF71MpZOZAuSPW1klK2M8XxfrBMfK7Y= +go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.10.0/go.mod h1:78XhIg8Ht9vR4tbLNUhXsiOnE2HOuSeKAiAcoVQEpOY= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.10.0 h1:pDDYmo0QadUPal5fwXoY1pmMpFcdyhXOmL5drCrI3vU= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.10.0/go.mod h1:Krqnjl22jUJ0HgMzw5eveuCvFDXY4nSYb4F8t5gdrag= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.10.0 h1:KtiUEhQmj/Pa874bVYKGNVdq8NPKiacPbaRRtgXi+t4= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.10.0/go.mod h1:OfUCyyIiDvNXHWpcWgbF+MWvqPZiNa3YDEnivcnYsV0= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.10.0 h1:S8DedULB3gp93Rh+9Z+7NTEv+6Id/KYS7LDyipZ9iCE= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.10.0/go.mod h1:5WV40MLWwvWlGP7Xm8g3pMcg0pKOUY609qxJn8y7LmM= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.10.0 h1:c9UtMu/qnbLlVwTwt+ABrURrioEruapIslTDYZHJe2w= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.10.0/go.mod h1:h3Lrh9t3Dnqp3NPwAZx7i37UFX7xrfnO1D+fuClREOA= +go.opentelemetry.io/otel/exporters/zipkin v1.10.0 h1:HcPAFsFpEBKF+G5NIOA+gBsxifd3Ej+wb+KsdBLa15E= +go.opentelemetry.io/otel/exporters/zipkin v1.10.0/go.mod h1:HdfvgwcOoCB0+zzrTHycW6btjK0zNpkz2oTGO815SCI= +go.opentelemetry.io/otel/sdk v1.10.0 h1:jZ6K7sVn04kk/3DNUdJ4mqRlGDiXAVuIG+MMENpTNdY= +go.opentelemetry.io/otel/sdk v1.10.0/go.mod h1:vO06iKzD5baltJz1zarxMCNHFpUlUiOy4s65ECtn6kE= +go.opentelemetry.io/otel/trace v1.10.0 h1:npQMbR8o7mum8uF95yFbOEJffhs1sbCOfDh8zAJiH5E= +go.opentelemetry.io/otel/trace v1.10.0/go.mod h1:Sij3YYczqAdz+EhmGhE6TpTxUO5/F/AzrK+kxfGqySM= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= +go.opentelemetry.io/proto/otlp v0.19.0 h1:IVN6GR+mhC4s5yfcTbmzHYODqvWAp3ZedA2SJPI1Nnw= go.opentelemetry.io/proto/otlp v0.19.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= @@ -1224,8 +1308,9 @@ go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ= go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= -go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI= go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= +go.uber.org/goleak v1.1.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA= +go.uber.org/goleak v1.1.12/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= @@ -1251,8 +1336,10 @@ golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3 golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20201112155050-0c6587e931a9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20210920023735-84f357641f63/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A= @@ -1301,8 +1388,9 @@ golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.9.0 h1:KENHtAZL2y3NLMYZeHY9DW8HW8V+kQyJsY/V9JlKvCs= +golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20180530234432-1e491301e022/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1337,6 +1425,7 @@ golang.org/x/net v0.0.0-20200421231249-e086a090c8fd/go.mod h1:qpuaurCH72eLCgpAm/ golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= @@ -1352,8 +1441,10 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8= +golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210917221730-978cfadd31cf/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211029224645-99673261e6eb/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211105192438-b53810dc28af/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= @@ -1397,8 +1488,9 @@ golang.org/x/oauth2 v0.0.0-20220622183110-fd043fe589d2/go.mod h1:jaDAt6Dkxork7Lm golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= golang.org/x/oauth2 v0.0.0-20221006150949-b44042a4b9c1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= -golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783 h1:nt+Q6cXKz4MosCSpnbMtqiQ8Oz0pxTef2B4Vca2lvfk= golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= +golang.org/x/oauth2 v0.6.0 h1:Lh8GPgSKBfWSwFvtuWOfeI3aAAnbXTSutYxJiOJFgIw= +golang.org/x/oauth2 v0.6.0/go.mod h1:ycmewcwgD4Rpr3eZJLSB4Kyyljb3qDh40vJ8STE5HKw= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1436,6 +1528,7 @@ golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1443,6 +1536,7 @@ golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1474,6 +1568,7 @@ golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20201214210602-f9fddec55a1e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201223074533-0d417f636930/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1552,8 +1647,10 @@ golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxb golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20220722155302-e5dcc9cfc0b9 h1:ftMN5LMiBFjbzleLqtoBZk7KdJwhuybIU+FckUHgoyQ= golang.org/x/time v0.0.0-20220722155302-e5dcc9cfc0b9/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20220922220347-f3bd1da661af/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.1.0 h1:xYY+Bajn2a7VBmTM5GikTmnK8ZuX8YgnQCqZpbBNtmA= +golang.org/x/time v0.1.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -1611,6 +1708,7 @@ golang.org/x/tools v0.0.0-20201014170642-d1624618ad65/go.mod h1:z6u4i615ZeAfBE4X golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= @@ -1622,8 +1720,9 @@ golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k= -golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/tools v0.7.0 h1:W4OVu8VVOaIO0yzWMNdepAulS7YfoS3Zabrm8DOXXU4= +golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1691,6 +1790,7 @@ google.golang.org/api v0.98.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ google.golang.org/api v0.99.0/go.mod h1:1YOf74vkVndF7pG6hIHuINsM7eWwpVTAfNMNiL91A08= google.golang.org/api v0.100.0/go.mod h1:ZE3Z2+ZOr87Rx7dqFsdRQkRBk36kDtp/h+QpHbB7a70= google.golang.org/api v0.102.0/go.mod h1:3VFl6/fzoA+qNuS1N1/VfXY4LjoXN/wzeIp7TweWwGo= +google.golang.org/api v0.103.0/go.mod h1:hGtW6nK1AC+d9si/UBhw8Xli+QMOf6xyNAyJw4qU9w0= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -1813,8 +1913,13 @@ google.golang.org/genproto v0.0.0-20221014213838-99cd37c6964a/go.mod h1:1vXfmgAz google.golang.org/genproto v0.0.0-20221024153911-1573dae28c9c/go.mod h1:9qHF0xnpdSfF6knlcsnpzUu5y+rpwgbvsyGAZPBMg4s= google.golang.org/genproto v0.0.0-20221024183307-1bc688fe9f3e/go.mod h1:9qHF0xnpdSfF6knlcsnpzUu5y+rpwgbvsyGAZPBMg4s= google.golang.org/genproto v0.0.0-20221027153422-115e99e71e1c/go.mod h1:CGI5F/G+E5bKwmfYo09AXuVN4dD894kIKUFmVbP2/Fo= -google.golang.org/genproto v0.0.0-20221118155620-16455021b5e6 h1:a2S6M0+660BgMNl++4JPlcAO/CjkqYItDEZwkoDQK7c= +google.golang.org/genproto v0.0.0-20221114212237-e4508ebdbee1/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= +google.golang.org/genproto v0.0.0-20221117204609-8f9c96812029/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= google.golang.org/genproto v0.0.0-20221118155620-16455021b5e6/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= +google.golang.org/genproto v0.0.0-20221201164419-0e50fba7f41c/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= +google.golang.org/genproto v0.0.0-20221202195650-67e5cbc046fd/go.mod h1:cTsE614GARnxrLsqKREzmNYJACSWWpAWdNMwnD7c2BE= +google.golang.org/genproto v0.0.0-20221227171554-f9683d7f8bef h1:uQ2vjV/sHTsWSqdKeLqmwitzgvjMl7o4IdtHwUDXSJY= +google.golang.org/genproto v0.0.0-20221227171554-f9683d7f8bef/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= google.golang.org/grpc v1.8.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= @@ -1861,6 +1966,7 @@ google.golang.org/grpc v1.48.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACu google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= google.golang.org/grpc v1.50.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= +google.golang.org/grpc v1.51.0/go.mod h1:wgNDFcnuBGmxLKI/qn4T+m5BtEBYXJPvibbUPsAIPww= google.golang.org/grpc v1.52.0 h1:kd48UiU7EHsV4rnLyOJRuP/Il/UHE7gdDAQ+SZI7nZk= google.golang.org/grpc v1.52.0/go.mod h1:pu6fVzoFb+NBYNAvQL08ic+lvB2IojljRYuun5vorUY= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= diff --git a/imports/imports.go b/imports/imports.go index 71dd06b246..90737e9bb1 100644 --- a/imports/imports.go +++ b/imports/imports.go @@ -66,6 +66,10 @@ import ( _ "dubbo.apache.org/dubbo-go/v3/metadata/service/remote" _ "dubbo.apache.org/dubbo-go/v3/metrics/app_info" _ "dubbo.apache.org/dubbo-go/v3/metrics/prometheus" + _ "dubbo.apache.org/dubbo-go/v3/otel/trace/jaeger" + _ "dubbo.apache.org/dubbo-go/v3/otel/trace/zipkin" + //_ "dubbo.apache.org/dubbo-go/v3/otel/trace/otlp" // FIXME: otlp-grpc use grpc health check which has the namespace conflict with dubbo3 protocol + _ "dubbo.apache.org/dubbo-go/v3/otel/trace/stdout" _ "dubbo.apache.org/dubbo-go/v3/protocol/dubbo" _ "dubbo.apache.org/dubbo-go/v3/protocol/dubbo3" _ "dubbo.apache.org/dubbo-go/v3/protocol/dubbo3/health" diff --git a/otel/trace/exporter.go b/otel/trace/exporter.go new file mode 100644 index 0000000000..454b02a975 --- /dev/null +++ b/otel/trace/exporter.go @@ -0,0 +1,110 @@ +/* + * 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 trace + +import ( + "errors" + "fmt" +) + +import ( + "github.com/dubbogo/gost/log/logger" + "go.opentelemetry.io/contrib/propagators/b3" + "go.opentelemetry.io/otel/propagation" + "go.opentelemetry.io/otel/sdk/resource" + sdktrace "go.opentelemetry.io/otel/sdk/trace" + semconv "go.opentelemetry.io/otel/semconv/v1.7.0" +) + +type ExporterConfig struct { + Exporter string + Endpoint string + SampleMode string + SampleRatio float64 + Propagator string + ServiceNamespace string + ServiceName string + ServiceVersion string +} + +type Exporter interface { + GetTracerProvider() *sdktrace.TracerProvider + GetPropagator() propagation.TextMapPropagator +} + +type DefaultExporter struct { + TracerProvider *sdktrace.TracerProvider + Propagator propagation.TextMapPropagator +} + +func (e *DefaultExporter) GetTracerProvider() *sdktrace.TracerProvider { + return e.TracerProvider +} + +func (e *DefaultExporter) GetPropagator() propagation.TextMapPropagator { + return e.Propagator +} + +// NewExporter is an absolute function with @customFunc to create a spec exporter +func NewExporter(config *ExporterConfig, customFunc func() (sdktrace.SpanExporter, error)) (tracerProvider *sdktrace.TracerProvider, propagator propagation.TextMapPropagator, err error) { + if config == nil { + err = errors.New("otel exporter config is nil") + return + } + + exporter, err := customFunc() + if err != nil { + err = fmt.Errorf("failed to create %s exporter: %v", config.Exporter, err) + logger.Error(err) + return + } + + var samplerOption sdktrace.TracerProviderOption + switch config.SampleMode { + case "ratio": + samplerOption = sdktrace.WithSampler(sdktrace.ParentBased(sdktrace.TraceIDRatioBased(config.SampleRatio))) + case "always": + samplerOption = sdktrace.WithSampler(sdktrace.ParentBased(sdktrace.AlwaysSample())) + case "never": + samplerOption = sdktrace.WithSampler(sdktrace.ParentBased(sdktrace.NeverSample())) + default: + err = fmt.Errorf("otel sample mode %s not supported", config.SampleMode) + logger.Error(err) + return + } + + tracerProvider = sdktrace.NewTracerProvider( + samplerOption, + sdktrace.WithBatcher(exporter), + sdktrace.WithResource(resource.NewSchemaless( + semconv.ServiceNamespaceKey.String(config.ServiceNamespace), + semconv.ServiceNameKey.String(config.ServiceName), + semconv.ServiceVersionKey.String(config.ServiceVersion), + )), + ) + + switch config.Propagator { + case "w3c": + propagator = propagation.NewCompositeTextMapPropagator(propagation.TraceContext{}, propagation.Baggage{}) + case "b3": + b3Propagator := b3.New(b3.WithInjectEncoding(b3.B3MultipleHeader | b3.B3SingleHeader)) + propagator = propagation.NewCompositeTextMapPropagator(b3Propagator, propagation.Baggage{}) + } + + return tracerProvider, propagator, nil +} diff --git a/otel/trace/jaeger/exporter.go b/otel/trace/jaeger/exporter.go new file mode 100644 index 0000000000..65a269022c --- /dev/null +++ b/otel/trace/jaeger/exporter.go @@ -0,0 +1,70 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package jaeger + +import ( + "sync" +) + +import ( + "dubbo.apache.org/dubbo-go/v3/common/extension" + "dubbo.apache.org/dubbo-go/v3/otel/trace" +) + +import ( + "go.opentelemetry.io/otel/exporters/jaeger" + sdktrace "go.opentelemetry.io/otel/sdk/trace" +) + +var ( + initOnce sync.Once + instance *Exporter +) + +func init() { + extension.SetTraceExporter("jaeger", newJaegerExporter) +} + +type Exporter struct { + *trace.DefaultExporter +} + +func newJaegerExporter(config *trace.ExporterConfig) (trace.Exporter, error) { + var initError error + if instance == nil { + initOnce.Do(func() { + customFunc := func() (sdktrace.SpanExporter, error) { + return jaeger.New(jaeger.WithCollectorEndpoint(jaeger.WithEndpoint(config.Endpoint))) + } + + tracerProvider, propagator, err := trace.NewExporter(config, customFunc) + if err != nil { + initError = err + return + } + + instance = &Exporter{ + DefaultExporter: &trace.DefaultExporter{ + TracerProvider: tracerProvider, + Propagator: propagator, + }, + } + }) + } + return instance, initError +} diff --git a/otel/trace/otlp/exporter.go b/otel/trace/otlp/exporter.go new file mode 100644 index 0000000000..69e2adeb1f --- /dev/null +++ b/otel/trace/otlp/exporter.go @@ -0,0 +1,104 @@ +/* + * 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 otlp + +import ( + "context" + "sync" +) + +import ( + "dubbo.apache.org/dubbo-go/v3/common/extension" + "dubbo.apache.org/dubbo-go/v3/otel/trace" +) + +import ( + "go.opentelemetry.io/otel/exporters/otlp/otlptrace" + "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc" + "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp" + sdktrace "go.opentelemetry.io/otel/sdk/trace" +) + +var ( + initHttpOnce sync.Once + httpInstance *Exporter + + initGrpcOnce sync.Once + grpcInstance *Exporter +) + +func init() { + extension.SetTraceExporter("otlp-http", newHttpExporter) + extension.SetTraceExporter("otlp-grpc", newHttpExporter) +} + +type Exporter struct { + *trace.DefaultExporter +} + +func newHttpExporter(config *trace.ExporterConfig) (trace.Exporter, error) { + var initError error + if httpInstance == nil { + initHttpOnce.Do(func() { + customFunc := func() (sdktrace.SpanExporter, error) { + client := otlptracehttp.NewClient(otlptracehttp.WithEndpoint(config.Endpoint)) + return otlptrace.New(context.Background(), client) + } + + tracerProvider, propagator, err := trace.NewExporter(config, customFunc) + if err != nil { + initError = err + return + } + + httpInstance = &Exporter{ + DefaultExporter: &trace.DefaultExporter{ + TracerProvider: tracerProvider, + Propagator: propagator, + }, + } + }) + } + return httpInstance, initError +} + +func newGrpcExporter(config *trace.ExporterConfig) (trace.Exporter, error) { + var initError error + if grpcInstance == nil { + initGrpcOnce.Do(func() { + customFunc := func() (sdktrace.SpanExporter, error) { + client := otlptracegrpc.NewClient(otlptracegrpc.WithEndpoint(config.Endpoint)) + return otlptrace.New(context.Background(), client) + } + + tracerProvider, propagator, err := trace.NewExporter(config, customFunc) + if err != nil { + initError = err + return + } + + grpcInstance = &Exporter{ + DefaultExporter: &trace.DefaultExporter{ + TracerProvider: tracerProvider, + Propagator: propagator, + }, + } + }) + } + return grpcInstance, initError +} diff --git a/otel/trace/stdout/exporter.go b/otel/trace/stdout/exporter.go new file mode 100644 index 0000000000..8024c4d896 --- /dev/null +++ b/otel/trace/stdout/exporter.go @@ -0,0 +1,69 @@ +/* + * 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 stdout + +import ( + "sync" +) + +import ( + "dubbo.apache.org/dubbo-go/v3/common/extension" + "dubbo.apache.org/dubbo-go/v3/otel/trace" + + "go.opentelemetry.io/otel/exporters/stdout/stdouttrace" + + sdktrace "go.opentelemetry.io/otel/sdk/trace" +) + +var ( + initOnce sync.Once + instance *Exporter +) + +func init() { + extension.SetTraceExporter("stdout", newStdoutExporter) +} + +type Exporter struct { + *trace.DefaultExporter +} + +func newStdoutExporter(config *trace.ExporterConfig) (trace.Exporter, error) { + var initError error + if instance == nil { + initOnce.Do(func() { + customFunc := func() (sdktrace.SpanExporter, error) { + return stdouttrace.New(stdouttrace.WithPrettyPrint()) + } + tracerProvider, propagator, err := trace.NewExporter(config, customFunc) + if err != nil { + initError = err + return + } + + instance = &Exporter{ + DefaultExporter: &trace.DefaultExporter{ + TracerProvider: tracerProvider, + Propagator: propagator, + }, + } + }) + } + + return instance, initError +} diff --git a/otel/trace/zipkin/exporter.go b/otel/trace/zipkin/exporter.go new file mode 100644 index 0000000000..4068872ce3 --- /dev/null +++ b/otel/trace/zipkin/exporter.go @@ -0,0 +1,70 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package zipkin + +import ( + "sync" +) + +import ( + "dubbo.apache.org/dubbo-go/v3/common/extension" + "dubbo.apache.org/dubbo-go/v3/otel/trace" +) + +import ( + "go.opentelemetry.io/otel/exporters/zipkin" + sdktrace "go.opentelemetry.io/otel/sdk/trace" +) + +var ( + initOnce sync.Once + instance *Exporter +) + +func init() { + extension.SetTraceExporter("zipkin", newZipkinExporter) +} + +type Exporter struct { + *trace.DefaultExporter +} + +func newZipkinExporter(config *trace.ExporterConfig) (trace.Exporter, error) { + var initError error + if instance == nil { + initOnce.Do(func() { + customFunc := func() (sdktrace.SpanExporter, error) { + return zipkin.New(config.Endpoint) + } + + tracerProvider, propagator, err := trace.NewExporter(config, customFunc) + if err != nil { + initError = err + return + } + + instance = &Exporter{ + DefaultExporter: &trace.DefaultExporter{ + TracerProvider: tracerProvider, + Propagator: propagator, + }, + } + }) + } + return instance, initError +} From bdf5b7078da8a9f9890bfd1d3c55d9207a6951f6 Mon Sep 17 00:00:00 2001 From: Ken Liu Date: Tue, 29 Aug 2023 21:02:17 +0800 Subject: [PATCH 05/22] add fmt make task (#2401) --- Makefile | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Makefile b/Makefile index 7cee059249..233ba53376 100644 --- a/Makefile +++ b/Makefile @@ -68,6 +68,11 @@ license: clean prepareLic .PHONY: verify verify: clean license test +.PHONE: fmt +fmt: + $(GO_GET) -u github.com/dubbogo/tools/cmd/imports-formatter + imports-formatter + .PHONY: clean clean: prepare rm -rf coverage.txt From 0a02805f4be77098bc918179b0221e9562c2ca0c Mon Sep 17 00:00:00 2001 From: Wang Guan Date: Wed, 30 Aug 2023 21:52:17 +0800 Subject: [PATCH 06/22] refactor: rewrite RPC metrics into the event pattern (#2392) --- common/constant/key.go | 1 + common/extension/metrics_test.go | 7 +- filter/metrics/filter.go | 42 +-- filter/metrics/filter_test.go | 43 +-- metrics/api.go | 293 +++++++++++++++++- metrics/bus_test.go | 5 +- metrics/prometheus/api.go | 201 ------------ metrics/prometheus/metric_set.go | 133 -------- metrics/prometheus/model.go | 389 ------------------------ metrics/prometheus/registry.go | 4 +- metrics/prometheus/reporter.go | 141 +-------- metrics/prometheus/reporter_test.go | 77 ----- metrics/reporter.go | 20 +- metrics/rpc/collector.go | 161 ++++++++++ metrics/{prometheus => rpc}/constant.go | 24 +- metrics/rpc/event.go | 67 ++++ metrics/rpc/metric_set.go | 106 +++++++ metrics/{prometheus => rpc}/util.go | 21 +- metrics/util/aggregate/quantile_test.go | 4 +- 19 files changed, 681 insertions(+), 1058 deletions(-) delete mode 100644 metrics/prometheus/api.go delete mode 100644 metrics/prometheus/metric_set.go delete mode 100644 metrics/prometheus/model.go delete mode 100644 metrics/prometheus/reporter_test.go create mode 100644 metrics/rpc/collector.go rename metrics/{prometheus => rpc}/constant.go (73%) create mode 100644 metrics/rpc/event.go create mode 100644 metrics/rpc/metric_set.go rename metrics/{prometheus => rpc}/util.go (78%) diff --git a/common/constant/key.go b/common/constant/key.go index 383b57e57c..0db06c01df 100644 --- a/common/constant/key.go +++ b/common/constant/key.go @@ -412,6 +412,7 @@ const ( // metrics key const ( + MetricsRpc = "dubbo.metrics.rpc" MetricsRegistry = "dubbo.metrics.registry" MetricsMetadata = "dubbo.metrics.metadata" MetricApp = "dubbo.metrics.app" diff --git a/common/extension/metrics_test.go b/common/extension/metrics_test.go index 573c4dd812..64f76422ca 100644 --- a/common/extension/metrics_test.go +++ b/common/extension/metrics_test.go @@ -18,9 +18,7 @@ package extension import ( - "context" "testing" - "time" ) import ( @@ -29,7 +27,6 @@ import ( import ( "dubbo.apache.org/dubbo-go/v3/metrics" - "dubbo.apache.org/dubbo-go/v3/protocol" ) func TestGetMetricReporter(t *testing.T) { @@ -45,8 +42,8 @@ func TestGetMetricReporter(t *testing.T) { type mockReporter struct{} // implement the interface of Reporter -func (m *mockReporter) ReportAfterInvocation(ctx context.Context, invoker protocol.Invoker, invocation protocol.Invocation, cost time.Duration, res protocol.Result) { +func (m *mockReporter) StartServer(config *metrics.ReporterConfig) { } -func (m *mockReporter) ReportBeforeInvocation(ctx context.Context, invoker protocol.Invoker, invocation protocol.Invocation) { +func (m *mockReporter) ShutdownServer() { } diff --git a/filter/metrics/filter.go b/filter/metrics/filter.go index bf59b514c7..0b623d1028 100644 --- a/filter/metrics/filter.go +++ b/filter/metrics/filter.go @@ -15,7 +15,6 @@ * limitations under the License. */ -// Package metrics provides metrics collection filter. package metrics import ( @@ -28,56 +27,43 @@ import ( "dubbo.apache.org/dubbo-go/v3/common/extension" "dubbo.apache.org/dubbo-go/v3/filter" "dubbo.apache.org/dubbo-go/v3/metrics" + "dubbo.apache.org/dubbo-go/v3/metrics/rpc" "dubbo.apache.org/dubbo-go/v3/protocol" ) // must initialize before using the filter and after loading configuration -var metricFilterInstance *Filter +var metricFilterInstance *metricsFilter func init() { extension.SetFilter(constant.MetricsFilterKey, newFilter) } -// Filter will calculate the invocation's duration and the report to the reporters -// more info please take a look at dubbo-samples projects -type Filter struct { - reporters []metrics.Reporter -} +// metricsFilter will report RPC metrics to the metrics bus and implements the filter.Filter interface +type metricsFilter struct{} -// Invoke collect the duration of invocation and then report the duration by using goroutine -func (p *Filter) Invoke(ctx context.Context, invoker protocol.Invoker, invocation protocol.Invocation) protocol.Result { - go func() { - for _, reporter := range p.reporters { - reporter.ReportBeforeInvocation(ctx, invoker, invocation) - } - }() +// Invoke publish the BeforeInvokeEvent and AfterInvokeEvent to metrics bus +func (mf *metricsFilter) Invoke(ctx context.Context, invoker protocol.Invoker, invocation protocol.Invocation) protocol.Result { + metrics.Publish(rpc.NewBeforeInvokeEvent(invoker, invocation)) start := time.Now() res := invoker.Invoke(ctx, invocation) end := time.Now() duration := end.Sub(start) - go func() { - for _, reporter := range p.reporters { - reporter.ReportAfterInvocation(ctx, invoker, invocation, duration, res) - } - }() + metrics.Publish(rpc.NewAfterInvokeEvent(invoker, invocation, duration, res)) return res } // OnResponse do nothing and return the result -func (p *Filter) OnResponse(ctx context.Context, res protocol.Result, invoker protocol.Invoker, invocation protocol.Invocation) protocol.Result { +func (mf *metricsFilter) OnResponse(ctx context.Context, res protocol.Result, invoker protocol.Invoker, invocation protocol.Invocation) protocol.Result { return res } -// newFilter the Filter is singleton. -// it's lazy initialization -// make sure that the configuration had been loaded before invoking this method. +// newFilter creates a new metricsFilter instance. +// +// It's lazy initialization, +// and make sure that the configuration had been loaded before invoking this method. func newFilter() filter.Filter { if metricFilterInstance == nil { - reporters := make([]metrics.Reporter, 0, 1) - reporters = append(reporters, extension.GetMetricReporter("prometheus", metrics.NewReporterConfig())) - metricFilterInstance = &Filter{ - reporters: reporters, - } + metricFilterInstance = &metricsFilter{} } return metricFilterInstance } diff --git a/filter/metrics/filter_test.go b/filter/metrics/filter_test.go index fd5614a943..f1165202e4 100644 --- a/filter/metrics/filter_test.go +++ b/filter/metrics/filter_test.go @@ -19,33 +19,25 @@ package metrics import ( "context" - "sync" "testing" - "time" ) import ( "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/mock" ) import ( "dubbo.apache.org/dubbo-go/v3/common" - "dubbo.apache.org/dubbo-go/v3/common/extension" + "dubbo.apache.org/dubbo-go/v3/common/constant" "dubbo.apache.org/dubbo-go/v3/metrics" - _ "dubbo.apache.org/dubbo-go/v3/metrics/prometheus" "dubbo.apache.org/dubbo-go/v3/protocol" "dubbo.apache.org/dubbo-go/v3/protocol/invocation" ) func TestMetricsFilterInvoke(t *testing.T) { - // prepare the mock reporter - mk := &mockReporter{} - extension.SetMetricReporter("mock", func(config *metrics.ReporterConfig) metrics.Reporter { - return mk - }) - - instance := newFilter() + mockChan := make(chan metrics.MetricsEvent, 10) + defer close(mockChan) + metrics.Subscribe(constant.MetricsRpc, mockChan) url, _ := common.NewURL( "dubbo://:20000/UserProvider?app.version=0.0.1&application=BDTService&bean.name=UserProvider" + @@ -57,31 +49,14 @@ func TestMetricsFilterInvoke(t *testing.T) { attach := make(map[string]interface{}, 10) inv := invocation.NewRPCInvocation("MethodName", []interface{}{"OK", "Hello"}, attach) - ctx := context.Background() - mk.On("Report", ctx, invoker, inv).Return(true, nil) - - mk.wg.Add(1) - result := instance.Invoke(ctx, invoker, inv) + filter := newFilter() + result := filter.Invoke(ctx, invoker, inv) assert.NotNil(t, result) - mk.AssertNotCalled(t, "Report", 1) - // it will do nothing - result = instance.OnResponse(ctx, nil, invoker, inv) + result = filter.OnResponse(ctx, nil, invoker, inv) assert.Nil(t, result) -} - -type mockReporter struct { - mock.Mock - wg sync.WaitGroup -} - -func (m *mockReporter) ReportAfterInvocation(ctx context.Context, invoker protocol.Invoker, invocation protocol.Invocation, cost time.Duration, res protocol.Result) { - m.Called(ctx, invoker, invocation) - m.wg.Done() -} -func (m *mockReporter) ReportBeforeInvocation(ctx context.Context, invoker protocol.Invoker, invocation protocol.Invocation) { - m.Called(ctx, invoker, invocation) - m.wg.Done() + assert.Equal(t, 2, len(mockChan)) + assert.Equal(t, constant.MetricsRpc, (<-mockChan).Type()) } diff --git a/metrics/api.go b/metrics/api.go index 4c19e63cfd..d0c7f729ea 100644 --- a/metrics/api.go +++ b/metrics/api.go @@ -17,6 +17,25 @@ package metrics +import ( + "encoding/json" + "sync" +) + +import ( + "github.com/dubbogo/gost/log/logger" +) + +import ( + "dubbo.apache.org/dubbo-go/v3/metrics/util/aggregate" +) + +const ( + DefaultCompression = 100 + DefaultBucketNum = 10 + DefaultTimeWindowSeconds = 120 +) + var ( registries = make(map[string]func(*ReporterConfig) MetricRegistry) collectors = make([]CollectorFunc, 0) @@ -29,7 +48,7 @@ type CollectorFunc func(MetricRegistry, *ReporterConfig) // Init Metrics module func Init(config *ReporterConfig) { if config.Enable { - // defalut protocol is already set in metricConfig + // default protocol is already set in metricConfig regFunc, ok := registries[config.Protocol] if ok { registry = regFunc(config) @@ -46,8 +65,8 @@ func SetRegistry(name string, v func(*ReporterConfig) MetricRegistry) { registries[name] = v } -// AddCollector add more indicators, like metadata、sla、configcenter etc -func AddCollector(name string, fun func(MetricRegistry, *ReporterConfig)) { +// AddCollector add more indicators, like metadata, sla, config-center etc. +func AddCollector(name string, fun CollectorFunc) { collectors = append(collectors, fun) } @@ -75,7 +94,7 @@ type RtOpts struct { // } // Type metric type, save with micrometer -type Type uint8 +type Type uint8 // TODO check if Type is is useful const ( Counter Type = iota @@ -94,8 +113,8 @@ const ( type MetricId struct { Name string Desc string - Tags map[string]string - Type Type + Tags map[string]string // also named label + Type Type // TODO check if this field is useful } func (m *MetricId) TagKeys() []string { @@ -110,6 +129,11 @@ func NewMetricId(key *MetricKey, level MetricLevel) *MetricId { return &MetricId{Name: key.Name, Desc: key.Desc, Tags: level.Tags()} } +// NewMetricIdByLabels create a MetricId by key and labels +func NewMetricIdByLabels(key *MetricKey, labels map[string]string) *MetricId { + return &MetricId{Name: key.Name, Desc: key.Desc, Tags: labels} +} + // MetricSample a metric sample,This is the final data presentation, // not an intermediate result(like summary,histogram they will export to a set of MetricSample) type MetricSample struct { @@ -126,10 +150,10 @@ type CounterMetric interface { // GaugeMetric gauge metric type GaugeMetric interface { Set(float64) - // Inc() - // Dec() - // Add(float64) - // Sub(float64) + Inc() + Dec() + Add(float64) + Sub(float64) } // histogram summary rt metric @@ -149,3 +173,252 @@ func (c *BaseCollector) StateCount(total, succ, fail *MetricKey, level MetricLev c.R.Counter(NewMetricId(fail, level)).Inc() } } + +// CounterVec means a set of counters with the same metricKey but different labels +type CounterVec interface { + Inc(labels map[string]string) + Add(labels map[string]string, v float64) +} + +// NewCounterVec create a CounterVec default implementation. +func NewCounterVec(metricRegistry MetricRegistry, metricKey *MetricKey) CounterVec { + return &DefaultCounterVec{ + metricRegistry: metricRegistry, + metricKey: metricKey, + } +} + +// DefaultCounterVec is a default CounterVec implementation. +type DefaultCounterVec struct { + metricRegistry MetricRegistry + metricKey *MetricKey +} + +func (d *DefaultCounterVec) Inc(labels map[string]string) { + d.metricRegistry.Counter(NewMetricIdByLabels(d.metricKey, labels)).Inc() +} + +func (d *DefaultCounterVec) Add(labels map[string]string, v float64) { + d.metricRegistry.Counter(NewMetricIdByLabels(d.metricKey, labels)).Add(v) +} + +// GaugeVec means a set of gauges with the same metricKey but different labels +type GaugeVec interface { + Set(labels map[string]string, v float64) + Inc(labels map[string]string) + Dec(labels map[string]string) + Add(labels map[string]string, v float64) + Sub(labels map[string]string, v float64) +} + +// NewGaugeVec create a GaugeVec default implementation. +func NewGaugeVec(metricRegistry MetricRegistry, metricKey *MetricKey) GaugeVec { + return &DefaultGaugeVec{ + metricRegistry: metricRegistry, + metricKey: metricKey, + } +} + +// DefaultGaugeVec is a default GaugeVec implementation. +type DefaultGaugeVec struct { + metricRegistry MetricRegistry + metricKey *MetricKey +} + +func (d *DefaultGaugeVec) Set(labels map[string]string, v float64) { + d.metricRegistry.Gauge(NewMetricIdByLabels(d.metricKey, labels)).Set(v) +} + +func (d *DefaultGaugeVec) Inc(labels map[string]string) { + d.metricRegistry.Gauge(NewMetricIdByLabels(d.metricKey, labels)).Inc() +} + +func (d *DefaultGaugeVec) Dec(labels map[string]string) { + d.metricRegistry.Gauge(NewMetricIdByLabels(d.metricKey, labels)).Dec() +} + +func (d *DefaultGaugeVec) Add(labels map[string]string, v float64) { + d.metricRegistry.Gauge(NewMetricIdByLabels(d.metricKey, labels)).Add(v) +} + +func (d *DefaultGaugeVec) Sub(labels map[string]string, v float64) { + d.metricRegistry.Gauge(NewMetricIdByLabels(d.metricKey, labels)).Sub(v) +} + +// RtVec means a set of rt metrics with the same metricKey but different labels +type RtVec interface { + Record(labels map[string]string, v float64) +} + +// NewRtVec create a RtVec default implementation DefaultRtVec. +func NewRtVec(metricRegistry MetricRegistry, metricKey *MetricKey, rtOpts *RtOpts) RtVec { + return &DefaultRtVec{ + metricRegistry: metricRegistry, + metricKey: metricKey, + rtOpts: rtOpts, + } +} + +// DefaultRtVec is a default RtVec implementation. +// +// If rtOpts.Aggregate is true, it will use the aggregate.TimeWindowAggregator with local aggregation, +// else it will use the aggregate.Result without aggregation. +type DefaultRtVec struct { + metricRegistry MetricRegistry + metricKey *MetricKey + rtOpts *RtOpts +} + +func (d *DefaultRtVec) Record(labels map[string]string, v float64) { + d.metricRegistry.Rt(NewMetricIdByLabels(d.metricKey, labels), d.rtOpts).Observe(v) +} + +// labelsToString convert @labels to json format string for cache key +func labelsToString(labels map[string]string) string { + labelsJson, err := json.Marshal(labels) + if err != nil { + logger.Errorf("json.Marshal(labels) = error:%v", err) + return "" + } + return string(labelsJson) +} + +// QpsMetricVec means a set of qps metrics with the same metricKey but different labels. +type QpsMetricVec interface { + Record(labels map[string]string) +} + +func NewQpsMetricVec(metricRegistry MetricRegistry, metricKey *MetricKey) QpsMetricVec { + return &DefaultQpsMetricVec{ + metricRegistry: metricRegistry, + metricKey: metricKey, + mux: sync.RWMutex{}, + cache: make(map[string]*aggregate.TimeWindowCounter), + } +} + +// DefaultQpsMetricVec is a default QpsMetricVec implementation. +// +// It is concurrent safe, and it uses the aggregate.TimeWindowCounter to store and calculate the qps metrics. +type DefaultQpsMetricVec struct { + metricRegistry MetricRegistry + metricKey *MetricKey + mux sync.RWMutex + cache map[string]*aggregate.TimeWindowCounter // key: metrics labels, value: TimeWindowCounter +} + +func (d *DefaultQpsMetricVec) Record(labels map[string]string) { + key := labelsToString(labels) + if key == "" { + return + } + d.mux.RLock() + twc, ok := d.cache[key] + d.mux.RUnlock() + if !ok { + d.mux.Lock() + twc, ok = d.cache[key] + if !ok { + twc = aggregate.NewTimeWindowCounter(DefaultBucketNum, DefaultTimeWindowSeconds) + d.cache[key] = twc + } + d.mux.Unlock() + } + twc.Inc() + d.metricRegistry.Gauge(NewMetricIdByLabels(d.metricKey, labels)).Set(twc.Count() / float64(twc.LivedSeconds())) +} + +// AggregateCounterVec means a set of aggregate counter metrics with the same metricKey but different labels. +type AggregateCounterVec interface { + Inc(labels map[string]string) +} + +func NewAggregateCounterVec(metricRegistry MetricRegistry, metricKey *MetricKey) AggregateCounterVec { + return &DefaultAggregateCounterVec{ + metricRegistry: metricRegistry, + metricKey: metricKey, + mux: sync.RWMutex{}, + cache: make(map[string]*aggregate.TimeWindowCounter), + } +} + +// DefaultAggregateCounterVec is a default AggregateCounterVec implementation. +// +// It is concurrent safe, and it uses the aggregate.TimeWindowCounter to store and calculate the aggregate counter metrics. +type DefaultAggregateCounterVec struct { + metricRegistry MetricRegistry + metricKey *MetricKey + mux sync.RWMutex + cache map[string]*aggregate.TimeWindowCounter // key: metrics labels, value: TimeWindowCounter +} + +func (d *DefaultAggregateCounterVec) Inc(labels map[string]string) { + key := labelsToString(labels) + if key == "" { + return + } + d.mux.RLock() + twc, ok := d.cache[key] + d.mux.RUnlock() + if !ok { + d.mux.Lock() + twc, ok = d.cache[key] + if !ok { + twc = aggregate.NewTimeWindowCounter(DefaultBucketNum, DefaultTimeWindowSeconds) + d.cache[key] = twc + } + d.mux.Unlock() + } + twc.Inc() + d.metricRegistry.Gauge(NewMetricIdByLabels(d.metricKey, labels)).Set(twc.Count()) +} + +// QuantileMetricVec means a set of quantile metrics with the same metricKey but different labels. +type QuantileMetricVec interface { + Record(labels map[string]string, v float64) +} + +func NewQuantileMetricVec(metricRegistry MetricRegistry, metricKeys []*MetricKey, quantiles []float64) QuantileMetricVec { + return &DefaultQuantileMetricVec{ + metricRegistry: metricRegistry, + metricKeys: metricKeys, + mux: sync.RWMutex{}, + cache: make(map[string]*aggregate.TimeWindowQuantile), + quantiles: quantiles, + } +} + +// DefaultQuantileMetricVec is a default QuantileMetricVec implementation. +// +// It is concurrent safe, and it uses the aggregate.TimeWindowQuantile to store and calculate the quantile metrics. +type DefaultQuantileMetricVec struct { + metricRegistry MetricRegistry + metricKeys []*MetricKey + mux sync.RWMutex + cache map[string]*aggregate.TimeWindowQuantile // key: metrics labels, value: TimeWindowQuantile + quantiles []float64 +} + +func (d *DefaultQuantileMetricVec) Record(labels map[string]string, v float64) { + key := labelsToString(labels) + if key == "" { + return + } + d.mux.RLock() + twq, ok := d.cache[key] + d.mux.RUnlock() + if !ok { + d.mux.Lock() + twq, ok = d.cache[key] + if !ok { + twq = aggregate.NewTimeWindowQuantile(DefaultCompression, DefaultBucketNum, DefaultTimeWindowSeconds) + d.cache[key] = twq + } + d.mux.Unlock() + } + twq.Add(v) + + for i, q := range twq.Quantiles(d.quantiles) { + d.metricRegistry.Gauge(NewMetricIdByLabels(d.metricKeys[i], labels)).Set(q) + } +} diff --git a/metrics/bus_test.go b/metrics/bus_test.go index 185f50896f..4e4a68eecf 100644 --- a/metrics/bus_test.go +++ b/metrics/bus_test.go @@ -18,10 +18,13 @@ package metrics import ( - "github.com/stretchr/testify/assert" "testing" ) +import ( + "github.com/stretchr/testify/assert" +) + var mockChan = make(chan MetricsEvent, 16) type MockEvent struct { diff --git a/metrics/prometheus/api.go b/metrics/prometheus/api.go deleted file mode 100644 index 2d01afdca3..0000000000 --- a/metrics/prometheus/api.go +++ /dev/null @@ -1,201 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package prometheus - -import ( - "sync" -) - -import ( - "github.com/prometheus/client_golang/prometheus" -) - -type syncMaps struct { - userGauge sync.Map - userSummary sync.Map - userCounter sync.Map - userCounterVec sync.Map - userGaugeVec sync.Map - userSummaryVec sync.Map -} - -// setGauge set gauge to target value with given label, if label is not empty, set gauge vec -// if target gauge/gaugevec not exist, just create new gauge and set the value -func (reporter *PrometheusReporter) setGauge(gaugeName string, toSetValue float64, labelMap prometheus.Labels) { - if len(labelMap) == 0 { - // gauge - if val, exist := reporter.userGauge.Load(gaugeName); !exist { - gauge := newGauge(gaugeName, reporter.namespace) - err := prometheus.DefaultRegisterer.Register(gauge) - if err == nil { - reporter.userGauge.Store(gaugeName, gauge) - gauge.Set(toSetValue) - } else if are, ok := err.(prometheus.AlreadyRegisteredError); ok { - // A gauge for that metric has been registered before. - // Use the old gauge from now on. - are.ExistingCollector.(prometheus.Gauge).Set(toSetValue) - } - - } else { - val.(prometheus.Gauge).Set(toSetValue) - } - return - } - - // gauge vec - if val, exist := reporter.userGaugeVec.Load(gaugeName); !exist { - keyList := make([]string, 0) - for k := range labelMap { - keyList = append(keyList, k) - } - gaugeVec := newGaugeVec(gaugeName, reporter.namespace, keyList) - err := prometheus.DefaultRegisterer.Register(gaugeVec) - if err == nil { - reporter.userGaugeVec.Store(gaugeName, gaugeVec) - gaugeVec.With(labelMap).Set(toSetValue) - } else if are, ok := err.(prometheus.AlreadyRegisteredError); ok { - // A gauge for that metric has been registered before. - // Use the old gauge from now on. - are.ExistingCollector.(*prometheus.GaugeVec).With(labelMap).Set(toSetValue) - } - } else { - val.(*prometheus.GaugeVec).With(labelMap).Set(toSetValue) - } -} - -// incCounter inc counter to inc if label is not empty, set counter vec -// if target counter/counterVec not exist, just create new counter and inc the value -func (reporter *PrometheusReporter) incCounter(counterName string, labelMap prometheus.Labels) { - if len(labelMap) == 0 { - // counter - if val, exist := reporter.userCounter.Load(counterName); !exist { - counter := newCounter(counterName, reporter.namespace) - err := prometheus.DefaultRegisterer.Register(counter) - if err == nil { - reporter.userCounter.Store(counterName, counter) - counter.Inc() - } else if are, ok := err.(prometheus.AlreadyRegisteredError); ok { - // A counter for that metric has been registered before. - // Use the old counter from now on. - are.ExistingCollector.(prometheus.Counter).Inc() - } - } else { - val.(prometheus.Counter).Inc() - } - return - } - - // counter vec inc - if val, exist := reporter.userCounterVec.Load(counterName); !exist { - keyList := make([]string, 0) - for k := range labelMap { - keyList = append(keyList, k) - } - counterVec := newCounterVec(counterName, reporter.namespace, keyList) - err := prometheus.DefaultRegisterer.Register(counterVec) - if err == nil { - reporter.userCounterVec.Store(counterName, counterVec) - counterVec.With(labelMap).Inc() - } else if are, ok := err.(prometheus.AlreadyRegisteredError); ok { - // A counter for that metric has been registered before. - // Use the old counter from now on. - are.ExistingCollector.(*prometheus.CounterVec).With(labelMap).Inc() - } - } else { - val.(*prometheus.CounterVec).With(labelMap).Inc() - } -} - -// incSummary inc summary to target value with given label, if label is not empty, set summary vec -// if target summary/summaryVec not exist, just create new summary and set the value -func (reporter *PrometheusReporter) incSummary(summaryName string, toSetValue float64, labelMap prometheus.Labels) { - if len(labelMap) == 0 { - // summary - if val, exist := reporter.userSummary.Load(summaryName); !exist { - summary := newSummary(summaryName, reporter.namespace) - err := prometheus.DefaultRegisterer.Register(summary) - if err == nil { - reporter.userSummary.Store(summaryName, summary) - summary.Observe(toSetValue) - } else if are, ok := err.(prometheus.AlreadyRegisteredError); ok { - // A summary for that metric has been registered before. - // Use the old summary from now on. - are.ExistingCollector.(prometheus.Summary).Observe(toSetValue) - } - } else { - val.(prometheus.Summary).Observe(toSetValue) - } - return - } - - // summary vec - if val, exist := reporter.userSummaryVec.Load(summaryName); !exist { - keyList := make([]string, 0) - for k := range labelMap { - keyList = append(keyList, k) - } - summaryVec := newSummaryVec(summaryName, reporter.namespace, keyList, reporter.reporterConfig.SummaryMaxAge) - err := prometheus.DefaultRegisterer.Register(summaryVec) - if err == nil { - reporter.userSummaryVec.Store(summaryName, summaryVec) - summaryVec.With(labelMap).Observe(toSetValue) - } else if are, ok := err.(prometheus.AlreadyRegisteredError); ok { - // A summary for that metric has been registered before. - // Use the old summary from now on. - are.ExistingCollector.(*prometheus.SummaryVec).With(labelMap).Observe(toSetValue) - } - } else { - val.(*prometheus.SummaryVec).With(labelMap).Observe(toSetValue) - } -} - -func SetGaugeWithLabel(gaugeName string, val float64, label prometheus.Labels) { - if reporterInstance.reporterConfig.Enable { - reporterInstance.setGauge(gaugeName, val, label) - } -} - -func SetGauge(gaugeName string, val float64) { - if reporterInstance.reporterConfig.Enable { - reporterInstance.setGauge(gaugeName, val, make(prometheus.Labels)) - } -} - -func IncCounterWithLabel(counterName string, label prometheus.Labels) { - if reporterInstance.reporterConfig.Enable { - reporterInstance.incCounter(counterName, label) - } -} - -func IncCounter(summaryName string) { - if reporterInstance.reporterConfig.Enable { - reporterInstance.incCounter(summaryName, make(prometheus.Labels)) - } -} - -func IncSummaryWithLabel(counterName string, val float64, label prometheus.Labels) { - if reporterInstance.reporterConfig.Enable { - reporterInstance.incSummary(counterName, val, label) - } -} - -func IncSummary(summaryName string, val float64) { - if reporterInstance.reporterConfig.Enable { - reporterInstance.incSummary(summaryName, val, make(prometheus.Labels)) - } -} diff --git a/metrics/prometheus/metric_set.go b/metrics/prometheus/metric_set.go deleted file mode 100644 index 5d3caf2736..0000000000 --- a/metrics/prometheus/metric_set.go +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package prometheus - -import ( - "fmt" - "strconv" - "strings" -) - -import ( - "github.com/prometheus/client_golang/prometheus" -) - -import ( - "dubbo.apache.org/dubbo-go/v3/metrics" -) - -// metricSet is a set of metrics that are reported to prometheus in dubbo-go -type metricSet struct { - provider providerMetrics - consumer consumerMetrics -} - -func (ms *metricSet) init(reporterConfig *metrics.ReporterConfig) { - ms.provider.init(reporterConfig) - ms.consumer.init(reporterConfig) -} - -type rpcCommonMetrics struct { - qpsTotal *qpsGaugeVec - requestsTotal *prometheus.CounterVec - requestsTotalAggregate *aggregateCounterGaugeVec - requestsProcessingTotal *prometheus.GaugeVec - requestsSucceedTotal *prometheus.CounterVec - requestsSucceedTotalAggregate *aggregateCounterGaugeVec - rtMillisecondsMin *GaugeVecWithSyncMap - rtMillisecondsMax *GaugeVecWithSyncMap - rtMillisecondsSum *prometheus.CounterVec - rtMillisecondsAvg *GaugeVecWithSyncMap - rtMillisecondsLast *prometheus.GaugeVec - rtMillisecondsQuantiles *quantileGaugeVec - rtMillisecondsAggregate *aggregateFunctionsGaugeVec -} - -type providerMetrics struct { - rpcCommonMetrics -} - -func (pm *providerMetrics) init(reporterConfig *metrics.ReporterConfig) { - pm.qpsTotal = newQpsGaugeVec(buildMetricsName(providerField, qpsField, totalField), reporterConfig.Namespace, labelNames) - pm.requestsTotal = newAutoCounterVec(buildMetricsName(providerField, requestsField, totalField), reporterConfig.Namespace, labelNames) - pm.requestsTotalAggregate = newAggregateCounterGaugeVec(buildMetricsName(providerField, requestsField, totalField, aggregateField), reporterConfig.Namespace, labelNames) - pm.requestsProcessingTotal = newAutoGaugeVec(buildMetricsName(providerField, requestsField, processingField, totalField), reporterConfig.Namespace, labelNames) - pm.requestsSucceedTotal = newAutoCounterVec(buildMetricsName(providerField, requestsField, succeedField, totalField), reporterConfig.Namespace, labelNames) - pm.requestsSucceedTotalAggregate = newAggregateCounterGaugeVec(buildMetricsName(providerField, requestsField, succeedField, totalField, aggregateField), reporterConfig.Namespace, labelNames) - pm.rtMillisecondsMin = newAutoGaugeVecWithSyncMap(buildMetricsName(providerField, rtField, milliSecondsField, minField), reporterConfig.Namespace, labelNames) - pm.rtMillisecondsMax = newAutoGaugeVecWithSyncMap(buildMetricsName(providerField, rtField, milliSecondsField, maxField), reporterConfig.Namespace, labelNames) - pm.rtMillisecondsSum = newAutoCounterVec(buildMetricsName(providerField, rtField, milliSecondsField, sumField), reporterConfig.Namespace, labelNames) - pm.rtMillisecondsAvg = newAutoGaugeVecWithSyncMap(buildMetricsName(providerField, rtField, milliSecondsField, avgField), reporterConfig.Namespace, labelNames) - pm.rtMillisecondsLast = newAutoGaugeVec(buildMetricsName(providerField, rtField, milliSecondsField, lastField), reporterConfig.Namespace, labelNames) - pm.rtMillisecondsQuantiles = newQuantileGaugeVec(buildRTQuantilesMetricsNames(providerField, quantiles), reporterConfig.Namespace, labelNames, quantiles) - pm.rtMillisecondsAggregate = newAggregateFunctionsGaugeVec( - buildMetricsName(providerField, rtField, minField, milliSecondsField, aggregateField), - buildMetricsName(providerField, rtField, maxField, milliSecondsField, aggregateField), - buildMetricsName(providerField, rtField, avgField, milliSecondsField, aggregateField), - reporterConfig.Namespace, - labelNames, - ) -} - -type consumerMetrics struct { - rpcCommonMetrics -} - -func (cm *consumerMetrics) init(reporterConfig *metrics.ReporterConfig) { - cm.qpsTotal = newQpsGaugeVec(buildMetricsName(consumerField, qpsField, totalField), reporterConfig.Namespace, labelNames) - cm.requestsTotal = newAutoCounterVec(buildMetricsName(consumerField, requestsField, totalField), reporterConfig.Namespace, labelNames) - cm.requestsTotalAggregate = newAggregateCounterGaugeVec(buildMetricsName(consumerField, requestsField, totalField, aggregateField), reporterConfig.Namespace, labelNames) - cm.requestsProcessingTotal = newAutoGaugeVec(buildMetricsName(consumerField, requestsField, processingField, totalField), reporterConfig.Namespace, labelNames) - cm.requestsSucceedTotal = newAutoCounterVec(buildMetricsName(consumerField, requestsField, succeedField, totalField), reporterConfig.Namespace, labelNames) - cm.requestsSucceedTotalAggregate = newAggregateCounterGaugeVec(buildMetricsName(consumerField, requestsField, succeedField, totalField, aggregateField), reporterConfig.Namespace, labelNames) - cm.rtMillisecondsMin = newAutoGaugeVecWithSyncMap(buildMetricsName(consumerField, rtField, milliSecondsField, minField), reporterConfig.Namespace, labelNames) - cm.rtMillisecondsMax = newAutoGaugeVecWithSyncMap(buildMetricsName(consumerField, rtField, milliSecondsField, maxField), reporterConfig.Namespace, labelNames) - cm.rtMillisecondsSum = newAutoCounterVec(buildMetricsName(consumerField, rtField, milliSecondsField, sumField), reporterConfig.Namespace, labelNames) - cm.rtMillisecondsAvg = newAutoGaugeVecWithSyncMap(buildMetricsName(consumerField, rtField, milliSecondsField, avgField), reporterConfig.Namespace, labelNames) - cm.rtMillisecondsLast = newAutoGaugeVec(buildMetricsName(consumerField, rtField, milliSecondsField, lastField), reporterConfig.Namespace, labelNames) - cm.rtMillisecondsQuantiles = newQuantileGaugeVec(buildRTQuantilesMetricsNames(consumerField, quantiles), reporterConfig.Namespace, labelNames, quantiles) - cm.rtMillisecondsAggregate = newAggregateFunctionsGaugeVec( - buildMetricsName(consumerField, rtField, minField, milliSecondsField, aggregateField), - buildMetricsName(consumerField, rtField, maxField, milliSecondsField, aggregateField), - buildMetricsName(consumerField, rtField, avgField, milliSecondsField, aggregateField), - reporterConfig.Namespace, - labelNames, - ) -} - -// buildMetricsName builds metrics name split by "_". -func buildMetricsName(args ...string) string { - sb := strings.Builder{} - for _, arg := range args { - sb.WriteString("_") - sb.WriteString(arg) - } - res := strings.TrimPrefix(sb.String(), "_") - return res -} - -// buildRTQuantilesMetricsNames is only used for building rt quantiles metric names. -func buildRTQuantilesMetricsNames(role string, quantiles []float64) []string { - res := make([]string, 0, len(quantiles)) - for _, q := range quantiles { - quantileField := fmt.Sprintf("p%v", strconv.FormatFloat(q*100, 'f', -1, 64)) - name := buildMetricsName(role, rtField, milliSecondsField, quantileField) - res = append(res, name) - } - return res -} diff --git a/metrics/prometheus/model.go b/metrics/prometheus/model.go deleted file mode 100644 index 3efd2149ce..0000000000 --- a/metrics/prometheus/model.go +++ /dev/null @@ -1,389 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package prometheus - -import ( - "strings" - "sync" - "sync/atomic" - "time" -) - -import ( - "github.com/prometheus/client_golang/prometheus" - "github.com/prometheus/client_golang/prometheus/promauto" -) - -import ( - "dubbo.apache.org/dubbo-go/v3/metrics/util/aggregate" -) - -func newHistogramVec(name, namespace string, labels []string) *prometheus.HistogramVec { - return prometheus.NewHistogramVec( - prometheus.HistogramOpts{ - Namespace: namespace, - Name: name, - Buckets: defaultHistogramBucket, - }, - labels) -} - -func newCounter(name, namespace string) prometheus.Counter { - return prometheus.NewCounter( - prometheus.CounterOpts{ - Namespace: namespace, - Name: name, - }) -} - -func newCounterVec(name, namespace string, labels []string) *prometheus.CounterVec { - return prometheus.NewCounterVec( - prometheus.CounterOpts{ - Name: name, - Namespace: namespace, - }, labels) -} - -func newGauge(name, namespace string) prometheus.Gauge { - return prometheus.NewGauge( - prometheus.GaugeOpts{ - Name: name, - Namespace: namespace, - }) -} - -func newGaugeVec(name, namespace string, labels []string) *prometheus.GaugeVec { - return prometheus.NewGaugeVec( - prometheus.GaugeOpts{ - Name: name, - Namespace: namespace, - }, labels) -} - -func newSummary(name, namespace string) prometheus.Summary { - return prometheus.NewSummary( - prometheus.SummaryOpts{ - Name: name, - Namespace: namespace, - }) -} - -// newSummaryVec create SummaryVec, the Namespace is dubbo -// the objectives is from my experience. -func newSummaryVec(name, namespace string, labels []string, maxAge int64) *prometheus.SummaryVec { - return prometheus.NewSummaryVec( - prometheus.SummaryOpts{ - Namespace: namespace, - Name: name, - Objectives: map[float64]float64{ - 0.5: 0.01, - 0.75: 0.01, - 0.90: 0.005, - 0.98: 0.002, - 0.99: 0.001, - 0.999: 0.0001, - }, - MaxAge: time.Duration(maxAge), - }, - labels, - ) -} - -// create an auto register histogram vec -func newAutoHistogramVec(name, namespace string, labels []string) *prometheus.HistogramVec { - return promauto.NewHistogramVec( - prometheus.HistogramOpts{ - Namespace: namespace, - Name: name, - Buckets: defaultHistogramBucket, - }, - labels) -} - -// create an auto register counter vec -func newAutoCounterVec(name, namespace string, labels []string) *prometheus.CounterVec { - return promauto.NewCounterVec( - prometheus.CounterOpts{ - Name: name, - Namespace: namespace, - }, labels) -} - -// create an auto register gauge vec -func newAutoGaugeVec(name, namespace string, labels []string) *prometheus.GaugeVec { - return promauto.NewGaugeVec( - prometheus.GaugeOpts{ - Name: name, - Namespace: namespace, - }, labels) -} - -// create an auto register summary vec -func newAutoSummaryVec(name, namespace string, labels []string, maxAge int64) *prometheus.SummaryVec { - return promauto.NewSummaryVec( - prometheus.SummaryOpts{ - Namespace: namespace, - Name: name, - Objectives: map[float64]float64{ - 0.5: 0.01, - 0.75: 0.01, - 0.90: 0.005, - 0.98: 0.002, - 0.99: 0.001, - 0.999: 0.0001, - }, - MaxAge: time.Duration(maxAge), - }, - labels, - ) -} - -type GaugeVecWithSyncMap struct { - GaugeVec *prometheus.GaugeVec - SyncMap *sync.Map // key: labels, value: *atomic.Value -} - -func newAutoGaugeVecWithSyncMap(name, namespace string, labels []string) *GaugeVecWithSyncMap { - return &GaugeVecWithSyncMap{ - GaugeVec: newAutoGaugeVec(name, namespace, labels), - SyncMap: &sync.Map{}, - } -} - -func convertLabelsToMapKey(labels prometheus.Labels) string { - return strings.Join([]string{ - labels[applicationNameKey], - labels[groupKey], - labels[hostnameKey], - labels[interfaceKey], - labels[ipKey], - labels[versionKey], - labels[methodKey], - }, "_") -} - -func (gv *GaugeVecWithSyncMap) updateMin(labels *prometheus.Labels, curValue int64) { - key := convertLabelsToMapKey(*labels) - cur := &atomic.Value{} // for first store - cur.Store(curValue) - for { - if actual, loaded := gv.SyncMap.LoadOrStore(key, cur); loaded { - store := actual.(*atomic.Value) - storeValue := store.Load().(int64) - if curValue < storeValue { - if store.CompareAndSwap(storeValue, curValue) { - // value is not changed, should update - gv.GaugeVec.With(*labels).Set(float64(curValue)) - break - } - // value has changed, continue for loop - } else { - // no need to update - break - } - } else { - // store current curValue as this labels' init value - gv.GaugeVec.With(*labels).Set(float64(curValue)) - break - } - } -} - -func (gv *GaugeVecWithSyncMap) updateMax(labels *prometheus.Labels, curValue int64) { - key := convertLabelsToMapKey(*labels) - cur := &atomic.Value{} // for first store - cur.Store(curValue) - for { - if actual, loaded := gv.SyncMap.LoadOrStore(key, cur); loaded { - store := actual.(*atomic.Value) - storeValue := store.Load().(int64) - if curValue > storeValue { - if store.CompareAndSwap(storeValue, curValue) { - // value is not changed, should update - gv.GaugeVec.With(*labels).Set(float64(curValue)) - break - } - // value has changed, continue for loop - } else { - // no need to update - break - } - } else { - // store current curValue as this labels' init value - gv.GaugeVec.With(*labels).Set(float64(curValue)) - break - } - } -} - -func (gv *GaugeVecWithSyncMap) updateAvg(labels *prometheus.Labels, curValue int64) { - key := convertLabelsToMapKey(*labels) - cur := &atomic.Value{} // for first store - type avgPair struct { - Sum int64 - N int64 - } - cur.Store(avgPair{Sum: curValue, N: 1}) - - for { - if actual, loaded := gv.SyncMap.LoadOrStore(key, cur); loaded { - store := actual.(*atomic.Value) - storeValue := store.Load().(avgPair) - newValue := avgPair{Sum: storeValue.Sum + curValue, N: storeValue.N + 1} - if store.CompareAndSwap(storeValue, newValue) { - // value is not changed, should update - gv.GaugeVec.With(*labels).Set(float64(newValue.Sum / newValue.N)) - break - } - } else { - // store current curValue as this labels' init value - gv.GaugeVec.With(*labels).Set(float64(curValue)) - break - } - } -} - -type quantileGaugeVec struct { - gaugeVecSlice []*prometheus.GaugeVec - quantiles []float64 - syncMap *sync.Map // key: labels string, value: TimeWindowQuantile -} - -// Notice: names and quantiles should be the same length and same order. -func newQuantileGaugeVec(names []string, namespace string, labels []string, quantiles []float64) *quantileGaugeVec { - gvs := make([]*prometheus.GaugeVec, len(names)) - for i, name := range names { - gvs[i] = newAutoGaugeVec(name, namespace, labels) - } - gv := &quantileGaugeVec{ - gaugeVecSlice: gvs, - quantiles: quantiles, - syncMap: &sync.Map{}, - } - return gv -} - -func (gv *quantileGaugeVec) updateQuantile(labels *prometheus.Labels, curValue int64) { - key := convertLabelsToMapKey(*labels) - cur := aggregate.NewTimeWindowQuantile(100, 10, 120) - cur.Add(float64(curValue)) - - updateFunc := func(td *aggregate.TimeWindowQuantile) { - qs := td.Quantiles(gv.quantiles) - for i, q := range qs { - gv.gaugeVecSlice[i].With(*labels).Set(q) - } - } - - if actual, loaded := gv.syncMap.LoadOrStore(key, cur); loaded { - store := actual.(*aggregate.TimeWindowQuantile) - store.Add(float64(curValue)) - updateFunc(store) - } else { - updateFunc(cur) - } -} - -type qpsGaugeVec struct { - gaugeVec *prometheus.GaugeVec - syncMap *sync.Map // key: labels string, value: TimeWindowCounter -} - -func newQpsGaugeVec(name, namespace string, labels []string) *qpsGaugeVec { - return &qpsGaugeVec{ - gaugeVec: newAutoGaugeVec(name, namespace, labels), - syncMap: &sync.Map{}, - } -} - -func (gv *qpsGaugeVec) updateQps(labels *prometheus.Labels) { - key := convertLabelsToMapKey(*labels) - cur := aggregate.NewTimeWindowCounter(10, 120) - cur.Inc() - - if actual, loaded := gv.syncMap.LoadOrStore(key, cur); loaded { - store := actual.(*aggregate.TimeWindowCounter) - store.Inc() - gv.gaugeVec.With(*labels).Set(store.Count() / float64(store.LivedSeconds())) - } else { - gv.gaugeVec.With(*labels).Set(cur.Count() / float64(cur.LivedSeconds())) - } -} - -type aggregateCounterGaugeVec struct { - gaugeVec *prometheus.GaugeVec - syncMap *sync.Map // key: labels string, value: TimeWindowCounter -} - -func newAggregateCounterGaugeVec(name, namespace string, labels []string) *aggregateCounterGaugeVec { - return &aggregateCounterGaugeVec{ - gaugeVec: newAutoGaugeVec(name, namespace, labels), - syncMap: &sync.Map{}, - } -} - -func (gv *aggregateCounterGaugeVec) inc(labels *prometheus.Labels) { - key := convertLabelsToMapKey(*labels) - cur := aggregate.NewTimeWindowCounter(10, 120) - cur.Inc() - - if actual, loaded := gv.syncMap.LoadOrStore(key, cur); loaded { - store := actual.(*aggregate.TimeWindowCounter) - store.Inc() - gv.gaugeVec.With(*labels).Set(store.Count()) - } else { - gv.gaugeVec.With(*labels).Set(cur.Count()) - } -} - -type aggregateFunctionsGaugeVec struct { - min *prometheus.GaugeVec - max *prometheus.GaugeVec - avg *prometheus.GaugeVec - syncMap *sync.Map // key: labels string, value: TimeWindowAggregator -} - -func newAggregateFunctionsGaugeVec(minName, maxName, avgName, namespace string, labels []string) *aggregateFunctionsGaugeVec { - return &aggregateFunctionsGaugeVec{ - min: newAutoGaugeVec(minName, namespace, labels), - max: newAutoGaugeVec(maxName, namespace, labels), - avg: newAutoGaugeVec(avgName, namespace, labels), - syncMap: &sync.Map{}, - } -} - -func (gv *aggregateFunctionsGaugeVec) update(labels *prometheus.Labels, curValue int64) { - key := convertLabelsToMapKey(*labels) - cur := aggregate.NewTimeWindowAggregator(10, 120) - cur.Add(float64(curValue)) - - updateFunc := func(aggregator *aggregate.TimeWindowAggregator) { - result := aggregator.Result() - gv.min.With(*labels).Set(result.Min) - gv.max.With(*labels).Set(result.Max) - gv.avg.With(*labels).Set(result.Avg) - } - - if actual, loaded := gv.syncMap.LoadOrStore(key, cur); loaded { - store := actual.(*aggregate.TimeWindowAggregator) - store.Add(float64(curValue)) - updateFunc(store) - } else { - updateFunc(cur) - } -} diff --git a/metrics/prometheus/registry.go b/metrics/prometheus/registry.go index 21ebc0d6d3..144a3a0599 100644 --- a/metrics/prometheus/registry.go +++ b/metrics/prometheus/registry.go @@ -95,8 +95,10 @@ func (p *promMetricRegistry) Summary(m *metrics.MetricId) metrics.ObservableMetr } func (p *promMetricRegistry) Rt(m *metrics.MetricId, opts *metrics.RtOpts) metrics.ObservableMetric { + key := m.Name var supplier func() interface{} if opts != nil && opts.Aggregate { + key += "_aggregate" supplier = func() interface{} { // TODO set default aggregate config from config return NewAggRtVec(&RtOpts{ @@ -114,7 +116,7 @@ func (p *promMetricRegistry) Rt(m *metrics.MetricId, opts *metrics.RtOpts) metri }, m.TagKeys()) } } - vec := p.getOrComputeVec(m.Name, supplier).(*RtVec) + vec := p.getOrComputeVec(key, supplier).(*RtVec) return vec.With(m.Tags) } diff --git a/metrics/prometheus/reporter.go b/metrics/prometheus/reporter.go index 0e9fedc822..a5e88eff28 100644 --- a/metrics/prometheus/reporter.go +++ b/metrics/prometheus/reporter.go @@ -21,82 +21,78 @@ import ( "context" "net/http" "sync" - "time" ) import ( "github.com/dubbogo/gost/log/logger" - "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promhttp" ) import ( "dubbo.apache.org/dubbo-go/v3/common/extension" "dubbo.apache.org/dubbo-go/v3/metrics" - "dubbo.apache.org/dubbo-go/v3/protocol" ) var ( - reporterInstance *PrometheusReporter + reporterInstance *reporter reporterInitOnce sync.Once ) +const ( + reporterName = "prometheus" +) + // should initialize after loading configuration func init() { // newPrometheusReporter() extension.SetMetricReporter(reporterName, newPrometheusReporter) } -// PrometheusReporter will collect the data for Prometheus +// reporter will export the metrics to Prometheus // if you want to use this feature, you need to initialize your prometheus. // https://prometheus.io/docs/guides/go-application/ -type PrometheusReporter struct { +type reporter struct { reporterServer *http.Server reporterConfig *metrics.ReporterConfig - metricSet - syncMaps - namespace string + namespace string } -// newPrometheusReporter create new prometheusReporter -// it will register the metrics into prometheus +// newPrometheusReporter create a new prometheus server or push gateway reporter func newPrometheusReporter(reporterConfig *metrics.ReporterConfig) metrics.Reporter { if reporterInstance == nil { reporterInitOnce.Do(func() { - ms := &metricSet{} - ms.init(reporterConfig) - reporterInstance = &PrometheusReporter{ + reporterInstance = &reporter{ reporterConfig: reporterConfig, namespace: reporterConfig.Namespace, - metricSet: *ms, } }) } if reporterConfig.Enable { if reporterConfig.Mode == metrics.ReportModePull { - go reporterInstance.startupServer(reporterConfig) + go reporterInstance.StartServer(reporterConfig) } // todo pushgateway support } else { - reporterInstance.shutdownServer() + reporterInstance.ShutdownServer() } return reporterInstance } -func (reporter *PrometheusReporter) startupServer(reporterConfig *metrics.ReporterConfig) { +func (r *reporter) StartServer(reporterConfig *metrics.ReporterConfig) { // start server mux := http.NewServeMux() mux.Handle(reporterConfig.Path, promhttp.Handler()) reporterInstance.reporterServer = &http.Server{Addr: ":" + reporterConfig.Port, Handler: mux} + logger.Infof("new prometheus reporter with port = %s, path = %s", reporterConfig.Port, reporterConfig.Path) if err := reporterInstance.reporterServer.ListenAndServe(); err != nil { logger.Warnf("new prometheus reporter with error = %s", err) } } -func (reporter *PrometheusReporter) shutdownServer() { +func (r *reporter) ShutdownServer() { if reporterInstance.reporterServer != nil { err := reporterInstance.reporterServer.Shutdown(context.Background()) if err != nil { @@ -105,110 +101,3 @@ func (reporter *PrometheusReporter) shutdownServer() { } } } - -func (reporter *PrometheusReporter) ReportBeforeInvocation(ctx context.Context, invoker protocol.Invoker, invocation protocol.Invocation) { - if !reporter.reporterConfig.Enable { - return - } - url := invoker.GetURL() - - role := getRole(url) - if role == "" { - return - } - labels := buildLabels(url) - reporter.incQpsTotal(role, &labels) - reporter.incRequestsProcessingTotal(role, &labels) -} - -func (reporter *PrometheusReporter) ReportAfterInvocation(ctx context.Context, invoker protocol.Invoker, invocation protocol.Invocation, cost time.Duration, res protocol.Result) { - if !reporter.reporterConfig.Enable { - return - } - url := invoker.GetURL() - - role := getRole(url) - if role == "" { - return - } - labels := buildLabels(url) - - reporter.incRequestsTotal(role, &labels) - reporter.decRequestsProcessingTotal(role, &labels) - reporter.reportRTMilliseconds(role, &labels, cost.Milliseconds()) - - if res != nil && res.Error() == nil { - // succeed - reporter.incRequestsSucceedTotal(role, &labels) - } -} - -func (reporter *PrometheusReporter) incQpsTotal(role string, labels *prometheus.Labels) { - switch role { - case providerField: - reporter.provider.qpsTotal.updateQps(labels) - case consumerField: - reporter.consumer.qpsTotal.updateQps(labels) - } -} - -func (reporter *PrometheusReporter) incRequestsTotal(role string, labels *prometheus.Labels) { - switch role { - case providerField: - reporter.provider.requestsTotal.With(*labels).Inc() - reporter.provider.requestsTotalAggregate.inc(labels) - case consumerField: - reporter.consumer.requestsTotal.With(*labels).Inc() - reporter.consumer.requestsTotalAggregate.inc(labels) - } -} - -func (reporter *PrometheusReporter) incRequestsProcessingTotal(role string, labels *prometheus.Labels) { - switch role { - case providerField: - reporter.provider.requestsProcessingTotal.With(*labels).Inc() - case consumerField: - reporter.consumer.requestsProcessingTotal.With(*labels).Inc() - } -} - -func (reporter *PrometheusReporter) decRequestsProcessingTotal(role string, labels *prometheus.Labels) { - switch role { - case providerField: - reporter.provider.requestsProcessingTotal.With(*labels).Dec() - case consumerField: - reporter.consumer.requestsProcessingTotal.With(*labels).Dec() - } -} - -func (reporter *PrometheusReporter) incRequestsSucceedTotal(role string, labels *prometheus.Labels) { - switch role { - case providerField: - reporter.provider.requestsSucceedTotal.With(*labels).Inc() - reporter.provider.requestsSucceedTotalAggregate.inc(labels) - case consumerField: - reporter.consumer.requestsSucceedTotal.With(*labels).Inc() - reporter.consumer.requestsSucceedTotalAggregate.inc(labels) - } -} - -func (reporter *PrometheusReporter) reportRTMilliseconds(role string, labels *prometheus.Labels, costMs int64) { - switch role { - case providerField: - go reporter.provider.rtMillisecondsLast.With(*labels).Set(float64(costMs)) - go reporter.provider.rtMillisecondsSum.With(*labels).Add(float64(costMs)) - go reporter.provider.rtMillisecondsMin.updateMin(labels, costMs) - go reporter.provider.rtMillisecondsMax.updateMax(labels, costMs) - go reporter.provider.rtMillisecondsAvg.updateAvg(labels, costMs) - go reporter.provider.rtMillisecondsQuantiles.updateQuantile(labels, costMs) - go reporter.provider.rtMillisecondsAggregate.update(labels, costMs) - case consumerField: - go reporter.consumer.rtMillisecondsLast.With(*labels).Set(float64(costMs)) - go reporter.consumer.rtMillisecondsSum.With(*labels).Add(float64(costMs)) - go reporter.consumer.rtMillisecondsMin.updateMin(labels, costMs) - go reporter.consumer.rtMillisecondsMax.updateMax(labels, costMs) - go reporter.consumer.rtMillisecondsAvg.updateAvg(labels, costMs) - go reporter.consumer.rtMillisecondsQuantiles.updateQuantile(labels, costMs) - go reporter.consumer.rtMillisecondsAggregate.update(labels, costMs) - } -} diff --git a/metrics/prometheus/reporter_test.go b/metrics/prometheus/reporter_test.go deleted file mode 100644 index b3ca11c360..0000000000 --- a/metrics/prometheus/reporter_test.go +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package prometheus - -import ( - "context" - "testing" - "time" -) - -import ( - "github.com/stretchr/testify/assert" -) - -import ( - "dubbo.apache.org/dubbo-go/v3/common" - "dubbo.apache.org/dubbo-go/v3/common/extension" - "dubbo.apache.org/dubbo-go/v3/metrics" - "dubbo.apache.org/dubbo-go/v3/protocol" - "dubbo.apache.org/dubbo-go/v3/protocol/invocation" -) - -func TestPrometheusReporter_Report(t *testing.T) { - reporter := extension.GetMetricReporter(reporterName, metrics.NewReporterConfig()) - url, _ := common.NewURL( - "dubbo://:20000/UserProvider?app.version=0.0.1&application=BDTService&bean.name=UserProvider" + - "&cluster=failover&environment=dev&group=&interface=com.ikurento.user.UserProvider&loadbalance=random&methods.GetUser." + - "loadbalance=random&methods.GetUser.retries=1&methods.GetUser.weight=0&module=dubbogo+user-info+server&name=" + - "BDTService&organization=ikurento.com&owner=ZX®istry.role=3&retries=&" + - "service.filter=echo%2Ctoken%2Caccesslog×tamp=1569153406&token=934804bf-b007-4174-94eb-96e3e1d60cc7&version=&warmup=100") - invoker := protocol.NewBaseInvoker(url) - - attach := make(map[string]interface{}, 10) - inv := invocation.NewRPCInvocation("MethodName", []interface{}{"OK", "Hello"}, attach) - - assert.False(t, isConsumer(url)) - ctx := context.Background() - reporter.ReportBeforeInvocation(ctx, invoker, inv) - reporter.ReportAfterInvocation(ctx, invoker, inv, 100*time.Millisecond, nil) - - // consumer side - url, _ = common.NewURL( - "dubbo://:20000/UserProvider?app.version=0.0.1&application=BDTService&bean.name=UserProvider" + - "&cluster=failover&environment=dev&group=&interface=com.ikurento.user.UserProvider&loadbalance=random&methods.GetUser." + - "loadbalance=random&methods.GetUser.retries=1&methods.GetUser.weight=0&module=dubbogo+user-info+server&name=" + - "BDTService&organization=ikurento.com&owner=ZX®istry.role=0&retries=&" + - "service.filter=echo%2Ctoken%2Caccesslog×tamp=1569153406&token=934804bf-b007-4174-94eb-96e3e1d60cc7&version=&warmup=100") - invoker = protocol.NewBaseInvoker(url) - reporter.ReportBeforeInvocation(ctx, invoker, inv) - reporter.ReportAfterInvocation(ctx, invoker, inv, 100*time.Millisecond, nil) - - // invalid role - url, _ = common.NewURL( - "dubbo://:20000/UserProvider?app.version=0.0.1&application=BDTService&bean.name=UserProvider" + - "&cluster=failover&environment=dev&group=&interface=com.ikurento.user.UserProvider&loadbalance=random&methods.GetUser." + - "loadbalance=random&methods.GetUser.retries=1&methods.GetUser.weight=0&module=dubbogo+user-info+server&name=" + - "BDTService&organization=ikurento.com&owner=ZX®istry.role=9&retries=&" + - "service.filter=echo%2Ctoken%2Caccesslog×tamp=1569153406&token=934804bf-b007-4174-94eb-96e3e1d60cc7&version=&warmup=100") - invoker = protocol.NewBaseInvoker(url) - reporter.ReportBeforeInvocation(ctx, invoker, inv) - reporter.ReportAfterInvocation(ctx, invoker, inv, 100*time.Millisecond, nil) -} diff --git a/metrics/reporter.go b/metrics/reporter.go index bf9693bb14..15ca7e09e9 100644 --- a/metrics/reporter.go +++ b/metrics/reporter.go @@ -17,15 +17,6 @@ package metrics -import ( - "context" - "time" -) - -import ( - "dubbo.apache.org/dubbo-go/v3/protocol" -) - const DefMaxAge = 600000000000 type ReporterConfig struct { @@ -36,7 +27,7 @@ type ReporterConfig struct { Path string PushGatewayAddress string SummaryMaxAge int64 - Protocol string // MetricsRegistry 扩展配置 ,如:prometheus + Protocol string // exporters, like prometheus } type ReportMode string @@ -58,11 +49,8 @@ func NewReporterConfig() *ReporterConfig { } } -// Reporter is the interface which will be used to report the invocation's duration -// -// Report method reports the duration of an invocation. +// Reporter is an interface used to represent the backend of metrics to be exported type Reporter interface { - ReportAfterInvocation(ctx context.Context, invoker protocol.Invoker, invocation protocol.Invocation, - cost time.Duration, res protocol.Result) - ReportBeforeInvocation(ctx context.Context, invoker protocol.Invoker, invocation protocol.Invocation) + StartServer(config *ReporterConfig) + ShutdownServer() } diff --git a/metrics/rpc/collector.go b/metrics/rpc/collector.go new file mode 100644 index 0000000000..f59779f6b9 --- /dev/null +++ b/metrics/rpc/collector.go @@ -0,0 +1,161 @@ +/* + * 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 rpc + +import ( + "github.com/dubbogo/gost/log/logger" +) + +import ( + "dubbo.apache.org/dubbo-go/v3/common/constant" + "dubbo.apache.org/dubbo-go/v3/metrics" +) + +var ( + rpcMetricsChan = make(chan metrics.MetricsEvent, 1024) +) + +// init will add the rpc collectorFunc to metrics.collectors slice, and lazy start the rpc collector goroutine +func init() { + var collectorFunc metrics.CollectorFunc + collectorFunc = func(registry metrics.MetricRegistry, c *metrics.ReporterConfig) { + rc := &rpcCollector{ + registry: registry, + metricSet: buildMetricSet(registry), + } + go rc.start() + } + + metrics.AddCollector("rpc", collectorFunc) +} + +// rpcCollector is a collector which will collect the rpc metrics +type rpcCollector struct { + registry metrics.MetricRegistry + metricSet *metricSet // metricSet is a struct which contains all metrics about rpc +} + +// start will subscribe the rpc.metricsEvent from channel rpcMetricsChan, and handle the event from the channel +func (c *rpcCollector) start() { + metrics.Subscribe(constant.MetricsRpc, rpcMetricsChan) + for event := range rpcMetricsChan { + if rpcEvent, ok := event.(*metricsEvent); ok { + switch rpcEvent.name { + case BeforeInvoke: + c.beforeInvokeHandler(rpcEvent) + case AfterInvoke: + c.afterInvokeHandler(rpcEvent) + default: + } + } else { + logger.Error("Bad metrics event found in RPC collector") + } + } +} + +func (c *rpcCollector) beforeInvokeHandler(event *metricsEvent) { + url := event.invoker.GetURL() + role := getRole(url) + + if role == "" { + return + } + labels := buildLabels(url, event.invocation) + c.recordQps(role, labels) + c.incRequestsProcessingTotal(role, labels) +} + +func (c *rpcCollector) afterInvokeHandler(event *metricsEvent) { + url := event.invoker.GetURL() + role := getRole(url) + + if role == "" { + return + } + labels := buildLabels(url, event.invocation) + c.incRequestsTotal(role, labels) + c.decRequestsProcessingTotal(role, labels) + if event.result != nil { + if event.result.Error() == nil { + c.incRequestsSucceedTotal(role, labels) + } + } + c.reportRTMilliseconds(role, labels, event.costTime.Milliseconds()) +} + +func (c *rpcCollector) recordQps(role string, labels map[string]string) { + switch role { + case providerField: + c.metricSet.provider.qpsTotal.Record(labels) + case consumerField: + c.metricSet.consumer.qpsTotal.Record(labels) + } +} + +func (c *rpcCollector) incRequestsTotal(role string, labels map[string]string) { + switch role { + case providerField: + c.metricSet.provider.requestsTotal.Inc(labels) + c.metricSet.provider.requestsTotalAggregate.Inc(labels) + case consumerField: + c.metricSet.consumer.requestsTotal.Inc(labels) + c.metricSet.consumer.requestsTotalAggregate.Inc(labels) + } +} + +func (c *rpcCollector) incRequestsProcessingTotal(role string, labels map[string]string) { + switch role { + case providerField: + c.metricSet.provider.requestsProcessingTotal.Inc(labels) + case consumerField: + c.metricSet.consumer.requestsProcessingTotal.Inc(labels) + } +} + +func (c *rpcCollector) decRequestsProcessingTotal(role string, labels map[string]string) { + switch role { + case providerField: + c.metricSet.provider.requestsProcessingTotal.Dec(labels) + case consumerField: + c.metricSet.consumer.requestsProcessingTotal.Dec(labels) + } +} + +func (c *rpcCollector) incRequestsSucceedTotal(role string, labels map[string]string) { + switch role { + case providerField: + c.metricSet.provider.requestsSucceedTotal.Inc(labels) + c.metricSet.provider.requestsSucceedTotalAggregate.Inc(labels) + case consumerField: + c.metricSet.consumer.requestsSucceedTotal.Inc(labels) + c.metricSet.consumer.requestsSucceedTotalAggregate.Inc(labels) + } +} + +func (c *rpcCollector) reportRTMilliseconds(role string, labels map[string]string, cost int64) { + switch role { + case providerField: + c.metricSet.provider.rtMilliseconds.Record(labels, float64(cost)) + c.metricSet.provider.rtMillisecondsAggregate.Record(labels, float64(cost)) + c.metricSet.provider.rtMillisecondsQuantiles.Record(labels, float64(cost)) + case consumerField: + c.metricSet.consumer.rtMilliseconds.Record(labels, float64(cost)) + c.metricSet.consumer.rtMillisecondsAggregate.Record(labels, float64(cost)) + c.metricSet.consumer.rtMillisecondsQuantiles.Record(labels, float64(cost)) + } +} diff --git a/metrics/prometheus/constant.go b/metrics/rpc/constant.go similarity index 73% rename from metrics/prometheus/constant.go rename to metrics/rpc/constant.go index 41904dba3e..450febef1b 100644 --- a/metrics/prometheus/constant.go +++ b/metrics/rpc/constant.go @@ -15,14 +15,13 @@ * limitations under the License. */ -package prometheus +package rpc import ( "dubbo.apache.org/dubbo-go/v3/common/constant" ) const ( - reporterName = "prometheus" applicationNameKey = constant.ApplicationNameKey groupKey = constant.GroupKey hostnameKey = constant.HostnameKey @@ -35,25 +34,4 @@ const ( const ( providerField = "provider" consumerField = "consumer" - - qpsField = "qps" - requestsField = "requests" - rtField = "rt" - - milliSecondsField = "milliseconds" - - minField = "min" - maxField = "max" - sumField = "sum" - avgField = "avg" - lastField = "last" - - totalField = "total" - aggregateField = "aggregate" - processingField = "processing" - succeedField = "succeed" -) - -var ( - quantiles = []float64{0.5, 0.9, 0.95, 0.99} ) diff --git a/metrics/rpc/event.go b/metrics/rpc/event.go new file mode 100644 index 0000000000..c56ecae539 --- /dev/null +++ b/metrics/rpc/event.go @@ -0,0 +1,67 @@ +/* + * 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 rpc + +import ( + "time" +) + +import ( + "dubbo.apache.org/dubbo-go/v3/common/constant" + "dubbo.apache.org/dubbo-go/v3/metrics" + "dubbo.apache.org/dubbo-go/v3/protocol" +) + +// metricsEvent is the event defined for rpc metrics +type metricsEvent struct { + name metricsName + invoker protocol.Invoker + invocation protocol.Invocation + costTime time.Duration + result protocol.Result +} + +// Type returns the type of the event, it is used for metrics bus to dispatch the event to rpc collector +func (m metricsEvent) Type() string { + return constant.MetricsRpc +} + +type metricsName uint8 + +const ( + BeforeInvoke metricsName = iota + AfterInvoke +) + +func NewBeforeInvokeEvent(invoker protocol.Invoker, invocation protocol.Invocation) metrics.MetricsEvent { + return &metricsEvent{ + name: BeforeInvoke, + invoker: invoker, + invocation: invocation, + } +} + +func NewAfterInvokeEvent(invoker protocol.Invoker, invocation protocol.Invocation, costTime time.Duration, result protocol.Result) metrics.MetricsEvent { + return &metricsEvent{ + name: AfterInvoke, + invoker: invoker, + invocation: invocation, + costTime: costTime, + result: result, + } +} diff --git a/metrics/rpc/metric_set.go b/metrics/rpc/metric_set.go new file mode 100644 index 0000000000..a27d439bc9 --- /dev/null +++ b/metrics/rpc/metric_set.go @@ -0,0 +1,106 @@ +/* + * 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 rpc + +import ( + "dubbo.apache.org/dubbo-go/v3/metrics" +) + +// metricSet is the metric set for rpc +type metricSet struct { + provider *providerMetrics + consumer *consumerMetrics +} + +type providerMetrics struct { + rpcCommonMetrics +} + +type consumerMetrics struct { + rpcCommonMetrics +} + +// rpcCommonMetrics is the common metrics for both provider and consumer +type rpcCommonMetrics struct { + qpsTotal metrics.QpsMetricVec + requestsTotal metrics.CounterVec + requestsTotalAggregate metrics.AggregateCounterVec + requestsProcessingTotal metrics.GaugeVec + requestsSucceedTotal metrics.CounterVec + requestsSucceedTotalAggregate metrics.AggregateCounterVec + rtMilliseconds metrics.RtVec + rtMillisecondsQuantiles metrics.QuantileMetricVec + rtMillisecondsAggregate metrics.RtVec +} + +// buildMetricSet will call init functions to initialize the metricSet +func buildMetricSet(registry metrics.MetricRegistry) *metricSet { + ms := &metricSet{ + provider: &providerMetrics{}, + consumer: &consumerMetrics{}, + } + ms.provider.init(registry) + ms.consumer.init(registry) + return ms +} + +func (pm *providerMetrics) init(registry metrics.MetricRegistry) { + pm.qpsTotal = metrics.NewQpsMetricVec(registry, metrics.NewMetricKey("dubbo_provider_qps_total", "The number of requests received by the provider per second")) + pm.requestsTotal = metrics.NewCounterVec(registry, metrics.NewMetricKey("dubbo_provider_requests_total", "The total number of received requests by the provider")) + pm.requestsTotalAggregate = metrics.NewAggregateCounterVec(registry, metrics.NewMetricKey("dubbo_provider_requests_total_aggregate", "The total number of received requests by the provider under the sliding window")) + pm.requestsProcessingTotal = metrics.NewGaugeVec(registry, metrics.NewMetricKey("dubbo_provider_requests_processing_total", "The number of received requests being processed by the provider")) + pm.requestsSucceedTotal = metrics.NewCounterVec(registry, metrics.NewMetricKey("dubbo_provider_requests_succeed_total", "The number of requests successfully received by the provider")) + pm.requestsSucceedTotalAggregate = metrics.NewAggregateCounterVec(registry, metrics.NewMetricKey("dubbo_provider_requests_succeed_total_aggregate", "The number of successful requests received by the provider under the sliding window")) + pm.rtMilliseconds = metrics.NewRtVec(registry, + metrics.NewMetricKey("dubbo_provider_rt_milliseconds", "response time among all requests processed by the provider"), + &metrics.RtOpts{Aggregate: false}, + ) + pm.rtMillisecondsAggregate = metrics.NewRtVec(registry, + metrics.NewMetricKey("dubbo_provider_rt_milliseconds", "response time of the provider under the sliding window"), + &metrics.RtOpts{Aggregate: true, BucketNum: metrics.DefaultBucketNum, TimeWindowSeconds: metrics.DefaultTimeWindowSeconds}, + ) + pm.rtMillisecondsQuantiles = metrics.NewQuantileMetricVec(registry, []*metrics.MetricKey{ + metrics.NewMetricKey("dubbo_provider_rt_milliseconds_p50", "The total response time spent by providers processing 50% of requests"), + metrics.NewMetricKey("dubbo_provider_rt_milliseconds_p90", "The total response time spent by providers processing 90% of requests"), + metrics.NewMetricKey("dubbo_provider_rt_milliseconds_p95", "The total response time spent by providers processing 95% of requests"), + metrics.NewMetricKey("dubbo_provider_rt_milliseconds_p99", "The total response time spent by providers processing 99% of requests"), + }, []float64{0.5, 0.9, 0.95, 0.99}) +} + +func (cm *consumerMetrics) init(registry metrics.MetricRegistry) { + cm.qpsTotal = metrics.NewQpsMetricVec(registry, metrics.NewMetricKey("dubbo_consumer_qps_total", "The number of requests sent by consumers per second")) + cm.requestsTotal = metrics.NewCounterVec(registry, metrics.NewMetricKey("dubbo_consumer_requests_total", "The total number of requests sent by consumers")) + cm.requestsTotalAggregate = metrics.NewAggregateCounterVec(registry, metrics.NewMetricKey("dubbo_consumer_requests_total_aggregate", "The total number of requests sent by consumers under the sliding window")) + cm.requestsProcessingTotal = metrics.NewGaugeVec(registry, metrics.NewMetricKey("dubbo_consumer_requests_processing_total", "The number of received requests being processed by the consumer")) + cm.requestsSucceedTotal = metrics.NewCounterVec(registry, metrics.NewMetricKey("dubbo_consumer_requests_succeed_total", "The number of successful requests sent by consumers")) + cm.requestsSucceedTotalAggregate = metrics.NewAggregateCounterVec(registry, metrics.NewMetricKey("dubbo_consumer_requests_succeed_total_aggregate", "The number of successful requests sent by consumers under the sliding window")) + cm.rtMilliseconds = metrics.NewRtVec(registry, + metrics.NewMetricKey("dubbo_consumer_rt_milliseconds", "response time among all requests from consumers"), + &metrics.RtOpts{Aggregate: false}, + ) + cm.rtMillisecondsAggregate = metrics.NewRtVec(registry, + metrics.NewMetricKey("dubbo_consumer_rt_milliseconds", "response time of the consumer under the sliding window"), + &metrics.RtOpts{Aggregate: true, BucketNum: metrics.DefaultBucketNum, TimeWindowSeconds: metrics.DefaultTimeWindowSeconds}, + ) + cm.rtMillisecondsQuantiles = metrics.NewQuantileMetricVec(registry, []*metrics.MetricKey{ + metrics.NewMetricKey("dubbo_consumer_rt_milliseconds_p50", "The total response time spent by consumers processing 50% of requests"), + metrics.NewMetricKey("dubbo_consumer_rt_milliseconds_p90", "The total response time spent by consumers processing 90% of requests"), + metrics.NewMetricKey("dubbo_consumer_rt_milliseconds_p95", "The total response time spent by consumers processing 95% of requests"), + metrics.NewMetricKey("dubbo_consumer_rt_milliseconds_p99", "The total response time spent by consumers processing 99% of requests"), + }, []float64{0.5, 0.9, 0.95, 0.99}) +} diff --git a/metrics/prometheus/util.go b/metrics/rpc/util.go similarity index 78% rename from metrics/prometheus/util.go rename to metrics/rpc/util.go index 29e5ebf3c9..7422b390f9 100644 --- a/metrics/prometheus/util.go +++ b/metrics/rpc/util.go @@ -15,7 +15,7 @@ * limitations under the License. */ -package prometheus +package rpc import ( "strconv" @@ -24,33 +24,28 @@ import ( import ( "github.com/dubbogo/gost/log/logger" - - "github.com/prometheus/client_golang/prometheus" ) import ( "dubbo.apache.org/dubbo-go/v3/common" "dubbo.apache.org/dubbo-go/v3/common/constant" + "dubbo.apache.org/dubbo-go/v3/protocol" ) -var ( - labelNames = []string{applicationNameKey, groupKey, hostnameKey, interfaceKey, ipKey, methodKey, versionKey} - defaultHistogramBucket = []float64{10, 50, 100, 200, 500, 1000, 10000} -) - -func buildLabels(url *common.URL) prometheus.Labels { - return prometheus.Labels{ +// buildLabels will build the labels for the rpc metrics +func buildLabels(url *common.URL, invocation protocol.Invocation) map[string]string { + return map[string]string{ applicationNameKey: url.GetParam(constant.ApplicationKey, ""), groupKey: url.Group(), - hostnameKey: "not implemented yet", + hostnameKey: common.GetLocalHostName(), interfaceKey: url.Service(), ipKey: common.GetLocalIp(), versionKey: url.GetParam(constant.AppVersionKey, ""), - methodKey: url.GetParam(constant.MethodKey, ""), + methodKey: invocation.MethodName(), } } -// return the role of the application, provider or consumer, if the url is not a valid one, return empty string +// getRole will get the application role from the url func getRole(url *common.URL) (role string) { if isProvider(url) { role = providerField diff --git a/metrics/util/aggregate/quantile_test.go b/metrics/util/aggregate/quantile_test.go index 5e82431661..d90d09652e 100644 --- a/metrics/util/aggregate/quantile_test.go +++ b/metrics/util/aggregate/quantile_test.go @@ -17,7 +17,9 @@ package aggregate -import "testing" +import ( + "testing" +) func TestAddAndQuantile(t1 *testing.T) { timeWindowQuantile := NewTimeWindowQuantile(100, 10, 1) From da40230e3bf8530801d4dbfcf32719f02d5a67e1 Mon Sep 17 00:00:00 2001 From: foghost Date: Sat, 2 Sep 2023 10:56:50 +0800 Subject: [PATCH 07/22] refactor: change metric config to url like other module (#2396) --- common/constant/key.go | 25 ++++++------ common/constant/metric.go | 62 ++++++++++++++++++++++++++++++ config/metric_config.go | 24 ++++++++++-- config/metric_config_test.go | 2 +- config/root_config.go | 2 +- metrics/api.go | 24 +++++++----- metrics/app_info/collector.go | 3 +- metrics/common.go | 32 +++++++-------- metrics/config_center/collector.go | 5 ++- metrics/metadata/collector.go | 3 +- metrics/prometheus/registry.go | 4 +- metrics/registry/collector.go | 3 +- metrics/rpc/collector.go | 28 +++++++------- metrics/rpc/constant.go | 37 ------------------ metrics/rpc/util.go | 19 ++++----- 15 files changed, 164 insertions(+), 109 deletions(-) create mode 100644 common/constant/metric.go delete mode 100644 metrics/rpc/constant.go diff --git a/common/constant/key.go b/common/constant/key.go index 0db06c01df..f200528785 100644 --- a/common/constant/key.go +++ b/common/constant/key.go @@ -176,10 +176,6 @@ const ( const ( ApplicationKey = "application" - ApplicationNameKey = "application_name" - ApplicationVersionKey = "application_version" - HostnameKey = "hostname" - IpKey = "ip" OrganizationKey = "organization" NameKey = "name" ModuleKey = "module" @@ -198,10 +194,6 @@ const ( ProvidersCategory = "providers" RouterKey = "router" ExportKey = "export" - GitCommitIdKey = "git_commit_id" - ConfigCenterKey = "config_center" - ChangeTypeKey = "change_type" - KeyKey = "key" ) // config center keys @@ -412,10 +404,19 @@ const ( // metrics key const ( - MetricsRpc = "dubbo.metrics.rpc" - MetricsRegistry = "dubbo.metrics.registry" - MetricsMetadata = "dubbo.metrics.metadata" - MetricApp = "dubbo.metrics.app" + AggregationEnabledKey = "aggregation.enabled" + AggregationBucketNumKey = "aggregation.bucket.num" + AggregationTimeWindowSecondsKey = "aggregation.time.window.seconds" + HistogramEnabledKey = "histogram.enabled" + PrometheusExporterEnabledKey = "prometheus.exporter.enabled" + PrometheusExporterMetricsPortKey = "prometheus.exporter.metrics.port" + PrometheusExporterMetricsPathKey = "prometheus.exporter.metrics.path" + PrometheusPushgatewayEnabledKey = "prometheus.pushgateway.enabled" + PrometheusPushgatewayBaseUrlKey = "prometheus.pushgateway.base.url" + PrometheusPushgatewayUsernameKey = "prometheus.pushgateway.username" + PrometheusPushgatewayPasswordKey = "prometheus.pushgateway.password" + PrometheusPushgatewayPushIntervalKey = "prometheus.pushgateway.push.interval" + PrometheusPushgatewayJobKey = "prometheus.pushgateway.job" ) // default meta cache config diff --git a/common/constant/metric.go b/common/constant/metric.go new file mode 100644 index 0000000000..4b35721eba --- /dev/null +++ b/common/constant/metric.go @@ -0,0 +1,62 @@ +/* + * 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 constant + +// metrics type +const ( + MetricsRegistry = "dubbo.metrics.registry" + MetricsMetadata = "dubbo.metrics.metadata" + MetricsApp = "dubbo.metrics.app" + MetricsConfigCenter = "dubbo.metrics.configCenter" + MetricsRpc = "dubbo.metrics.rpc" +) + +const ( + TagApplicationName = "application_name" + TagApplicationVersion = "application_version" + TagHostname = "hostname" + TagIp = "ip" + TagGitCommitId = "git_commit_id" + TagConfigCenter = "config_center" + TagChangeType = "change_type" + TagKey = "key" + TagPid = "pid" + TagInterface = "interface" + TagMethod = "method" + TagGroup = "group" + TagVersion = "version" + TagErrorCode = "error" +) +const ( + MetricNamespace = "dubbo" + ProtocolPrometheus = "prometheus" + ProtocolDefault = ProtocolPrometheus + AggregationCollectorKey = "aggregation" + AggregationDefaultBucketNum = 10 + AggregationDefaultTimeWindowSeconds = 120 + PrometheusDefaultMetricsPath = "/metrics" + PrometheusDefaultMetricsPort = "9090" + PrometheusDefaultPushInterval = 30 + PrometheusDefaultJobName = "default_dubbo_job" + MetricFilterStartTime = "metric_filter_start_time" +) + +const ( + SideProvider = "provider" + SideConsumer = "consumer" +) diff --git a/config/metric_config.go b/config/metric_config.go index a6b874987f..b0e45d06aa 100644 --- a/config/metric_config.go +++ b/config/metric_config.go @@ -17,6 +17,10 @@ package config +import ( + "strconv" +) + import ( "github.com/creasty/defaults" @@ -26,6 +30,8 @@ import ( ) 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" ) @@ -40,6 +46,7 @@ type MetricConfig struct { PushGatewayAddress string `default:"" yaml:"push-gateway-address" json:"push-gateway-address,omitempty" property:"push-gateway-address"` SummaryMaxAge int64 `default:"600000000000" yaml:"summary-max-age" json:"summary-max-age,omitempty" property:"summary-max-age"` Protocol string `default:"prometheus" yaml:"protocol" json:"protocol,omitempty" property:"protocol"` + rootConfig *RootConfig } func (mc *MetricConfig) ToReporterConfig() *metrics.ReporterConfig { @@ -60,7 +67,7 @@ func (mc *MetricConfig) ToReporterConfig() *metrics.ReporterConfig { return defaultMetricsReportConfig } -func (mc *MetricConfig) Init() error { +func (mc *MetricConfig) Init(rc *RootConfig) error { if mc == nil { return errors.New("metrics config is null") } @@ -70,10 +77,10 @@ func (mc *MetricConfig) Init() error { if err := verify(mc); err != nil { return err } - metrics.InitAppInfo(GetRootConfig().Application.Name, GetRootConfig().Application.Version) + mc.rootConfig = rc config := mc.ToReporterConfig() extension.GetMetricReporter(mc.Protocol, config) - metrics.Init(config) + metrics.Init(mc.toURL()) return nil } @@ -100,3 +107,14 @@ func (mc *MetricConfig) DynamicUpdateProperties(newMetricConfig *MetricConfig) { } } } + +// prometheus://localhost:9090?&histogram.enabled=false&prometheus.exporter.enabled=false +func (mc *MetricConfig) toURL() *common.URL { + url, _ := common.NewURL("localhost", common.WithProtocol(mc.Protocol)) + url.SetParam(constant.PrometheusExporterEnabledKey, strconv.FormatBool(*mc.Enable)) + url.SetParam(constant.PrometheusExporterMetricsPortKey, mc.Port) + url.SetParam(constant.PrometheusExporterMetricsPathKey, mc.Path) + url.SetParam(constant.ApplicationKey, mc.rootConfig.Application.Name) + url.SetParam(constant.AppVersionKey, mc.rootConfig.Application.Version) + return url +} diff --git a/config/metric_config_test.go b/config/metric_config_test.go index 14804b3c7c..70dce11b1e 100644 --- a/config/metric_config_test.go +++ b/config/metric_config_test.go @@ -27,7 +27,7 @@ import ( func TestMetricConfigBuilder(t *testing.T) { config := NewMetricConfigBuilder().Build() - err := config.Init() + err := config.Init(&RootConfig{Application: &ApplicationConfig{Name: "dubbo", Version: "1.0.0"}}) assert.NoError(t, err) reporterConfig := config.ToReporterConfig() assert.Equal(t, string(reporterConfig.Mode), "pull") diff --git a/config/root_config.go b/config/root_config.go index 724af48ab0..e578464fe4 100644 --- a/config/root_config.go +++ b/config/root_config.go @@ -182,7 +182,7 @@ func (rc *RootConfig) Init() error { if err := rc.Otel.Init(rc.Application); err != nil { return err } - if err := rc.Metric.Init(); err != nil { + if err := rc.Metric.Init(rc); err != nil { return err } for _, t := range rc.Tracing { diff --git a/metrics/api.go b/metrics/api.go index d0c7f729ea..6a1f519074 100644 --- a/metrics/api.go +++ b/metrics/api.go @@ -27,6 +27,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/util/aggregate" ) @@ -37,31 +39,33 @@ const ( ) var ( - registries = make(map[string]func(*ReporterConfig) MetricRegistry) + registries = make(map[string]func(*common.URL) MetricRegistry) collectors = make([]CollectorFunc, 0) registry MetricRegistry + once sync.Once ) // CollectorFunc used to extend more indicators -type CollectorFunc func(MetricRegistry, *ReporterConfig) +type CollectorFunc func(MetricRegistry, *common.URL) // Init Metrics module -func Init(config *ReporterConfig) { - if config.Enable { +func Init(url *common.URL) { + once.Do(func() { + InitAppInfo(url.GetParam(constant.ApplicationKey, ""), url.GetParam(constant.AppVersionKey, "")) // default protocol is already set in metricConfig - regFunc, ok := registries[config.Protocol] + regFunc, ok := registries[url.Protocol] if ok { - registry = regFunc(config) + registry = regFunc(url) for _, co := range collectors { - co(registry, config) + co(registry, url) } registry.Export() } - } + }) } // SetRegistry extend more MetricRegistry, default PrometheusRegistry -func SetRegistry(name string, v func(*ReporterConfig) MetricRegistry) { +func SetRegistry(name string, v func(*common.URL) MetricRegistry) { registries[name] = v } @@ -93,7 +97,7 @@ type RtOpts struct { // rs []MetricRegistry // } -// Type metric type, save with micrometer +// Type metric type, same with micrometer type Type uint8 // TODO check if Type is is useful const ( diff --git a/metrics/app_info/collector.go b/metrics/app_info/collector.go index a2bae022fe..98abeb4092 100644 --- a/metrics/app_info/collector.go +++ b/metrics/app_info/collector.go @@ -18,6 +18,7 @@ package app_info import ( + "dubbo.apache.org/dubbo-go/v3/common" "dubbo.apache.org/dubbo-go/v3/metrics" ) @@ -29,7 +30,7 @@ import ( var info = metrics.NewMetricKey("dubbo_application_info_total", "Total Application Info") // Total Application Info include application name、version etc func init() { - metrics.AddCollector("application_info", func(mr metrics.MetricRegistry, config *metrics.ReporterConfig) { + metrics.AddCollector("application_info", func(mr metrics.MetricRegistry, _ *common.URL) { mr.Counter(&metrics.MetricId{Name: info.Name, Desc: info.Desc, Tags: metrics.GetApplicationLevel().Tags()}).Inc() }) } diff --git a/metrics/common.go b/metrics/common.go index 3dbe51bd1a..8d8562e869 100644 --- a/metrics/common.go +++ b/metrics/common.go @@ -64,11 +64,11 @@ func GetApplicationLevel() *ApplicationMetricLevel { func (m *ApplicationMetricLevel) Tags() map[string]string { tags := make(map[string]string) - tags[constant.IpKey] = m.Ip - tags[constant.HostnameKey] = m.HostName - tags[constant.ApplicationNameKey] = m.ApplicationName - tags[constant.ApplicationVersionKey] = m.Version - tags[constant.GitCommitIdKey] = m.GitCommitId + tags[constant.TagIp] = m.Ip + tags[constant.TagHostname] = m.HostName + tags[constant.TagApplicationName] = m.ApplicationName + tags[constant.TagApplicationVersion] = m.Version + tags[constant.TagGitCommitId] = m.GitCommitId return tags } @@ -83,7 +83,7 @@ func NewServiceMetric(interfaceName string) *ServiceMetricLevel { func (m ServiceMetricLevel) Tags() map[string]string { tags := m.ApplicationMetricLevel.Tags() - tags[constant.InterfaceKey] = m.Interface + tags[constant.TagInterface] = m.Interface return tags } @@ -96,9 +96,9 @@ type MethodMetricLevel struct { func (m MethodMetricLevel) Tags() map[string]string { tags := m.ServiceMetricLevel.Tags() - tags[constant.MethodKey] = m.Method - tags[constant.GroupKey] = m.Group - tags[constant.VersionKey] = m.Version + tags[constant.TagMethod] = m.Method + tags[constant.TagGroup] = m.Group + tags[constant.TagVersion] = m.Version return tags } @@ -126,12 +126,12 @@ func NewConfigCenterLevel(key string, group string, configCenter string, changeT func (l ConfigCenterLevel) Tags() map[string]string { tags := make(map[string]string) - tags[constant.ApplicationKey] = l.ApplicationName - tags[constant.IpKey] = l.Ip - tags[constant.HostnameKey] = l.HostName - tags[constant.KeyKey] = l.Key - tags[constant.GroupKey] = l.Group - tags[constant.ConfigCenterKey] = l.ConfigCenter - tags[constant.ChangeTypeKey] = l.ChangeType + tags[constant.TagApplicationName] = l.ApplicationName + tags[constant.TagIp] = l.Ip + tags[constant.TagHostname] = l.HostName + tags[constant.TagKey] = l.Key + tags[constant.TagGroup] = l.Group + tags[constant.TagConfigCenter] = l.ConfigCenter + tags[constant.TagChangeType] = l.ChangeType return tags } diff --git a/metrics/config_center/collector.go b/metrics/config_center/collector.go index 7236501882..9ae551f0e5 100644 --- a/metrics/config_center/collector.go +++ b/metrics/config_center/collector.go @@ -18,18 +18,19 @@ package metrics import ( + "dubbo.apache.org/dubbo-go/v3/common" "dubbo.apache.org/dubbo-go/v3/common/constant" "dubbo.apache.org/dubbo-go/v3/metrics" "dubbo.apache.org/dubbo-go/v3/remoting" ) -const eventType = constant.MetricApp +const eventType = constant.MetricsConfigCenter var ch = make(chan metrics.MetricsEvent, 10) var info = metrics.NewMetricKey("dubbo_configcenter_total", "Config Changed Total") func init() { - metrics.AddCollector("application_info", func(mr metrics.MetricRegistry, config *metrics.ReporterConfig) { + metrics.AddCollector("config_center", func(mr metrics.MetricRegistry, _ *common.URL) { c := &configCenterCollector{r: mr} c.start() }) diff --git a/metrics/metadata/collector.go b/metrics/metadata/collector.go index 23921242f1..7125fb1f14 100644 --- a/metrics/metadata/collector.go +++ b/metrics/metadata/collector.go @@ -22,6 +22,7 @@ import ( ) import ( + "dubbo.apache.org/dubbo-go/v3/common" "dubbo.apache.org/dubbo-go/v3/common/constant" "dubbo.apache.org/dubbo-go/v3/metrics" ) @@ -31,7 +32,7 @@ const eventType = constant.MetricsMetadata var ch = make(chan metrics.MetricsEvent, 10) func init() { - metrics.AddCollector("metadata", func(mr metrics.MetricRegistry, rc *metrics.ReporterConfig) { + metrics.AddCollector("metadata", func(mr metrics.MetricRegistry, _ *common.URL) { l := &MetadataMetricCollector{metrics.BaseCollector{R: mr}} l.start() }) diff --git a/metrics/prometheus/registry.go b/metrics/prometheus/registry.go index 144a3a0599..2a4c712439 100644 --- a/metrics/prometheus/registry.go +++ b/metrics/prometheus/registry.go @@ -29,11 +29,13 @@ import ( ) import ( + "dubbo.apache.org/dubbo-go/v3/common" + "dubbo.apache.org/dubbo-go/v3/common/constant" "dubbo.apache.org/dubbo-go/v3/metrics" ) func init() { - metrics.SetRegistry("prometheus", func(rc *metrics.ReporterConfig) metrics.MetricRegistry { + metrics.SetRegistry(constant.ProtocolPrometheus, func(url *common.URL) metrics.MetricRegistry { return &promMetricRegistry{r: prom.DefaultRegisterer} }) } diff --git a/metrics/registry/collector.go b/metrics/registry/collector.go index fcd94b9740..53a5d71b30 100644 --- a/metrics/registry/collector.go +++ b/metrics/registry/collector.go @@ -18,6 +18,7 @@ package registry import ( + "dubbo.apache.org/dubbo-go/v3/common" "dubbo.apache.org/dubbo-go/v3/common/constant" "dubbo.apache.org/dubbo-go/v3/metrics" ) @@ -27,7 +28,7 @@ var ( ) func init() { - metrics.AddCollector("registry", func(m metrics.MetricRegistry, c *metrics.ReporterConfig) { + metrics.AddCollector("registry", func(m metrics.MetricRegistry, _ *common.URL) { rc := ®istryCollector{metrics.BaseCollector{R: m}} go rc.start() }) diff --git a/metrics/rpc/collector.go b/metrics/rpc/collector.go index f59779f6b9..dc9fb53347 100644 --- a/metrics/rpc/collector.go +++ b/metrics/rpc/collector.go @@ -22,6 +22,7 @@ import ( ) import ( + "dubbo.apache.org/dubbo-go/v3/common" "dubbo.apache.org/dubbo-go/v3/common/constant" "dubbo.apache.org/dubbo-go/v3/metrics" ) @@ -32,8 +33,7 @@ var ( // init will add the rpc collectorFunc to metrics.collectors slice, and lazy start the rpc collector goroutine func init() { - var collectorFunc metrics.CollectorFunc - collectorFunc = func(registry metrics.MetricRegistry, c *metrics.ReporterConfig) { + collectorFunc := func(registry metrics.MetricRegistry, c *common.URL) { rc := &rpcCollector{ registry: registry, metricSet: buildMetricSet(registry), @@ -100,19 +100,19 @@ func (c *rpcCollector) afterInvokeHandler(event *metricsEvent) { func (c *rpcCollector) recordQps(role string, labels map[string]string) { switch role { - case providerField: + case constant.SideProvider: c.metricSet.provider.qpsTotal.Record(labels) - case consumerField: + case constant.SideConsumer: c.metricSet.consumer.qpsTotal.Record(labels) } } func (c *rpcCollector) incRequestsTotal(role string, labels map[string]string) { switch role { - case providerField: + case constant.SideProvider: c.metricSet.provider.requestsTotal.Inc(labels) c.metricSet.provider.requestsTotalAggregate.Inc(labels) - case consumerField: + case constant.SideConsumer: c.metricSet.consumer.requestsTotal.Inc(labels) c.metricSet.consumer.requestsTotalAggregate.Inc(labels) } @@ -120,28 +120,28 @@ func (c *rpcCollector) incRequestsTotal(role string, labels map[string]string) { func (c *rpcCollector) incRequestsProcessingTotal(role string, labels map[string]string) { switch role { - case providerField: + case constant.SideProvider: c.metricSet.provider.requestsProcessingTotal.Inc(labels) - case consumerField: + case constant.SideConsumer: c.metricSet.consumer.requestsProcessingTotal.Inc(labels) } } func (c *rpcCollector) decRequestsProcessingTotal(role string, labels map[string]string) { switch role { - case providerField: + case constant.SideProvider: c.metricSet.provider.requestsProcessingTotal.Dec(labels) - case consumerField: + case constant.SideConsumer: c.metricSet.consumer.requestsProcessingTotal.Dec(labels) } } func (c *rpcCollector) incRequestsSucceedTotal(role string, labels map[string]string) { switch role { - case providerField: + case constant.SideProvider: c.metricSet.provider.requestsSucceedTotal.Inc(labels) c.metricSet.provider.requestsSucceedTotalAggregate.Inc(labels) - case consumerField: + case constant.SideConsumer: c.metricSet.consumer.requestsSucceedTotal.Inc(labels) c.metricSet.consumer.requestsSucceedTotalAggregate.Inc(labels) } @@ -149,11 +149,11 @@ func (c *rpcCollector) incRequestsSucceedTotal(role string, labels map[string]st func (c *rpcCollector) reportRTMilliseconds(role string, labels map[string]string, cost int64) { switch role { - case providerField: + case constant.SideProvider: c.metricSet.provider.rtMilliseconds.Record(labels, float64(cost)) c.metricSet.provider.rtMillisecondsAggregate.Record(labels, float64(cost)) c.metricSet.provider.rtMillisecondsQuantiles.Record(labels, float64(cost)) - case consumerField: + case constant.SideConsumer: c.metricSet.consumer.rtMilliseconds.Record(labels, float64(cost)) c.metricSet.consumer.rtMillisecondsAggregate.Record(labels, float64(cost)) c.metricSet.consumer.rtMillisecondsQuantiles.Record(labels, float64(cost)) diff --git a/metrics/rpc/constant.go b/metrics/rpc/constant.go deleted file mode 100644 index 450febef1b..0000000000 --- a/metrics/rpc/constant.go +++ /dev/null @@ -1,37 +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 rpc - -import ( - "dubbo.apache.org/dubbo-go/v3/common/constant" -) - -const ( - applicationNameKey = constant.ApplicationNameKey - groupKey = constant.GroupKey - hostnameKey = constant.HostnameKey - interfaceKey = constant.InterfaceKey - ipKey = constant.IpKey - methodKey = constant.MethodKey - versionKey = constant.VersionKey -) - -const ( - providerField = "provider" - consumerField = "consumer" -) diff --git a/metrics/rpc/util.go b/metrics/rpc/util.go index 7422b390f9..e8437bf957 100644 --- a/metrics/rpc/util.go +++ b/metrics/rpc/util.go @@ -35,22 +35,23 @@ import ( // buildLabels will build the labels for the rpc metrics func buildLabels(url *common.URL, invocation protocol.Invocation) map[string]string { return map[string]string{ - applicationNameKey: url.GetParam(constant.ApplicationKey, ""), - groupKey: url.Group(), - hostnameKey: common.GetLocalHostName(), - interfaceKey: url.Service(), - ipKey: common.GetLocalIp(), - versionKey: url.GetParam(constant.AppVersionKey, ""), - methodKey: invocation.MethodName(), + constant.TagApplicationName: url.GetParam(constant.ApplicationKey, ""), + constant.TagApplicationVersion: url.GetParam(constant.AppVersionKey, ""), + constant.TagHostname: common.GetLocalHostName(), + constant.TagIp: common.GetLocalIp(), + constant.TagInterface: url.Service(), + constant.TagMethod: invocation.MethodName(), + constant.TagGroup: url.Group(), + constant.TagVersion: url.GetParam(constant.VersionKey, ""), } } // getRole will get the application role from the url func getRole(url *common.URL) (role string) { if isProvider(url) { - role = providerField + role = constant.SideProvider } else if isConsumer(url) { - role = consumerField + role = constant.SideConsumer } else { logger.Warnf("The url belongs neither the consumer nor the provider, "+ "so the invocation will be ignored. url: %s", url.String()) From 314b09d5edb8d21ada1de0a4cd59f84b56b85d71 Mon Sep 17 00:00:00 2001 From: Wang Guan Date: Mon, 4 Sep 2023 14:04:53 +0800 Subject: [PATCH 08/22] refactor: simplify configuration when enable metrics (#2408) --- common/constant/default.go | 2 +- config/reference_config.go | 7 +++++++ config/service_config.go | 7 +++++++ config/service_config_test.go | 2 +- 4 files changed, 16 insertions(+), 2 deletions(-) diff --git a/common/constant/default.go b/common/constant/default.go index 8f5ca5584a..a27da2f4d1 100644 --- a/common/constant/default.go +++ b/common/constant/default.go @@ -59,7 +59,7 @@ const ( // DefaultServiceFilters defines default service filters, it is highly recommended // that put the AdaptiveServiceProviderFilterKey at the end. DefaultServiceFilters = EchoFilterKey + "," + - MetricsFilterKey + "," + TokenFilterKey + "," + AccessLogFilterKey + "," + TpsLimitFilterKey + "," + + TokenFilterKey + "," + AccessLogFilterKey + "," + TpsLimitFilterKey + "," + GenericServiceFilterKey + "," + ExecuteLimitFilterKey + "," + GracefulShutdownProviderFilterKey DefaultReferenceFilters = GracefulShutdownConsumerFilterKey diff --git a/config/reference_config.go b/config/reference_config.go index 06797a8ece..64d7c53a3d 100644 --- a/config/reference_config.go +++ b/config/reference_config.go @@ -74,6 +74,7 @@ type ReferenceConfig struct { TracingKey string `yaml:"tracing-key" json:"tracing-key,omitempty" propertiy:"tracing-key"` rootConfig *RootConfig metaDataType string + metricsEnable bool MeshProviderPort int `yaml:"mesh-provider-port" json:"mesh-provider-port,omitempty" propertiy:"mesh-provider-port"` } @@ -118,6 +119,9 @@ func (rc *ReferenceConfig) Init(root *RootConfig) error { if rc.TracingKey == "" { rc.TracingKey = root.Consumer.TracingKey } + if root.Metric.Enable != nil { + rc.metricsEnable = *root.Metric.Enable + } if rc.Check == nil { rc.Check = &root.Consumer.Check } @@ -355,6 +359,9 @@ func (rc *ReferenceConfig) getURLMap() url.Values { if rc.Generic != "" { defaultReferenceFilter = constant.GenericFilterKey + "," + defaultReferenceFilter } + if rc.metricsEnable { + defaultReferenceFilter += fmt.Sprintf(",%s", constant.MetricsFilterKey) + } urlMap.Set(constant.ReferenceFilterKey, mergeValue(rc.Filter, "", defaultReferenceFilter)) for _, v := range rc.Methods { diff --git a/config/service_config.go b/config/service_config.go index 976071a2bf..1b0038ed06 100644 --- a/config/service_config.go +++ b/config/service_config.go @@ -82,6 +82,7 @@ type ServiceConfig struct { RCRegistriesMap map[string]*RegistryConfig ProxyFactoryKey string adaptiveService bool + metricsEnable bool // whether append metrics filter to filter chain unexported *atomic.Bool exported *atomic.Bool export bool // a flag to control whether the current service should export or not @@ -144,6 +145,9 @@ func (s *ServiceConfig) Init(rc *RootConfig) error { if s.TracingKey == "" { s.TracingKey = rc.Provider.TracingKey } + if rc.Metric.Enable != nil { + s.metricsEnable = *rc.Metric.Enable + } err := s.check() if err != nil { panic(err) @@ -427,6 +431,9 @@ func (s *ServiceConfig) getUrlMap() url.Values { if s.adaptiveService { filters += fmt.Sprintf(",%s", constant.AdaptiveServiceProviderFilterKey) } + if s.metricsEnable { + filters += fmt.Sprintf(",%s", constant.MetricsFilterKey) + } urlMap.Set(constant.ServiceFilterKey, filters) // filter special config diff --git a/config/service_config_test.go b/config/service_config_test.go index da6b5af0dd..4f5954acfa 100644 --- a/config/service_config_test.go +++ b/config/service_config_test.go @@ -114,7 +114,7 @@ func TestNewServiceConfigBuilder(t *testing.T) { values := serviceConfig.getUrlMap() assert.Equal(t, values.Get("methods.Say.weight"), "0") assert.Equal(t, values.Get("methods.Say.tps.limit.rate"), "") - assert.Equal(t, values.Get(constant.ServiceFilterKey), "echo,metrics,token,accesslog,tps,generic_service,execute,pshutdown") + assert.Equal(t, values.Get(constant.ServiceFilterKey), "echo,token,accesslog,tps,generic_service,execute,pshutdown") }) t.Run("Implement", func(t *testing.T) { From fb6641dc99c23a10f9dabf4e753397ac889c549b Mon Sep 17 00:00:00 2001 From: foghost Date: Mon, 4 Sep 2023 14:06:07 +0800 Subject: [PATCH 09/22] add prometheus pushgateway support (#2415) --- common/extension/metrics.go | 42 ------------ common/extension/metrics_test.go | 49 ------------- config/metric_config.go | 82 ++++++++++++++-------- metrics/prometheus/registry.go | 96 ++++++++++++++++++++++---- metrics/prometheus/registry_test.go | 87 +++++++++++++++++++++-- metrics/prometheus/reporter.go | 103 ---------------------------- 6 files changed, 213 insertions(+), 246 deletions(-) delete mode 100644 common/extension/metrics.go delete mode 100644 common/extension/metrics_test.go delete mode 100644 metrics/prometheus/reporter.go diff --git a/common/extension/metrics.go b/common/extension/metrics.go deleted file mode 100644 index 639d921065..0000000000 --- a/common/extension/metrics.go +++ /dev/null @@ -1,42 +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 extension - -import ( - "dubbo.apache.org/dubbo-go/v3/metrics" -) - -// we couldn't store the instance because the some instance may initialize before loading configuration -// so lazy initialization will be better. -var metricReporterMap = make(map[string]func(config *metrics.ReporterConfig) metrics.Reporter, 4) - -// SetMetricReporter sets a reporter with the @name -func SetMetricReporter(name string, reporterFunc func(config *metrics.ReporterConfig) metrics.Reporter) { - metricReporterMap[name] = reporterFunc -} - -// GetMetricReporter finds the reporter with @name. -// if not found, it will panic. -// we should know that this method usually is called when system starts, so we should panic -func GetMetricReporter(name string, config *metrics.ReporterConfig) metrics.Reporter { - reporterFunc, found := metricReporterMap[name] - if !found { - panic("Cannot find the reporter with name: " + name) - } - return reporterFunc(config) -} diff --git a/common/extension/metrics_test.go b/common/extension/metrics_test.go deleted file mode 100644 index 64f76422ca..0000000000 --- a/common/extension/metrics_test.go +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package extension - -import ( - "testing" -) - -import ( - "github.com/stretchr/testify/assert" -) - -import ( - "dubbo.apache.org/dubbo-go/v3/metrics" -) - -func TestGetMetricReporter(t *testing.T) { - reporter := &mockReporter{} - name := "mock" - SetMetricReporter(name, func(config *metrics.ReporterConfig) metrics.Reporter { - return reporter - }) - res := GetMetricReporter(name, metrics.NewReporterConfig()) - assert.Equal(t, reporter, res) -} - -type mockReporter struct{} - -// implement the interface of Reporter -func (m *mockReporter) StartServer(config *metrics.ReporterConfig) { -} - -func (m *mockReporter) ShutdownServer() { -} diff --git a/config/metric_config.go b/config/metric_config.go index b0e45d06aa..0859b57ccd 100644 --- a/config/metric_config.go +++ b/config/metric_config.go @@ -24,45 +24,56 @@ import ( import ( "github.com/creasty/defaults" - "github.com/dubbogo/gost/log/logger" - "github.com/pkg/errors" ) 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" ) // MetricConfig This is the config struct for all metrics implementation type MetricConfig struct { - Mode string `default:"pull" yaml:"mode" json:"mode,omitempty" property:"mode"` // push or pull, - Namespace string `default:"dubbo" yaml:"namespace" json:"namespace,omitempty" property:"namespace"` - Enable *bool `default:"false" yaml:"enable" json:"enable,omitempty" property:"enable"` - Port string `default:"9090" yaml:"port" json:"port,omitempty" property:"port"` - Path string `default:"/metrics" yaml:"path" json:"path,omitempty" property:"path"` - PushGatewayAddress string `default:"" yaml:"push-gateway-address" json:"push-gateway-address,omitempty" property:"push-gateway-address"` - SummaryMaxAge int64 `default:"600000000000" yaml:"summary-max-age" json:"summary-max-age,omitempty" property:"summary-max-age"` - Protocol string `default:"prometheus" yaml:"protocol" json:"protocol,omitempty" property:"protocol"` - rootConfig *RootConfig + Enable *bool `default:"false" yaml:"enable" json:"enable,omitempty" property:"enable"` + Port string `default:"9090" yaml:"port" json:"port,omitempty" property:"port"` + Path string `default:"/metrics" yaml:"path" json:"path,omitempty" property:"path"` + Protocol string `default:"prometheus" yaml:"protocol" json:"protocol,omitempty" property:"protocol"` + Prometheus *PrometheusConfig `yaml:"prometheus" json:"prometheus" property:"prometheus"` + Aggregation *AggregateConfig `yaml:"aggregation" json:"aggregation" property:"aggregation"` + rootConfig *RootConfig +} + +type AggregateConfig struct { + Enabled *bool `default:"false" yaml:"enabled" json:"enabled,omitempty" property:"enabled"` + BucketNum int `default:"10" yaml:"bucket-num" json:"bucket-num,omitempty" property:"bucket-num"` + TimeWindowSeconds int `default:"120" yaml:"time-window-seconds" json:"time-window-seconds,omitempty" property:"time-window-seconds"` +} + +type PrometheusConfig struct { + Exporter *Exporter `yaml:"exporter" json:"exporter,omitempty" property:"exporter"` + Pushgateway *PushgatewayConfig `yaml:"pushgateway" json:"pushgateway,omitempty" property:"pushgateway"` +} + +type Exporter struct { + Enabled *bool `default:"false" yaml:"enabled" json:"enabled,omitempty" property:"enabled"` +} + +type PushgatewayConfig struct { + Enabled *bool `default:"false" yaml:"enabled" json:"enabled,omitempty" property:"enabled"` + BaseUrl string `default:"" yaml:"base-url" json:"base-url,omitempty" property:"base-url"` + Job string `default:"default_dubbo_job" yaml:"job" json:"job,omitempty" property:"job"` + Username string `default:"" yaml:"username" json:"username,omitempty" property:"username"` + Password string `default:"" yaml:"password" json:"password,omitempty" property:"password"` + PushInterval int `default:"30" yaml:"push-interval" json:"push-interval,omitempty" property:"push-interval"` } func (mc *MetricConfig) ToReporterConfig() *metrics.ReporterConfig { defaultMetricsReportConfig := metrics.NewReporterConfig() - if mc.Mode == metrics.ReportModePush { - defaultMetricsReportConfig.Mode = metrics.ReportModePush - } - if mc.Namespace != "" { - defaultMetricsReportConfig.Namespace = mc.Namespace - } defaultMetricsReportConfig.Enable = *mc.Enable defaultMetricsReportConfig.Port = mc.Port defaultMetricsReportConfig.Path = mc.Path - defaultMetricsReportConfig.PushGatewayAddress = mc.PushGatewayAddress - defaultMetricsReportConfig.SummaryMaxAge = mc.SummaryMaxAge defaultMetricsReportConfig.Protocol = mc.Protocol return defaultMetricsReportConfig } @@ -78,8 +89,6 @@ func (mc *MetricConfig) Init(rc *RootConfig) error { return err } mc.rootConfig = rc - config := mc.ToReporterConfig() - extension.GetMetricReporter(mc.Protocol, config) metrics.Init(mc.toURL()) return nil } @@ -98,14 +107,7 @@ func (mcb *MetricConfigBuilder) Build() *MetricConfig { // DynamicUpdateProperties dynamically update properties. func (mc *MetricConfig) DynamicUpdateProperties(newMetricConfig *MetricConfig) { - if newMetricConfig != nil { - if newMetricConfig.Enable != mc.Enable { - mc.Enable = newMetricConfig.Enable - logger.Infof("MetricConfig's Enable was dynamically updated, new value:%v", mc.Enable) - - extension.GetMetricReporter(mc.Protocol, mc.ToReporterConfig()) - } - } + // TODO update } // prometheus://localhost:9090?&histogram.enabled=false&prometheus.exporter.enabled=false @@ -116,5 +118,25 @@ func (mc *MetricConfig) toURL() *common.URL { url.SetParam(constant.PrometheusExporterMetricsPathKey, mc.Path) url.SetParam(constant.ApplicationKey, mc.rootConfig.Application.Name) url.SetParam(constant.AppVersionKey, mc.rootConfig.Application.Version) + if mc.Aggregation != nil { + url.SetParam(constant.AggregationEnabledKey, strconv.FormatBool(*mc.Aggregation.Enabled)) + url.SetParam(constant.AggregationBucketNumKey, strconv.Itoa(mc.Aggregation.BucketNum)) + url.SetParam(constant.AggregationTimeWindowSecondsKey, strconv.Itoa(mc.Aggregation.TimeWindowSeconds)) + } + if mc.Prometheus != nil { + if mc.Prometheus.Exporter != nil { + exporter := mc.Prometheus.Exporter + url.SetParam(constant.PrometheusExporterEnabledKey, strconv.FormatBool(*exporter.Enabled || *mc.Enable)) // for compatibility + } + if mc.Prometheus.Pushgateway != nil { + pushGateWay := mc.Prometheus.Pushgateway + url.SetParam(constant.PrometheusPushgatewayEnabledKey, strconv.FormatBool(*pushGateWay.Enabled)) + url.SetParam(constant.PrometheusPushgatewayBaseUrlKey, pushGateWay.BaseUrl) + url.SetParam(constant.PrometheusPushgatewayUsernameKey, pushGateWay.Username) + url.SetParam(constant.PrometheusPushgatewayPasswordKey, pushGateWay.Password) + url.SetParam(constant.PrometheusPushgatewayPushIntervalKey, strconv.Itoa(pushGateWay.PushInterval)) + url.SetParam(constant.PrometheusPushgatewayJobKey, pushGateWay.Job) + } + } return url } diff --git a/metrics/prometheus/registry.go b/metrics/prometheus/registry.go index 2a4c712439..f84f2ad552 100644 --- a/metrics/prometheus/registry.go +++ b/metrics/prometheus/registry.go @@ -19,11 +19,18 @@ package prometheus import ( "bytes" + "context" + "net/http" "sync" + "time" ) import ( + "github.com/dubbogo/gost/log/logger" + prom "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/client_golang/prometheus/promhttp" + "github.com/prometheus/client_golang/prometheus/push" "github.com/prometheus/common/expfmt" ) @@ -31,21 +38,28 @@ import ( 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" ) func init() { metrics.SetRegistry(constant.ProtocolPrometheus, func(url *common.URL) metrics.MetricRegistry { - return &promMetricRegistry{r: prom.DefaultRegisterer} + return &promMetricRegistry{r: prom.DefaultRegisterer, gather: prom.DefaultGatherer, url: url} }) } type promMetricRegistry struct { - r prom.Registerer // for convenience of testing - vecs sync.Map + r prom.Registerer + gather prom.Gatherer + vecs sync.Map + url *common.URL +} + +func NewPromMetricRegistry(reg *prom.Registry, url *common.URL) *promMetricRegistry { + return &promMetricRegistry{r: reg, gather: reg, url: url} } -func (p *promMetricRegistry) getOrComputeVec(key string, supplier func() interface{}) interface{} { +func (p *promMetricRegistry) getOrComputeVec(key string, supplier func() prom.Collector) interface{} { v, ok := p.vecs.Load(key) if !ok { v, ok = p.vecs.LoadOrStore(key, supplier()) @@ -57,7 +71,7 @@ func (p *promMetricRegistry) getOrComputeVec(key string, supplier func() interfa } func (p *promMetricRegistry) Counter(m *metrics.MetricId) metrics.CounterMetric { - vec := p.getOrComputeVec(m.Name, func() interface{} { + vec := p.getOrComputeVec(m.Name, func() prom.Collector { return prom.NewCounterVec(prom.CounterOpts{ Name: m.Name, Help: m.Desc, @@ -67,7 +81,7 @@ func (p *promMetricRegistry) Counter(m *metrics.MetricId) metrics.CounterMetric } func (p *promMetricRegistry) Gauge(m *metrics.MetricId) metrics.GaugeMetric { - vec := p.getOrComputeVec(m.Name, func() interface{} { + vec := p.getOrComputeVec(m.Name, func() prom.Collector { return prom.NewGaugeVec(prom.GaugeOpts{ Name: m.Name, Help: m.Desc, @@ -77,7 +91,7 @@ func (p *promMetricRegistry) Gauge(m *metrics.MetricId) metrics.GaugeMetric { } func (p *promMetricRegistry) Histogram(m *metrics.MetricId) metrics.ObservableMetric { - vec := p.getOrComputeVec(m.Name, func() interface{} { + vec := p.getOrComputeVec(m.Name, func() prom.Collector { return prom.NewHistogramVec(prom.HistogramOpts{ Name: m.Name, Help: m.Desc, @@ -87,7 +101,7 @@ func (p *promMetricRegistry) Histogram(m *metrics.MetricId) metrics.ObservableMe } func (p *promMetricRegistry) Summary(m *metrics.MetricId) metrics.ObservableMetric { - vec := p.getOrComputeVec(m.Name, func() interface{} { + vec := p.getOrComputeVec(m.Name, func() prom.Collector { return prom.NewSummaryVec(prom.SummaryOpts{ Name: m.Name, Help: m.Desc, @@ -98,11 +112,16 @@ func (p *promMetricRegistry) Summary(m *metrics.MetricId) metrics.ObservableMetr func (p *promMetricRegistry) Rt(m *metrics.MetricId, opts *metrics.RtOpts) metrics.ObservableMetric { key := m.Name - var supplier func() interface{} + var supplier func() prom.Collector if opts != nil && opts.Aggregate { key += "_aggregate" - supplier = func() interface{} { - // TODO set default aggregate config from config + if opts.BucketNum == 0 { + opts.BucketNum = p.url.GetParamByIntValue(constant.AggregationBucketNumKey, constant.AggregationDefaultBucketNum) + } + if opts.TimeWindowSeconds == 0 { + opts.TimeWindowSeconds = p.url.GetParamInt(constant.AggregationTimeWindowSecondsKey, constant.AggregationDefaultTimeWindowSeconds) + } + supplier = func() prom.Collector { return NewAggRtVec(&RtOpts{ Name: m.Name, Help: m.Desc, @@ -111,7 +130,7 @@ func (p *promMetricRegistry) Rt(m *metrics.MetricId, opts *metrics.RtOpts) metri }, m.TagKeys()) } } else { - supplier = func() interface{} { + supplier = func() prom.Collector { return NewRtVec(&RtOpts{ Name: m.Name, Help: m.Desc, @@ -123,12 +142,59 @@ func (p *promMetricRegistry) Rt(m *metrics.MetricId, opts *metrics.RtOpts) metri } func (p *promMetricRegistry) Export() { - // use promauto export global, TODO move here + if p.url.GetParamBool(constant.PrometheusExporterEnabledKey, false) { + go func() { + mux := http.NewServeMux() + path := p.url.GetParam(constant.PrometheusDefaultMetricsPath, constant.PrometheusDefaultMetricsPath) + port := p.url.GetParam(constant.PrometheusExporterMetricsPortKey, constant.PrometheusDefaultMetricsPort) + mux.Handle(path, promhttp.InstrumentMetricHandler(p.r, promhttp.HandlerFor(p.gather, promhttp.HandlerOpts{}))) + srv := &http.Server{Addr: ":" + port, Handler: mux} + extension.AddCustomShutdownCallback(func() { + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + if err := srv.Shutdown(ctx); nil != err { + logger.Fatalf("prometheus server shutdown failed, err: %v", err) + } else { + logger.Info("prometheus server gracefully shutdown success") + } + }) + logger.Infof("prometheus endpoint :%s%s", port, path) + if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed { // except Shutdown or Close + logger.Errorf("new prometheus server with error = %v", err) + } + }() + } + if p.url.GetParamBool(constant.PrometheusPushgatewayEnabledKey, false) { + baseUrl, exist := p.url.GetNonDefaultParam(constant.PrometheusPushgatewayBaseUrlKey) + if !exist { + logger.Error("no pushgateway url found in config path: metrics.prometheus.pushgateway.bash-url, please check your config file") + return + } + username := p.url.GetParam(constant.PrometheusPushgatewayBaseUrlKey, "") + password := p.url.GetParam(constant.PrometheusPushgatewayBaseUrlKey, "") + job := p.url.GetParam(constant.PrometheusPushgatewayJobKey, constant.PrometheusDefaultJobName) + pushInterval := p.url.GetParamByIntValue(constant.PrometheusPushgatewayPushIntervalKey, constant.PrometheusDefaultPushInterval) + pusher := push.New(baseUrl, job).Gatherer(p.gather) + if len(username) != 0 { + pusher.BasicAuth(username, password) + } + logger.Infof("prometheus pushgateway will push to %s every %d seconds", baseUrl, pushInterval) + ticker := time.NewTicker(time.Duration(pushInterval) * time.Second) + go func() { + for range ticker.C { + err := pusher.Add() + if err != nil { + logger.Errorf("push metric data to prometheus push gateway error", err) + } else { + logger.Debugf("prometheus pushgateway push to %s success", baseUrl) + } + } + }() + } } func (p *promMetricRegistry) Scrape() (string, error) { - r := p.r.(prom.Gatherer) - gathering, err := r.Gather() + gathering, err := p.gather.Gather() if err != nil { return "", err } diff --git a/metrics/prometheus/registry_test.go b/metrics/prometheus/registry_test.go index 7e7ac2afcd..a3e5e6636f 100644 --- a/metrics/prometheus/registry_test.go +++ b/metrics/prometheus/registry_test.go @@ -18,8 +18,11 @@ package prometheus import ( + "io" + "net/http" "sync" "testing" + "time" ) import ( @@ -29,16 +32,32 @@ import ( ) import ( + "dubbo.apache.org/dubbo-go/v3/common" + "dubbo.apache.org/dubbo-go/v3/common/constant" "dubbo.apache.org/dubbo-go/v3/metrics" ) var ( tags = map[string]string{"app": "dubbo", "version": "1.0.0"} metricId = &metrics.MetricId{Name: "dubbo_request", Desc: "request", Tags: tags} + url = common.NewURLWithOptions( + common.WithProtocol(constant.ProtocolPrometheus), + common.WithParamsValue(constant.PrometheusExporterEnabledKey, "true"), + common.WithParamsValue(constant.PrometheusExporterMetricsPortKey, constant.PrometheusDefaultMetricsPort), + common.WithParamsValue(constant.PrometheusExporterMetricsPathKey, constant.PrometheusDefaultMetricsPath), + common.WithParamsValue(constant.ApplicationKey, "dubbo"), + common.WithParamsValue(constant.AppVersionKey, "1.0.0"), + common.WithParamsValue(constant.PrometheusPushgatewayEnabledKey, "true"), + common.WithParamsValue(constant.PrometheusPushgatewayBaseUrlKey, "localhost:9091"), + common.WithParamsValue(constant.PrometheusPushgatewayUsernameKey, ""), + common.WithParamsValue(constant.PrometheusPushgatewayPasswordKey, ""), + common.WithParamsValue(constant.PrometheusPushgatewayPushIntervalKey, "2"), + common.WithParamsValue(constant.PrometheusPushgatewayJobKey, "dubbo-push"), + ) ) func TestPromMetricRegistryCounter(t *testing.T) { - p := &promMetricRegistry{r: prom.NewRegistry()} + p := NewPromMetricRegistry(prom.NewRegistry(), url) p.Counter(metricId).Inc() text, err := p.Scrape() assert.Nil(t, err) @@ -47,7 +66,7 @@ func TestPromMetricRegistryCounter(t *testing.T) { } func TestPromMetricRegistryGauge(t *testing.T) { - p := &promMetricRegistry{r: prom.NewRegistry()} + p := NewPromMetricRegistry(prom.NewRegistry(), url) p.Gauge(metricId).Set(100) text, err := p.Scrape() assert.Nil(t, err) @@ -57,7 +76,7 @@ func TestPromMetricRegistryGauge(t *testing.T) { } func TestPromMetricRegistryHistogram(t *testing.T) { - p := &promMetricRegistry{r: prom.NewRegistry()} + p := NewPromMetricRegistry(prom.NewRegistry(), url) p.Histogram(metricId).Observe(100) text, err := p.Scrape() assert.Nil(t, err) @@ -68,7 +87,7 @@ func TestPromMetricRegistryHistogram(t *testing.T) { } func TestPromMetricRegistrySummary(t *testing.T) { - p := &promMetricRegistry{r: prom.NewRegistry()} + p := NewPromMetricRegistry(prom.NewRegistry(), url) p.Summary(metricId).Observe(100) text, err := p.Scrape() assert.Nil(t, err) @@ -78,7 +97,7 @@ func TestPromMetricRegistrySummary(t *testing.T) { } func TestPromMetricRegistryRt(t *testing.T) { - p := &promMetricRegistry{r: prom.NewRegistry()} + p := NewPromMetricRegistry(prom.NewRegistry(), url) for i := 0; i < 10; i++ { p.Rt(metricId, &metrics.RtOpts{}).Observe(10 * float64(i)) } @@ -90,7 +109,7 @@ func TestPromMetricRegistryRt(t *testing.T) { assert.Contains(t, text, "# HELP dubbo_request_min Min request\n# TYPE dubbo_request_min gauge\ndubbo_request_min{app=\"dubbo\",version=\"1.0.0\"} 0") assert.Contains(t, text, "# HELP dubbo_request_sum Sum request\n# TYPE dubbo_request_sum gauge\ndubbo_request_sum{app=\"dubbo\",version=\"1.0.0\"} 450") - p = &promMetricRegistry{r: prom.NewRegistry()} + p = NewPromMetricRegistry(prom.NewRegistry(), url) for i := 0; i < 10; i++ { p.Rt(metricId, &metrics.RtOpts{Aggregate: true, BucketNum: 10, TimeWindowSeconds: 60}).Observe(10 * float64(i)) } @@ -102,7 +121,7 @@ func TestPromMetricRegistryRt(t *testing.T) { } func TestPromMetricRegistryCounterConcurrent(t *testing.T) { - p := &promMetricRegistry{r: prom.NewRegistry()} + p := NewPromMetricRegistry(prom.NewRegistry(), url) var wg sync.WaitGroup for i := 0; i < 10; i++ { wg.Add(1) @@ -117,3 +136,57 @@ func TestPromMetricRegistryCounterConcurrent(t *testing.T) { assert.Contains(t, text, "# HELP dubbo_request request\n# TYPE dubbo_request counter") assert.Contains(t, text, `dubbo_request{app="dubbo",version="1.0.0"} 10`) } + +func TestPromMetricRegistryExport(t *testing.T) { + p := NewPromMetricRegistry(prom.NewRegistry(), url) + go func() { + for { + p.Rt(metricId, &metrics.RtOpts{}).Observe(10 * float64(1)) + time.Sleep(1 * time.Second) + } + }() + p.Export() + // test push + var wg sync.WaitGroup + wg.Add(1) + go func() { + err := http.ListenAndServe(url.GetParam(constant.PrometheusPushgatewayBaseUrlKey, ""), + http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + bodyBytes, err := io.ReadAll(r.Body) + assert.Nil(t, err) + text := string(bodyBytes) + assert.Contains(t, text, "dubbo_request_avg") + wg.Done() + })) + assert.Nil(t, err) + }() + timeout := url.GetParamByIntValue(constant.PrometheusPushgatewayPushIntervalKey, constant.PrometheusDefaultPushInterval) + if waitTimeout(&wg, time.Duration(timeout+1)*time.Second) { + assert.Fail(t, "wait pushgateway data timeout") + } + // test pull + resp, err := http.Get("http://localhost:" + + url.GetParam(constant.PrometheusExporterMetricsPortKey, constant.PrometheusDefaultMetricsPort) + + url.GetParam(constant.PrometheusExporterMetricsPathKey, constant.PrometheusDefaultMetricsPath), + ) + assert.Nil(t, err) + defer resp.Body.Close() + bodyBytes, err := io.ReadAll(resp.Body) + assert.Nil(t, err) + text := string(bodyBytes) + assert.Contains(t, text, "dubbo_request_avg") +} + +func waitTimeout(wg *sync.WaitGroup, timeout time.Duration) bool { + c := make(chan struct{}) + go func() { + defer close(c) + wg.Wait() + }() + select { + case <-c: + return false // completed normally + case <-time.After(timeout): + return true // timed out + } +} diff --git a/metrics/prometheus/reporter.go b/metrics/prometheus/reporter.go deleted file mode 100644 index a5e88eff28..0000000000 --- a/metrics/prometheus/reporter.go +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package prometheus - -import ( - "context" - "net/http" - "sync" -) - -import ( - "github.com/dubbogo/gost/log/logger" - - "github.com/prometheus/client_golang/prometheus/promhttp" -) - -import ( - "dubbo.apache.org/dubbo-go/v3/common/extension" - "dubbo.apache.org/dubbo-go/v3/metrics" -) - -var ( - reporterInstance *reporter - reporterInitOnce sync.Once -) - -const ( - reporterName = "prometheus" -) - -// should initialize after loading configuration -func init() { - // newPrometheusReporter() - extension.SetMetricReporter(reporterName, newPrometheusReporter) -} - -// reporter will export the metrics to Prometheus -// if you want to use this feature, you need to initialize your prometheus. -// https://prometheus.io/docs/guides/go-application/ -type reporter struct { - reporterServer *http.Server - reporterConfig *metrics.ReporterConfig - namespace string -} - -// newPrometheusReporter create a new prometheus server or push gateway reporter -func newPrometheusReporter(reporterConfig *metrics.ReporterConfig) metrics.Reporter { - if reporterInstance == nil { - reporterInitOnce.Do(func() { - reporterInstance = &reporter{ - reporterConfig: reporterConfig, - namespace: reporterConfig.Namespace, - } - }) - } - - if reporterConfig.Enable { - if reporterConfig.Mode == metrics.ReportModePull { - go reporterInstance.StartServer(reporterConfig) - } - // todo pushgateway support - } else { - reporterInstance.ShutdownServer() - } - - return reporterInstance -} - -func (r *reporter) StartServer(reporterConfig *metrics.ReporterConfig) { - // start server - mux := http.NewServeMux() - mux.Handle(reporterConfig.Path, promhttp.Handler()) - reporterInstance.reporterServer = &http.Server{Addr: ":" + reporterConfig.Port, Handler: mux} - logger.Infof("new prometheus reporter with port = %s, path = %s", reporterConfig.Port, reporterConfig.Path) - if err := reporterInstance.reporterServer.ListenAndServe(); err != nil { - logger.Warnf("new prometheus reporter with error = %s", err) - } -} - -func (r *reporter) ShutdownServer() { - if reporterInstance.reporterServer != nil { - err := reporterInstance.reporterServer.Shutdown(context.Background()) - if err != nil { - logger.Errorf("shutdown prometheus reporter with error = %s, prometheus reporter close now", err) - reporterInstance.reporterServer.Close() - } - } -} From 6de48b3cf317982228e9d63e92a2a4028907d7dc Mon Sep 17 00:00:00 2001 From: Eng Zer Jun Date: Mon, 4 Sep 2023 17:06:06 +0800 Subject: [PATCH 10/22] refactor(root_config): remove redundant nil check in `Init` (#2412) --- config/root_config.go | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/config/root_config.go b/config/root_config.go index e578464fe4..07e4b8f5d9 100644 --- a/config/root_config.go +++ b/config/root_config.go @@ -167,12 +167,9 @@ func (rc *RootConfig) Init() error { } // init registry - registries := rc.Registries - if registries != nil { - for _, reg := range registries { - if err := reg.Init(); err != nil { - return err - } + for _, reg := range rc.Registries { + if err := reg.Init(); err != nil { + return err } } From 4b9bbd8e8ceb55e43d48250d0734d930b0384842 Mon Sep 17 00:00:00 2001 From: Qin Date: Tue, 5 Sep 2023 11:55:32 +0800 Subject: [PATCH 11/22] fix: health.proto has name conflict with the one in google.golang.org/grpc (#2395) * fix: health.proto has name conflict with the one in google.golang.org/grpc health check in "dubbo.apache.org/dubbo-go/v3/protocol/dubbo3/health/triple_health_v1" conflicts with the one in "google.golang.org/grpc/health/grpc_health_v1". Fixes #2394 * update license --- .../health/triple_health_v1/health.pb.go | 169 +++++++++--------- .../health/triple_health_v1/health.proto | 2 +- .../triple_health_v1/health_triple.pb.go | 27 ++- 3 files changed, 93 insertions(+), 105 deletions(-) diff --git a/protocol/dubbo3/health/triple_health_v1/health.pb.go b/protocol/dubbo3/health/triple_health_v1/health.pb.go index e8bc5f970c..499740042e 100644 --- a/protocol/dubbo3/health/triple_health_v1/health.pb.go +++ b/protocol/dubbo3/health/triple_health_v1/health.pb.go @@ -20,21 +20,17 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.28.0 -// protoc v3.20.1 -// source: protocol/dubbo3/health/triple_health_v1/health.proto +// protoc-gen-go v1.30.0 +// protoc v3.21.12 +// source: health.proto package triple_health_v1 -import ( - reflect "reflect" - sync "sync" -) - import ( protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" ) const ( @@ -80,11 +76,11 @@ func (x HealthCheckResponse_ServingStatus) String() string { } func (HealthCheckResponse_ServingStatus) Descriptor() protoreflect.EnumDescriptor { - return file_protocol_dubbo3_health_triple_health_v1_health_proto_enumTypes[0].Descriptor() + return file_health_proto_enumTypes[0].Descriptor() } func (HealthCheckResponse_ServingStatus) Type() protoreflect.EnumType { - return &file_protocol_dubbo3_health_triple_health_v1_health_proto_enumTypes[0] + return &file_health_proto_enumTypes[0] } func (x HealthCheckResponse_ServingStatus) Number() protoreflect.EnumNumber { @@ -93,7 +89,7 @@ func (x HealthCheckResponse_ServingStatus) Number() protoreflect.EnumNumber { // Deprecated: Use HealthCheckResponse_ServingStatus.Descriptor instead. func (HealthCheckResponse_ServingStatus) EnumDescriptor() ([]byte, []int) { - return file_protocol_dubbo3_health_triple_health_v1_health_proto_rawDescGZIP(), []int{1, 0} + return file_health_proto_rawDescGZIP(), []int{1, 0} } type HealthCheckRequest struct { @@ -107,7 +103,7 @@ type HealthCheckRequest struct { func (x *HealthCheckRequest) Reset() { *x = HealthCheckRequest{} if protoimpl.UnsafeEnabled { - mi := &file_protocol_dubbo3_health_triple_health_v1_health_proto_msgTypes[0] + mi := &file_health_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -120,7 +116,7 @@ func (x *HealthCheckRequest) String() string { func (*HealthCheckRequest) ProtoMessage() {} func (x *HealthCheckRequest) ProtoReflect() protoreflect.Message { - mi := &file_protocol_dubbo3_health_triple_health_v1_health_proto_msgTypes[0] + mi := &file_health_proto_msgTypes[0] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -133,7 +129,7 @@ func (x *HealthCheckRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use HealthCheckRequest.ProtoReflect.Descriptor instead. func (*HealthCheckRequest) Descriptor() ([]byte, []int) { - return file_protocol_dubbo3_health_triple_health_v1_health_proto_rawDescGZIP(), []int{0} + return file_health_proto_rawDescGZIP(), []int{0} } func (x *HealthCheckRequest) GetService() string { @@ -148,13 +144,13 @@ type HealthCheckResponse struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Status HealthCheckResponse_ServingStatus `protobuf:"varint,1,opt,name=status,proto3,enum=grpc.health.v1.HealthCheckResponse_ServingStatus" json:"status,omitempty"` + Status HealthCheckResponse_ServingStatus `protobuf:"varint,1,opt,name=status,proto3,enum=dubbogo.health.v1.HealthCheckResponse_ServingStatus" json:"status,omitempty"` } func (x *HealthCheckResponse) Reset() { *x = HealthCheckResponse{} if protoimpl.UnsafeEnabled { - mi := &file_protocol_dubbo3_health_triple_health_v1_health_proto_msgTypes[1] + mi := &file_health_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -167,7 +163,7 @@ func (x *HealthCheckResponse) String() string { func (*HealthCheckResponse) ProtoMessage() {} func (x *HealthCheckResponse) ProtoReflect() protoreflect.Message { - mi := &file_protocol_dubbo3_health_triple_health_v1_health_proto_msgTypes[1] + mi := &file_health_proto_msgTypes[1] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -180,7 +176,7 @@ func (x *HealthCheckResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use HealthCheckResponse.ProtoReflect.Descriptor instead. func (*HealthCheckResponse) Descriptor() ([]byte, []int) { - return file_protocol_dubbo3_health_triple_health_v1_health_proto_rawDescGZIP(), []int{1} + return file_health_proto_rawDescGZIP(), []int{1} } func (x *HealthCheckResponse) GetStatus() HealthCheckResponse_ServingStatus { @@ -190,70 +186,69 @@ func (x *HealthCheckResponse) GetStatus() HealthCheckResponse_ServingStatus { return HealthCheckResponse_UNKNOWN } -var File_protocol_dubbo3_health_triple_health_v1_health_proto protoreflect.FileDescriptor - -var file_protocol_dubbo3_health_triple_health_v1_health_proto_rawDesc = []byte{ - 0x0a, 0x34, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2f, 0x64, 0x75, 0x62, 0x62, 0x6f, - 0x33, 0x2f, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x2f, 0x74, 0x72, 0x69, 0x70, 0x6c, 0x65, 0x5f, - 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x5f, 0x76, 0x31, 0x2f, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x68, 0x65, 0x61, - 0x6c, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x22, 0x2e, 0x0a, 0x12, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, - 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, - 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, - 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x22, 0xb1, 0x01, 0x0a, 0x13, 0x48, 0x65, 0x61, 0x6c, 0x74, - 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x49, - 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x31, - 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, +var File_health_proto protoreflect.FileDescriptor + +var file_health_proto_rawDesc = []byte{ + 0x0a, 0x0c, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x11, + 0x64, 0x75, 0x62, 0x62, 0x6f, 0x67, 0x6f, 0x2e, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x2e, 0x76, + 0x31, 0x22, 0x2e, 0x0a, 0x12, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x22, 0xb4, 0x01, 0x0a, 0x13, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, + 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4c, 0x0a, 0x06, 0x73, 0x74, 0x61, + 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x34, 0x2e, 0x64, 0x75, 0x62, 0x62, + 0x6f, 0x67, 0x6f, 0x2e, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x48, 0x65, + 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, + 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x4f, 0x0a, 0x0d, 0x53, 0x65, 0x72, 0x76, 0x69, + 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, + 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x53, 0x45, 0x52, 0x56, 0x49, 0x4e, 0x47, + 0x10, 0x01, 0x12, 0x0f, 0x0a, 0x0b, 0x4e, 0x4f, 0x54, 0x5f, 0x53, 0x45, 0x52, 0x56, 0x49, 0x4e, + 0x47, 0x10, 0x02, 0x12, 0x13, 0x0a, 0x0f, 0x53, 0x45, 0x52, 0x56, 0x49, 0x43, 0x45, 0x5f, 0x55, + 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x03, 0x32, 0xba, 0x01, 0x0a, 0x06, 0x48, 0x65, 0x61, + 0x6c, 0x74, 0x68, 0x12, 0x56, 0x0a, 0x05, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x12, 0x25, 0x2e, 0x64, + 0x75, 0x62, 0x62, 0x6f, 0x67, 0x6f, 0x2e, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x2e, 0x76, 0x31, + 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x64, 0x75, 0x62, 0x62, 0x6f, 0x67, 0x6f, 0x2e, 0x68, 0x65, + 0x61, 0x6c, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, + 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x58, 0x0a, 0x05, 0x57, + 0x61, 0x74, 0x63, 0x68, 0x12, 0x25, 0x2e, 0x64, 0x75, 0x62, 0x62, 0x6f, 0x67, 0x6f, 0x2e, 0x68, + 0x65, 0x61, 0x6c, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, + 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x64, 0x75, + 0x62, 0x62, 0x6f, 0x67, 0x6f, 0x2e, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, 0x75, - 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x4f, 0x0a, 0x0d, 0x53, 0x65, 0x72, - 0x76, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, - 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x53, 0x45, 0x52, 0x56, 0x49, - 0x4e, 0x47, 0x10, 0x01, 0x12, 0x0f, 0x0a, 0x0b, 0x4e, 0x4f, 0x54, 0x5f, 0x53, 0x45, 0x52, 0x56, - 0x49, 0x4e, 0x47, 0x10, 0x02, 0x12, 0x13, 0x0a, 0x0f, 0x53, 0x45, 0x52, 0x56, 0x49, 0x43, 0x45, - 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x03, 0x32, 0xae, 0x01, 0x0a, 0x06, 0x48, - 0x65, 0x61, 0x6c, 0x74, 0x68, 0x12, 0x50, 0x0a, 0x05, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x12, 0x22, - 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, - 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, - 0x2e, 0x76, 0x31, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x52, 0x0a, 0x05, 0x57, 0x61, 0x74, 0x63, 0x68, - 0x12, 0x22, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x2e, 0x76, - 0x31, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x68, 0x65, 0x61, 0x6c, - 0x74, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, - 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x42, 0x34, 0x5a, 0x32, 0x67, - 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x64, 0x75, 0x62, 0x62, 0x6f, 0x67, - 0x6f, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2d, 0x67, 0x6f, 0x2f, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, - 0x2f, 0x74, 0x72, 0x69, 0x70, 0x6c, 0x65, 0x5f, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x5f, 0x76, - 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x6e, 0x73, 0x65, 0x30, 0x01, 0x42, 0x34, 0x5a, 0x32, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, + 0x63, 0x6f, 0x6d, 0x2f, 0x64, 0x75, 0x62, 0x62, 0x6f, 0x67, 0x6f, 0x2f, 0x67, 0x72, 0x70, 0x63, + 0x2d, 0x67, 0x6f, 0x2f, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x2f, 0x74, 0x72, 0x69, 0x70, 0x6c, + 0x65, 0x5f, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x5f, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x33, } var ( - file_protocol_dubbo3_health_triple_health_v1_health_proto_rawDescOnce sync.Once - file_protocol_dubbo3_health_triple_health_v1_health_proto_rawDescData = file_protocol_dubbo3_health_triple_health_v1_health_proto_rawDesc + file_health_proto_rawDescOnce sync.Once + file_health_proto_rawDescData = file_health_proto_rawDesc ) -func file_protocol_dubbo3_health_triple_health_v1_health_proto_rawDescGZIP() []byte { - file_protocol_dubbo3_health_triple_health_v1_health_proto_rawDescOnce.Do(func() { - file_protocol_dubbo3_health_triple_health_v1_health_proto_rawDescData = protoimpl.X.CompressGZIP(file_protocol_dubbo3_health_triple_health_v1_health_proto_rawDescData) +func file_health_proto_rawDescGZIP() []byte { + file_health_proto_rawDescOnce.Do(func() { + file_health_proto_rawDescData = protoimpl.X.CompressGZIP(file_health_proto_rawDescData) }) - return file_protocol_dubbo3_health_triple_health_v1_health_proto_rawDescData + return file_health_proto_rawDescData } -var file_protocol_dubbo3_health_triple_health_v1_health_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_protocol_dubbo3_health_triple_health_v1_health_proto_msgTypes = make([]protoimpl.MessageInfo, 2) -var file_protocol_dubbo3_health_triple_health_v1_health_proto_goTypes = []interface{}{ - (HealthCheckResponse_ServingStatus)(0), // 0: grpc.health.v1.HealthCheckResponse.ServingStatus - (*HealthCheckRequest)(nil), // 1: grpc.health.v1.HealthCheckRequest - (*HealthCheckResponse)(nil), // 2: grpc.health.v1.HealthCheckResponse +var file_health_proto_enumTypes = make([]protoimpl.EnumInfo, 1) +var file_health_proto_msgTypes = make([]protoimpl.MessageInfo, 2) +var file_health_proto_goTypes = []interface{}{ + (HealthCheckResponse_ServingStatus)(0), // 0: dubbogo.health.v1.HealthCheckResponse.ServingStatus + (*HealthCheckRequest)(nil), // 1: dubbogo.health.v1.HealthCheckRequest + (*HealthCheckResponse)(nil), // 2: dubbogo.health.v1.HealthCheckResponse } -var file_protocol_dubbo3_health_triple_health_v1_health_proto_depIdxs = []int32{ - 0, // 0: grpc.health.v1.HealthCheckResponse.status:type_name -> grpc.health.v1.HealthCheckResponse.ServingStatus - 1, // 1: grpc.health.v1.Health.Check:input_type -> grpc.health.v1.HealthCheckRequest - 1, // 2: grpc.health.v1.Health.Watch:input_type -> grpc.health.v1.HealthCheckRequest - 2, // 3: grpc.health.v1.Health.Check:output_type -> grpc.health.v1.HealthCheckResponse - 2, // 4: grpc.health.v1.Health.Watch:output_type -> grpc.health.v1.HealthCheckResponse +var file_health_proto_depIdxs = []int32{ + 0, // 0: dubbogo.health.v1.HealthCheckResponse.status:type_name -> dubbogo.health.v1.HealthCheckResponse.ServingStatus + 1, // 1: dubbogo.health.v1.Health.Check:input_type -> dubbogo.health.v1.HealthCheckRequest + 1, // 2: dubbogo.health.v1.Health.Watch:input_type -> dubbogo.health.v1.HealthCheckRequest + 2, // 3: dubbogo.health.v1.Health.Check:output_type -> dubbogo.health.v1.HealthCheckResponse + 2, // 4: dubbogo.health.v1.Health.Watch:output_type -> dubbogo.health.v1.HealthCheckResponse 3, // [3:5] is the sub-list for method output_type 1, // [1:3] is the sub-list for method input_type 1, // [1:1] is the sub-list for extension type_name @@ -261,13 +256,13 @@ var file_protocol_dubbo3_health_triple_health_v1_health_proto_depIdxs = []int32{ 0, // [0:1] is the sub-list for field type_name } -func init() { file_protocol_dubbo3_health_triple_health_v1_health_proto_init() } -func file_protocol_dubbo3_health_triple_health_v1_health_proto_init() { - if File_protocol_dubbo3_health_triple_health_v1_health_proto != nil { +func init() { file_health_proto_init() } +func file_health_proto_init() { + if File_health_proto != nil { return } if !protoimpl.UnsafeEnabled { - file_protocol_dubbo3_health_triple_health_v1_health_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + file_health_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*HealthCheckRequest); i { case 0: return &v.state @@ -279,7 +274,7 @@ func file_protocol_dubbo3_health_triple_health_v1_health_proto_init() { return nil } } - file_protocol_dubbo3_health_triple_health_v1_health_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + file_health_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*HealthCheckResponse); i { case 0: return &v.state @@ -296,19 +291,19 @@ func file_protocol_dubbo3_health_triple_health_v1_health_proto_init() { out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_protocol_dubbo3_health_triple_health_v1_health_proto_rawDesc, + RawDescriptor: file_health_proto_rawDesc, NumEnums: 1, NumMessages: 2, NumExtensions: 0, NumServices: 1, }, - GoTypes: file_protocol_dubbo3_health_triple_health_v1_health_proto_goTypes, - DependencyIndexes: file_protocol_dubbo3_health_triple_health_v1_health_proto_depIdxs, - EnumInfos: file_protocol_dubbo3_health_triple_health_v1_health_proto_enumTypes, - MessageInfos: file_protocol_dubbo3_health_triple_health_v1_health_proto_msgTypes, + GoTypes: file_health_proto_goTypes, + DependencyIndexes: file_health_proto_depIdxs, + EnumInfos: file_health_proto_enumTypes, + MessageInfos: file_health_proto_msgTypes, }.Build() - File_protocol_dubbo3_health_triple_health_v1_health_proto = out.File - file_protocol_dubbo3_health_triple_health_v1_health_proto_rawDesc = nil - file_protocol_dubbo3_health_triple_health_v1_health_proto_goTypes = nil - file_protocol_dubbo3_health_triple_health_v1_health_proto_depIdxs = nil + File_health_proto = out.File + file_health_proto_rawDesc = nil + file_health_proto_goTypes = nil + file_health_proto_depIdxs = nil } diff --git a/protocol/dubbo3/health/triple_health_v1/health.proto b/protocol/dubbo3/health/triple_health_v1/health.proto index ae55348388..b636b80f96 100644 --- a/protocol/dubbo3/health/triple_health_v1/health.proto +++ b/protocol/dubbo3/health/triple_health_v1/health.proto @@ -20,7 +20,7 @@ syntax = "proto3"; -package grpc.health.v1; +package dubbogo.health.v1; option go_package = "github.com/dubbogo/grpc-go/health/triple_health_v1"; diff --git a/protocol/dubbo3/health/triple_health_v1/health_triple.pb.go b/protocol/dubbo3/health/triple_health_v1/health_triple.pb.go index a63d394d57..00633ccfa7 100644 --- a/protocol/dubbo3/health/triple_health_v1/health_triple.pb.go +++ b/protocol/dubbo3/health/triple_health_v1/health_triple.pb.go @@ -18,34 +18,27 @@ // Code generated by protoc-gen-go-triple. DO NOT EDIT. // versions: // - protoc-gen-go-triple v1.0.8 -// - protoc v3.20.1 -// source: protocol/dubbo3/health/triple_health_v1/health.proto +// - protoc v3.21.12 +// source: health.proto package triple_health_v1 import ( context "context" + constant1 "dubbo.apache.org/dubbo-go/v3/common/constant" + protocol "dubbo.apache.org/dubbo-go/v3/protocol" + dubbo3 "dubbo.apache.org/dubbo-go/v3/protocol/dubbo3" + invocation "dubbo.apache.org/dubbo-go/v3/protocol/invocation" fmt "fmt" -) - -import ( grpc_go "github.com/dubbogo/grpc-go" codes "github.com/dubbogo/grpc-go/codes" metadata "github.com/dubbogo/grpc-go/metadata" status "github.com/dubbogo/grpc-go/status" - common "github.com/dubbogo/triple/pkg/common" constant "github.com/dubbogo/triple/pkg/common/constant" triple "github.com/dubbogo/triple/pkg/triple" ) -import ( - constant1 "dubbo.apache.org/dubbo-go/v3/common/constant" - protocol "dubbo.apache.org/dubbo-go/v3/protocol" - dubbo3 "dubbo.apache.org/dubbo-go/v3/protocol/dubbo3" - invocation "dubbo.apache.org/dubbo-go/v3/protocol/invocation" -) - // This is a compile-time assertion to ensure that this generated file // is compatible with the grpc package it is being compiled against. const _ = grpc_go.SupportPackageIsVersion7 @@ -89,7 +82,7 @@ func (c *HealthClientImpl) GetDubboStub(cc *triple.TripleConn) HealthClient { } func (c *HealthClientImpl) XXX_InterfaceName() string { - return "grpc.health.v1.Health" + return "dubbogo.health.v1.Health" } func NewHealthClient(cc *triple.TripleConn) HealthClient { @@ -184,7 +177,7 @@ func (s *UnimplementedHealthServer) XXX_ServiceDesc() *grpc_go.ServiceDesc { return &Health_ServiceDesc } func (s *UnimplementedHealthServer) XXX_InterfaceName() string { - return "grpc.health.v1.Health" + return "dubbogo.health.v1.Health" } func (UnimplementedHealthServer) mustEmbedUnimplementedHealthServer() {} @@ -267,7 +260,7 @@ func (x *healthWatchServer) Send(m *HealthCheckResponse) error { // It's only intended for direct use with grpc_go.RegisterService, // and not to be introspected or modified (even as a copy) var Health_ServiceDesc = grpc_go.ServiceDesc{ - ServiceName: "grpc.health.v1.Health", + ServiceName: "dubbogo.health.v1.Health", HandlerType: (*HealthServer)(nil), Methods: []grpc_go.MethodDesc{ { @@ -282,5 +275,5 @@ var Health_ServiceDesc = grpc_go.ServiceDesc{ ServerStreams: true, }, }, - Metadata: "protocol/dubbo3/health/triple_health_v1/health.proto", + Metadata: "health.proto", } From d10057a531f996a4dc5178d6e08d43070a5861f5 Mon Sep 17 00:00:00 2001 From: finalt Date: Wed, 13 Sep 2023 16:36:07 +0800 Subject: [PATCH 12/22] Improve cache init time and add application name (#2420) --- common/constant/key.go | 2 +- .../service_instances_changed_listener_impl.go | 13 ++++++++++--- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/common/constant/key.go b/common/constant/key.go index f200528785..4d0b0a8a32 100644 --- a/common/constant/key.go +++ b/common/constant/key.go @@ -422,6 +422,6 @@ const ( // default meta cache config const ( DefaultMetaCacheName = "dubbo.meta" - DefaultMetaFileName = "dubbo.metadata" + DefaultMetaFileName = "dubbo.metadata." DefaultEntrySize = 100 ) diff --git a/registry/servicediscovery/service_instances_changed_listener_impl.go b/registry/servicediscovery/service_instances_changed_listener_impl.go index 8bd4ac8732..252c979901 100644 --- a/registry/servicediscovery/service_instances_changed_listener_impl.go +++ b/registry/servicediscovery/service_instances_changed_listener_impl.go @@ -18,7 +18,9 @@ package servicediscovery import ( + "encoding/gob" "reflect" + "sync" "time" ) @@ -32,6 +34,7 @@ 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/config" "dubbo.apache.org/dubbo-go/v3/registry" "dubbo.apache.org/dubbo-go/v3/registry/servicediscovery/store" "dubbo.apache.org/dubbo-go/v3/remoting" @@ -39,10 +42,13 @@ import ( var ( metaCache *store.CacheManager + one sync.Once ) -func init() { - cache, err := store.NewCacheManager(constant.DefaultMetaCacheName, constant.DefaultMetaFileName, time.Minute*10, constant.DefaultEntrySize, true) +func initCache() { + gob.Register(&common.MetadataInfo{}) + fileName := constant.DefaultMetaFileName + config.GetApplicationConfig().Name + cache, err := store.NewCacheManager(constant.DefaultMetaCacheName, fileName, time.Minute*10, constant.DefaultEntrySize, true) if err != nil { logger.Fatal("Failed to create cache [%s],the err is %v", constant.DefaultMetaCacheName, err) } @@ -59,6 +65,7 @@ type ServiceInstancesChangedListenerImpl struct { } func NewServiceInstancesChangedListener(services *gxset.HashSet) registry.ServiceInstancesChangedListener { + one.Do(initCache) return &ServiceInstancesChangedListenerImpl{ serviceNames: services, listeners: make(map[string]registry.NotifyListener), @@ -209,7 +216,7 @@ func (lstn *ServiceInstancesChangedListenerImpl) GetEventType() reflect.Type { // GetMetadataInfo get metadata info when MetadataStorageTypePropertyName is null func GetMetadataInfo(instance registry.ServiceInstance, revision string) (*common.MetadataInfo, error) { - + one.Do(initCache) if metadataInfo, ok := metaCache.Get(revision); ok { return metadataInfo.(*common.MetadataInfo), nil } From 5ac057d3ca6c3c0ea1fa355c6dcdf64a0813c6b9 Mon Sep 17 00:00:00 2001 From: finalt Date: Wed, 13 Sep 2023 20:21:07 +0800 Subject: [PATCH 13/22] Followup of #2420, rename variable 'one' to 'cacheOnce' (#2423) --- .../service_instances_changed_listener_impl.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/registry/servicediscovery/service_instances_changed_listener_impl.go b/registry/servicediscovery/service_instances_changed_listener_impl.go index 252c979901..de2667bae2 100644 --- a/registry/servicediscovery/service_instances_changed_listener_impl.go +++ b/registry/servicediscovery/service_instances_changed_listener_impl.go @@ -42,7 +42,7 @@ import ( var ( metaCache *store.CacheManager - one sync.Once + cacheOnce sync.Once ) func initCache() { @@ -65,7 +65,7 @@ type ServiceInstancesChangedListenerImpl struct { } func NewServiceInstancesChangedListener(services *gxset.HashSet) registry.ServiceInstancesChangedListener { - one.Do(initCache) + cacheOnce.Do(initCache) return &ServiceInstancesChangedListenerImpl{ serviceNames: services, listeners: make(map[string]registry.NotifyListener), @@ -216,7 +216,7 @@ func (lstn *ServiceInstancesChangedListenerImpl) GetEventType() reflect.Type { // GetMetadataInfo get metadata info when MetadataStorageTypePropertyName is null func GetMetadataInfo(instance registry.ServiceInstance, revision string) (*common.MetadataInfo, error) { - one.Do(initCache) + cacheOnce.Do(initCache) if metadataInfo, ok := metaCache.Get(revision); ok { return metadataInfo.(*common.MetadataInfo), nil } From debe37d0a160f761d903d051f8f227f7a95f7415 Mon Sep 17 00:00:00 2001 From: maguowei Date: Mon, 9 Oct 2023 14:28:55 +0800 Subject: [PATCH 14/22] fix config random port, followup of #2384 --- config/service_config.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/service_config.go b/config/service_config.go index 1b0038ed06..073ad8e6d4 100644 --- a/config/service_config.go +++ b/config/service_config.go @@ -271,7 +271,7 @@ func (s *ServiceConfig) Export() error { } port := proto.Port - if len(proto.Port) == 0 { + if num, err := strconv.Atoi(proto.Port); err != nil || num <= 0 { port = nextPort.Value.(string) nextPort = nextPort.Next() } From 3764ba48ad337994ddafb41fae40b82c263ad47c Mon Sep 17 00:00:00 2001 From: Scout Wang <33331974+DMwangnima@users.noreply.github.com> Date: Wed, 11 Oct 2023 16:09:43 +0800 Subject: [PATCH 15/22] fixes #2439, resolve ConsumerConfig nil pointer problem (#2440) --- config/reference_config.go | 35 +++++++++++++++++---------------- config/reference_config_test.go | 7 +++++++ 2 files changed, 25 insertions(+), 17 deletions(-) diff --git a/config/reference_config.go b/config/reference_config.go index 64d7c53a3d..e38372ec98 100644 --- a/config/reference_config.go +++ b/config/reference_config.go @@ -101,30 +101,31 @@ func (rc *ReferenceConfig) Init(root *RootConfig) error { rc.Version = root.Application.Version } } - if rc.Filter == "" { - rc.Filter = root.Consumer.Filter + rc.RegistryIDs = translateIds(rc.RegistryIDs) + if root.Consumer != nil { + if rc.Filter == "" { + rc.Filter = root.Consumer.Filter + } + if len(rc.RegistryIDs) <= 0 { + rc.RegistryIDs = root.Consumer.RegistryIDs + } + if rc.Protocol == "" { + rc.Protocol = root.Consumer.Protocol + } + if rc.TracingKey == "" { + rc.TracingKey = root.Consumer.TracingKey + } + if rc.Check == nil { + rc.Check = &root.Consumer.Check + } } if rc.Cluster == "" { rc.Cluster = "failover" } - rc.RegistryIDs = translateIds(rc.RegistryIDs) - if len(rc.RegistryIDs) <= 0 { - rc.RegistryIDs = root.Consumer.RegistryIDs - } - - if rc.Protocol == "" { - rc.Protocol = root.Consumer.Protocol - } - - if rc.TracingKey == "" { - rc.TracingKey = root.Consumer.TracingKey - } if root.Metric.Enable != nil { rc.metricsEnable = *root.Metric.Enable } - if rc.Check == nil { - rc.Check = &root.Consumer.Check - } + return verify(rc) } diff --git a/config/reference_config_test.go b/config/reference_config_test.go index 8e0d1e37fc..13a5ed23de 100644 --- a/config/reference_config_test.go +++ b/config/reference_config_test.go @@ -460,3 +460,10 @@ func TestNewReferenceConfigBuilder(t *testing.T) { invoker := config.GetInvoker() assert.Nil(t, invoker) } + +func TestReferenceConfigInitWithoutConsumerConfig(t *testing.T) { + testRootConfig := NewRootConfigBuilder().Build() + testRootConfig.Consumer = nil + err := NewReferenceConfigBuilder().Build().Init(testRootConfig) + assert.Nil(t, err) +} From 8b041402f7d7cebb82effc0f6213f3f19f17c9ed Mon Sep 17 00:00:00 2001 From: huangjikun <72253502+xiaomiusa87@users.noreply.github.com> Date: Thu, 12 Oct 2023 10:31:36 +0800 Subject: [PATCH 16/22] Fixes #2428, zk registry support customize 'rootPath' (#2437) --- registry/zookeeper/service_discovery.go | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/registry/zookeeper/service_discovery.go b/registry/zookeeper/service_discovery.go index 5a5d7be0c1..915f10b2bb 100644 --- a/registry/zookeeper/service_discovery.go +++ b/registry/zookeeper/service_discovery.go @@ -64,9 +64,14 @@ type zookeeperServiceDiscovery struct { // newZookeeperServiceDiscovery the constructor of newZookeeperServiceDiscovery func newZookeeperServiceDiscovery(url *common.URL) (registry.ServiceDiscovery, error) { + group := url.GetParam(constant.RegistryGroupKey, rootPath) + if !strings.HasPrefix(group, constant.PathSeparator) { + group = constant.PathSeparator + group + } + zksd := &zookeeperServiceDiscovery{ url: url, - rootPath: rootPath, + rootPath: group, instanceListenerMap: make(map[string]*gxset.HashSet), } if err := zookeeper.ValidateZookeeperClient(zksd, url.Location); err != nil { @@ -74,7 +79,7 @@ func newZookeeperServiceDiscovery(url *common.URL) (registry.ServiceDiscovery, e } zksd.WaitGroup().Add(1) // zk client start successful, then wg +1 go zookeeper.HandleClientRestart(zksd) - zksd.csd = curator_discovery.NewServiceDiscovery(zksd.client, rootPath) + zksd.csd = curator_discovery.NewServiceDiscovery(zksd.client, group) return zksd, nil } From 40dd198515bfcf7d50b5fdb08fe138f1e2957754 Mon Sep 17 00:00:00 2001 From: foghost Date: Tue, 24 Oct 2023 11:30:02 +0800 Subject: [PATCH 17/22] add switch for metric collector (#2424) --- common/constant/key.go | 4 ++ config/metric_config.go | 44 +++++++++++--- config/metric_config_test.go | 18 ++++-- metrics/config_center/collector.go | 8 ++- metrics/metadata/collector.go | 8 ++- metrics/prometheus/registry.go | 94 ++++++++++++++++-------------- metrics/registry/collector.go | 8 ++- metrics/rpc/collector.go | 12 ++-- 8 files changed, 125 insertions(+), 71 deletions(-) diff --git a/common/constant/key.go b/common/constant/key.go index 4d0b0a8a32..c85384d439 100644 --- a/common/constant/key.go +++ b/common/constant/key.go @@ -404,6 +404,10 @@ const ( // metrics key const ( + MetadataEnabledKey = "metrics.metadata.enabled" + RegistryEnabledKey = "metrics.registry.enabled" + ConfigCenterEnabledKey = "metrics.config-center.enabled" + RpcEnabledKey = "metrics.rpc.enabled" AggregationEnabledKey = "aggregation.enabled" AggregationBucketNumKey = "aggregation.bucket.num" AggregationTimeWindowSecondsKey = "aggregation.time.window.seconds" diff --git a/config/metric_config.go b/config/metric_config.go index 0859b57ccd..af41eb8532 100644 --- a/config/metric_config.go +++ b/config/metric_config.go @@ -35,13 +35,17 @@ import ( // MetricConfig This is the config struct for all metrics implementation type MetricConfig struct { - Enable *bool `default:"false" yaml:"enable" json:"enable,omitempty" property:"enable"` - Port string `default:"9090" yaml:"port" json:"port,omitempty" property:"port"` - Path string `default:"/metrics" yaml:"path" json:"path,omitempty" property:"path"` - Protocol string `default:"prometheus" yaml:"protocol" json:"protocol,omitempty" property:"protocol"` - Prometheus *PrometheusConfig `yaml:"prometheus" json:"prometheus" property:"prometheus"` - Aggregation *AggregateConfig `yaml:"aggregation" json:"aggregation" property:"aggregation"` - rootConfig *RootConfig + Enable *bool `default:"false" yaml:"enable" json:"enable,omitempty" property:"enable"` + Port string `default:"9090" yaml:"port" json:"port,omitempty" property:"port"` + Path string `default:"/metrics" yaml:"path" json:"path,omitempty" property:"path"` + Protocol string `default:"prometheus" yaml:"protocol" json:"protocol,omitempty" property:"protocol"` + EnableMetadata *bool `default:"true" yaml:"enable-metadata" json:"enable-metadata,omitempty" property:"enable-metadata"` + EnableRegistry *bool `default:"true" yaml:"enable-registry" json:"enable-registry,omitempty" property:"enable-registry"` + EnableConfigCenter *bool `default:"true" yaml:"enable-config-center" json:"enable-config-center,omitempty" property:"enable-config-center"` + EnableRpc *bool `default:"true" yaml:"enable-rpc" json:"enable-rpc,omitempty" property:"enable-rpc"` + Prometheus *PrometheusConfig `yaml:"prometheus" json:"prometheus" property:"prometheus"` + Aggregation *AggregateConfig `yaml:"aggregation" json:"aggregation" property:"aggregation"` + rootConfig *RootConfig } type AggregateConfig struct { @@ -101,6 +105,26 @@ func NewMetricConfigBuilder() *MetricConfigBuilder { return &MetricConfigBuilder{metricConfig: &MetricConfig{}} } +func (mcb *MetricConfigBuilder) SetMetadataEnabled(enabled bool) *MetricConfigBuilder { + mcb.metricConfig.EnableMetadata = &enabled + return mcb +} + +func (mcb *MetricConfigBuilder) SetRegistryEnabled(enabled bool) *MetricConfigBuilder { + mcb.metricConfig.EnableRegistry = &enabled + return mcb +} + +func (mcb *MetricConfigBuilder) SetConfigCenterEnabled(enabled bool) *MetricConfigBuilder { + mcb.metricConfig.EnableConfigCenter = &enabled + return mcb +} + +func (mcb *MetricConfigBuilder) SetRpcEnabled(enabled bool) *MetricConfigBuilder { + mcb.metricConfig.EnableRpc = &enabled + return mcb +} + func (mcb *MetricConfigBuilder) Build() *MetricConfig { return mcb.metricConfig } @@ -113,11 +137,15 @@ func (mc *MetricConfig) DynamicUpdateProperties(newMetricConfig *MetricConfig) { // prometheus://localhost:9090?&histogram.enabled=false&prometheus.exporter.enabled=false func (mc *MetricConfig) toURL() *common.URL { url, _ := common.NewURL("localhost", common.WithProtocol(mc.Protocol)) - url.SetParam(constant.PrometheusExporterEnabledKey, strconv.FormatBool(*mc.Enable)) + url.SetParam(constant.PrometheusExporterEnabledKey, strconv.FormatBool(*mc.Enable)) // for compatibility url.SetParam(constant.PrometheusExporterMetricsPortKey, mc.Port) url.SetParam(constant.PrometheusExporterMetricsPathKey, mc.Path) url.SetParam(constant.ApplicationKey, mc.rootConfig.Application.Name) url.SetParam(constant.AppVersionKey, mc.rootConfig.Application.Version) + url.SetParam(constant.MetadataEnabledKey, strconv.FormatBool(*mc.EnableMetadata)) + url.SetParam(constant.RegistryEnabledKey, strconv.FormatBool(*mc.EnableRegistry)) + url.SetParam(constant.ConfigCenterEnabledKey, strconv.FormatBool(*mc.EnableConfigCenter)) + url.SetParam(constant.RpcEnabledKey, strconv.FormatBool(*mc.EnableRpc)) if mc.Aggregation != nil { url.SetParam(constant.AggregationEnabledKey, strconv.FormatBool(*mc.Aggregation.Enabled)) url.SetParam(constant.AggregationBucketNumKey, strconv.Itoa(mc.Aggregation.BucketNum)) diff --git a/config/metric_config_test.go b/config/metric_config_test.go index 70dce11b1e..31a0ac6b7b 100644 --- a/config/metric_config_test.go +++ b/config/metric_config_test.go @@ -26,9 +26,17 @@ import ( ) func TestMetricConfigBuilder(t *testing.T) { - config := NewMetricConfigBuilder().Build() - err := config.Init(&RootConfig{Application: &ApplicationConfig{Name: "dubbo", Version: "1.0.0"}}) - assert.NoError(t, err) - reporterConfig := config.ToReporterConfig() - assert.Equal(t, string(reporterConfig.Mode), "pull") + config := NewMetricConfigBuilder(). + SetConfigCenterEnabled(false). + SetMetadataEnabled(false). + SetRegistryEnabled(false). + SetRpcEnabled(false). + Build() + enable := false + assert.Equal(t, &MetricConfig{ + EnableConfigCenter: &enable, + EnableMetadata: &enable, + EnableRegistry: &enable, + EnableRpc: &enable, + }, config) } diff --git a/metrics/config_center/collector.go b/metrics/config_center/collector.go index 9ae551f0e5..3b4bb1e498 100644 --- a/metrics/config_center/collector.go +++ b/metrics/config_center/collector.go @@ -30,9 +30,11 @@ var ch = make(chan metrics.MetricsEvent, 10) var info = metrics.NewMetricKey("dubbo_configcenter_total", "Config Changed Total") func init() { - metrics.AddCollector("config_center", func(mr metrics.MetricRegistry, _ *common.URL) { - c := &configCenterCollector{r: mr} - c.start() + metrics.AddCollector("config_center", func(mr metrics.MetricRegistry, url *common.URL) { + if url.GetParamBool(constant.ConfigCenterEnabledKey, true) { + c := &configCenterCollector{r: mr} + c.start() + } }) } diff --git a/metrics/metadata/collector.go b/metrics/metadata/collector.go index 7125fb1f14..8a08e0ff47 100644 --- a/metrics/metadata/collector.go +++ b/metrics/metadata/collector.go @@ -32,9 +32,11 @@ const eventType = constant.MetricsMetadata var ch = make(chan metrics.MetricsEvent, 10) func init() { - metrics.AddCollector("metadata", func(mr metrics.MetricRegistry, _ *common.URL) { - l := &MetadataMetricCollector{metrics.BaseCollector{R: mr}} - l.start() + metrics.AddCollector("metadata", func(mr metrics.MetricRegistry, url *common.URL) { + if url.GetParamBool(constant.MetadataEnabledKey, true) { + l := &MetadataMetricCollector{metrics.BaseCollector{R: mr}} + l.start() + } }) } diff --git a/metrics/prometheus/registry.go b/metrics/prometheus/registry.go index f84f2ad552..d108f8f9f6 100644 --- a/metrics/prometheus/registry.go +++ b/metrics/prometheus/registry.go @@ -143,56 +143,62 @@ func (p *promMetricRegistry) Rt(m *metrics.MetricId, opts *metrics.RtOpts) metri func (p *promMetricRegistry) Export() { if p.url.GetParamBool(constant.PrometheusExporterEnabledKey, false) { - go func() { - mux := http.NewServeMux() - path := p.url.GetParam(constant.PrometheusDefaultMetricsPath, constant.PrometheusDefaultMetricsPath) - port := p.url.GetParam(constant.PrometheusExporterMetricsPortKey, constant.PrometheusDefaultMetricsPort) - mux.Handle(path, promhttp.InstrumentMetricHandler(p.r, promhttp.HandlerFor(p.gather, promhttp.HandlerOpts{}))) - srv := &http.Server{Addr: ":" + port, Handler: mux} - extension.AddCustomShutdownCallback(func() { - ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) - defer cancel() - if err := srv.Shutdown(ctx); nil != err { - logger.Fatalf("prometheus server shutdown failed, err: %v", err) - } else { - logger.Info("prometheus server gracefully shutdown success") - } - }) - logger.Infof("prometheus endpoint :%s%s", port, path) - if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed { // except Shutdown or Close - logger.Errorf("new prometheus server with error = %v", err) - } - }() + go p.exportHttp() } if p.url.GetParamBool(constant.PrometheusPushgatewayEnabledKey, false) { - baseUrl, exist := p.url.GetNonDefaultParam(constant.PrometheusPushgatewayBaseUrlKey) - if !exist { - logger.Error("no pushgateway url found in config path: metrics.prometheus.pushgateway.bash-url, please check your config file") - return - } - username := p.url.GetParam(constant.PrometheusPushgatewayBaseUrlKey, "") - password := p.url.GetParam(constant.PrometheusPushgatewayBaseUrlKey, "") - job := p.url.GetParam(constant.PrometheusPushgatewayJobKey, constant.PrometheusDefaultJobName) - pushInterval := p.url.GetParamByIntValue(constant.PrometheusPushgatewayPushIntervalKey, constant.PrometheusDefaultPushInterval) - pusher := push.New(baseUrl, job).Gatherer(p.gather) - if len(username) != 0 { - pusher.BasicAuth(username, password) + p.exportPushgateway() + } +} + +func (p *promMetricRegistry) exportHttp() { + mux := http.NewServeMux() + path := p.url.GetParam(constant.PrometheusDefaultMetricsPath, constant.PrometheusDefaultMetricsPath) + port := p.url.GetParam(constant.PrometheusExporterMetricsPortKey, constant.PrometheusDefaultMetricsPort) + mux.Handle(path, promhttp.InstrumentMetricHandler(p.r, promhttp.HandlerFor(p.gather, promhttp.HandlerOpts{}))) + srv := &http.Server{Addr: ":" + port, Handler: mux} + extension.AddCustomShutdownCallback(func() { + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + if err := srv.Shutdown(ctx); nil != err { + logger.Fatalf("prometheus server shutdown failed, err: %v", err) + } else { + logger.Info("prometheus server gracefully shutdown success") } - logger.Infof("prometheus pushgateway will push to %s every %d seconds", baseUrl, pushInterval) - ticker := time.NewTicker(time.Duration(pushInterval) * time.Second) - go func() { - for range ticker.C { - err := pusher.Add() - if err != nil { - logger.Errorf("push metric data to prometheus push gateway error", err) - } else { - logger.Debugf("prometheus pushgateway push to %s success", baseUrl) - } - } - }() + }) + logger.Infof("prometheus endpoint :%s%s", port, path) + if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed { // except Shutdown or Close + logger.Errorf("new prometheus server with error: %v", err) } } +func (p *promMetricRegistry) exportPushgateway() { + baseUrl, exist := p.url.GetNonDefaultParam(constant.PrometheusPushgatewayBaseUrlKey) + if !exist { + logger.Error("no pushgateway base url found in config path: metrics.prometheus.pushgateway.base-url, please check your config") + return + } + username := p.url.GetParam(constant.PrometheusPushgatewayBaseUrlKey, "") + password := p.url.GetParam(constant.PrometheusPushgatewayBaseUrlKey, "") + job := p.url.GetParam(constant.PrometheusPushgatewayJobKey, constant.PrometheusDefaultJobName) + pushInterval := p.url.GetParamByIntValue(constant.PrometheusPushgatewayPushIntervalKey, constant.PrometheusDefaultPushInterval) + pusher := push.New(baseUrl, job).Gatherer(p.gather) + if len(username) != 0 { + pusher.BasicAuth(username, password) + } + logger.Infof("prometheus pushgateway will push to %s every %d seconds", baseUrl, pushInterval) + ticker := time.NewTicker(time.Duration(pushInterval) * time.Second) + go func() { + for range ticker.C { + err := pusher.Add() + if err != nil { + logger.Errorf("push metric data to prometheus pushgateway error: %v", err) + } else { + logger.Debugf("prometheus pushgateway push to %s success", baseUrl) + } + } + }() +} + func (p *promMetricRegistry) Scrape() (string, error) { gathering, err := p.gather.Gather() if err != nil { diff --git a/metrics/registry/collector.go b/metrics/registry/collector.go index 53a5d71b30..871dd469be 100644 --- a/metrics/registry/collector.go +++ b/metrics/registry/collector.go @@ -28,9 +28,11 @@ var ( ) func init() { - metrics.AddCollector("registry", func(m metrics.MetricRegistry, _ *common.URL) { - rc := ®istryCollector{metrics.BaseCollector{R: m}} - go rc.start() + metrics.AddCollector("registry", func(m metrics.MetricRegistry, url *common.URL) { + if url.GetParamBool(constant.RegistryEnabledKey, true) { + rc := ®istryCollector{metrics.BaseCollector{R: m}} + go rc.start() + } }) } diff --git a/metrics/rpc/collector.go b/metrics/rpc/collector.go index dc9fb53347..d9e9f0551a 100644 --- a/metrics/rpc/collector.go +++ b/metrics/rpc/collector.go @@ -33,12 +33,14 @@ var ( // init will add the rpc collectorFunc to metrics.collectors slice, and lazy start the rpc collector goroutine func init() { - collectorFunc := func(registry metrics.MetricRegistry, c *common.URL) { - rc := &rpcCollector{ - registry: registry, - metricSet: buildMetricSet(registry), + collectorFunc := func(registry metrics.MetricRegistry, url *common.URL) { + if url.GetParamBool(constant.RpcEnabledKey, true) { + rc := &rpcCollector{ + registry: registry, + metricSet: buildMetricSet(registry), + } + go rc.start() } - go rc.start() } metrics.AddCollector("rpc", collectorFunc) From cccb67d802da04479f8ec0e68f65d3f332249bf0 Mon Sep 17 00:00:00 2001 From: Wang Guan Date: Fri, 27 Oct 2023 11:00:32 +0800 Subject: [PATCH 18/22] feat: add rpc exception metrics (#2459) --- metrics/rpc/collector.go | 14 ++++++++++++++ metrics/rpc/metric_set.go | 10 ++++++++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/metrics/rpc/collector.go b/metrics/rpc/collector.go index d9e9f0551a..08881382ca 100644 --- a/metrics/rpc/collector.go +++ b/metrics/rpc/collector.go @@ -95,6 +95,9 @@ func (c *rpcCollector) afterInvokeHandler(event *metricsEvent) { if event.result != nil { if event.result.Error() == nil { c.incRequestsSucceedTotal(role, labels) + } else { + // TODO: Breaking down RPC exceptions further + c.incRequestsFailedTotal(role, labels) } } c.reportRTMilliseconds(role, labels, event.costTime.Milliseconds()) @@ -149,6 +152,17 @@ func (c *rpcCollector) incRequestsSucceedTotal(role string, labels map[string]st } } +func (c *rpcCollector) incRequestsFailedTotal(role string, labels map[string]string) { + switch role { + case constant.SideProvider: + c.metricSet.provider.requestsFailedTotal.Inc(labels) + c.metricSet.provider.requestsFailedTotalAggregate.Inc(labels) + case constant.SideConsumer: + c.metricSet.consumer.requestsFailedTotal.Inc(labels) + c.metricSet.consumer.requestsFailedTotalAggregate.Inc(labels) + } +} + func (c *rpcCollector) reportRTMilliseconds(role string, labels map[string]string, cost int64) { switch role { case constant.SideProvider: diff --git a/metrics/rpc/metric_set.go b/metrics/rpc/metric_set.go index a27d439bc9..aa349467c8 100644 --- a/metrics/rpc/metric_set.go +++ b/metrics/rpc/metric_set.go @@ -43,6 +43,8 @@ type rpcCommonMetrics struct { requestsProcessingTotal metrics.GaugeVec requestsSucceedTotal metrics.CounterVec requestsSucceedTotalAggregate metrics.AggregateCounterVec + requestsFailedTotal metrics.CounterVec + requestsFailedTotalAggregate metrics.AggregateCounterVec rtMilliseconds metrics.RtVec rtMillisecondsQuantiles metrics.QuantileMetricVec rtMillisecondsAggregate metrics.RtVec @@ -66,12 +68,14 @@ func (pm *providerMetrics) init(registry metrics.MetricRegistry) { pm.requestsProcessingTotal = metrics.NewGaugeVec(registry, metrics.NewMetricKey("dubbo_provider_requests_processing_total", "The number of received requests being processed by the provider")) pm.requestsSucceedTotal = metrics.NewCounterVec(registry, metrics.NewMetricKey("dubbo_provider_requests_succeed_total", "The number of requests successfully received by the provider")) pm.requestsSucceedTotalAggregate = metrics.NewAggregateCounterVec(registry, metrics.NewMetricKey("dubbo_provider_requests_succeed_total_aggregate", "The number of successful requests received by the provider under the sliding window")) + pm.requestsFailedTotal = metrics.NewCounterVec(registry, metrics.NewMetricKey("dubbo_provider_requests_failed_total", "Total Failed Requests")) + pm.requestsFailedTotalAggregate = metrics.NewAggregateCounterVec(registry, metrics.NewMetricKey("dubbo_provider_requests_failed_total_aggregate", "Total Failed Aggregate Requests")) pm.rtMilliseconds = metrics.NewRtVec(registry, metrics.NewMetricKey("dubbo_provider_rt_milliseconds", "response time among all requests processed by the provider"), &metrics.RtOpts{Aggregate: false}, ) pm.rtMillisecondsAggregate = metrics.NewRtVec(registry, - metrics.NewMetricKey("dubbo_provider_rt_milliseconds", "response time of the provider under the sliding window"), + metrics.NewMetricKey("dubbo_provider_rt", "response time of the provider under the sliding window"), &metrics.RtOpts{Aggregate: true, BucketNum: metrics.DefaultBucketNum, TimeWindowSeconds: metrics.DefaultTimeWindowSeconds}, ) pm.rtMillisecondsQuantiles = metrics.NewQuantileMetricVec(registry, []*metrics.MetricKey{ @@ -89,12 +93,14 @@ func (cm *consumerMetrics) init(registry metrics.MetricRegistry) { cm.requestsProcessingTotal = metrics.NewGaugeVec(registry, metrics.NewMetricKey("dubbo_consumer_requests_processing_total", "The number of received requests being processed by the consumer")) cm.requestsSucceedTotal = metrics.NewCounterVec(registry, metrics.NewMetricKey("dubbo_consumer_requests_succeed_total", "The number of successful requests sent by consumers")) cm.requestsSucceedTotalAggregate = metrics.NewAggregateCounterVec(registry, metrics.NewMetricKey("dubbo_consumer_requests_succeed_total_aggregate", "The number of successful requests sent by consumers under the sliding window")) + cm.requestsFailedTotal = metrics.NewCounterVec(registry, metrics.NewMetricKey("dubbo_consumer_requests_failed_total", "Total Failed Requests")) + cm.requestsFailedTotalAggregate = metrics.NewAggregateCounterVec(registry, metrics.NewMetricKey("dubbo_consumer_requests_failed_total_aggregate", "Total Failed Aggregate Requests")) cm.rtMilliseconds = metrics.NewRtVec(registry, metrics.NewMetricKey("dubbo_consumer_rt_milliseconds", "response time among all requests from consumers"), &metrics.RtOpts{Aggregate: false}, ) cm.rtMillisecondsAggregate = metrics.NewRtVec(registry, - metrics.NewMetricKey("dubbo_consumer_rt_milliseconds", "response time of the consumer under the sliding window"), + metrics.NewMetricKey("dubbo_consumer_rt", "response time of the consumer under the sliding window"), &metrics.RtOpts{Aggregate: true, BucketNum: metrics.DefaultBucketNum, TimeWindowSeconds: metrics.DefaultTimeWindowSeconds}, ) cm.rtMillisecondsQuantiles = metrics.NewQuantileMetricVec(registry, []*metrics.MetricKey{ From 918f22a2d7c2081bb6440d4a5af1bc98594ad9b0 Mon Sep 17 00:00:00 2001 From: Xuewei Niu Date: Sat, 28 Oct 2023 17:58:22 +0800 Subject: [PATCH 19/22] ci: Clone from target branch (#2468) We are maintaining several branches at this time, e.g. release-3.0 and main. However, cloning dubbo-go-samples for integrate testing is still from master. This leads to CI failure on old branch, like release-3.0, when the master branch have received some breaking changes. Therefore, the dubbo-go-samples' branch is required to keep same as the target branch. Signed-off-by: Xuewei Niu --- .github/workflows/github-actions.yml | 4 +++- integrate_test.sh | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/github-actions.yml b/.github/workflows/github-actions.yml index 1c25fc5349..6fe4a85156 100644 --- a/.github/workflows/github-actions.yml +++ b/.github/workflows/github-actions.yml @@ -2,7 +2,9 @@ name: CI on: push: - branches: "*" + branches: + - main + - 'release-*' pull_request: branches: "*" diff --git a/integrate_test.sh b/integrate_test.sh index f8ca769423..a0f88a076c 100644 --- a/integrate_test.sh +++ b/integrate_test.sh @@ -36,7 +36,7 @@ echo "github pull request base branch -> $3" echo "github pull request head branch -> ${GITHUB_HEAD_REF}" echo "use dubbo-go-samples $3 branch for integration testing" -git clone -b master https://github.com/apache/dubbo-go-samples.git samples && cd samples +git clone -b $3 https://github.com/apache/dubbo-go-samples.git samples && cd samples # update dubbo-go to current commit id go mod edit -replace=dubbo.apache.org/dubbo-go/v3=github.com/"$1"/v3@"$2" From 216a146f33beecf714822d84fcacbfb85e665af5 Mon Sep 17 00:00:00 2001 From: Xuewei Niu Date: Sat, 28 Oct 2023 19:01:13 +0800 Subject: [PATCH 20/22] ci: Fix CI testing failure on push (#2470) `$GITHUB_BASE_NAME` is an invalid variable, and is replaced with `$GITHUB_REF_NAME` to acquire target branch of push. Replacing mod name in `integrate_test.sh` adapts a case of "apache/dubbo-go". It ensures that its mod name isn't changed to "github.com/apache/dubbo-go". Signed-off-by: Xuewei Niu --- .github/workflows/github-actions.yml | 6 ++---- integrate_test.sh | 19 ++++++------------- 2 files changed, 8 insertions(+), 17 deletions(-) diff --git a/.github/workflows/github-actions.yml b/.github/workflows/github-actions.yml index 6fe4a85156..e15150cc82 100644 --- a/.github/workflows/github-actions.yml +++ b/.github/workflows/github-actions.yml @@ -77,12 +77,10 @@ jobs: run: | if [ "$GITHUB_EVENT_NAME" == "pull_request" ]; then chmod +x integrate_test.sh \ - && [[ -n "${{github.event.pull_request.head.repo.full_name}}" ]] \ - && [[ -n "${{github.event.pull_request.head.sha}}" ]] \ - && [[ -n "${{github.base_ref}}" ]] \ && ./integrate_test.sh ${{github.event.pull_request.head.repo.full_name}} ${{github.event.pull_request.head.sha}} ${{github.base_ref}} elif [ "$GITHUB_EVENT_NAME" == "push" ]; then - chmod +x integrate_test.sh && ./integrate_test.sh $GITHUB_REPOSITORY $GITHUB_SHA $GITHUB_BASE_REF + chmod +x integrate_test.sh \ + && ./integrate_test.sh $GITHUB_REPOSITORY $GITHUB_SHA $GITHUB_REF_NAME else echo "$GITHUB_EVENT_NAME is an unsupported event type." exit 1 diff --git a/integrate_test.sh b/integrate_test.sh index a0f88a076c..374202c2ed 100644 --- a/integrate_test.sh +++ b/integrate_test.sh @@ -17,29 +17,22 @@ #!/bin/bash set -e -set -x -echo 'start integrate-test' +echo "start integrate-test: repo = $1, SHA = $2, branch = $3" # set root workspace ROOT_DIR=$(pwd) echo "integrate-test root work-space -> ${ROOT_DIR}" -# show all github-env -echo "github current commit id -> $2" -echo "github pull request branch -> ${GITHUB_REF}" -echo "github pull request slug -> ${GITHUB_REPOSITORY}" -echo "github pull request repo slug -> ${GITHUB_REPOSITORY}" -echo "github pull request actor -> ${GITHUB_ACTOR}" -echo "github pull request repo param -> $1" -echo "github pull request base branch -> $3" -echo "github pull request head branch -> ${GITHUB_HEAD_REF}" - echo "use dubbo-go-samples $3 branch for integration testing" git clone -b $3 https://github.com/apache/dubbo-go-samples.git samples && cd samples # update dubbo-go to current commit id -go mod edit -replace=dubbo.apache.org/dubbo-go/v3=github.com/"$1"/v3@"$2" +if [ "$1" == "apache/dubbo-go" ]; then + go mod edit -replace=dubbo.apache.org/dubbo-go/v3=dubbo.apache.org/dubbo-go/v3@"$2" +else + go mod edit -replace=dubbo.apache.org/dubbo-go/v3=github.com/"$1"/v3@"$2" +fi go mod tidy From bbe0bff8a89dbaa35e11e13bb5198560c540f455 Mon Sep 17 00:00:00 2001 From: Xuewei Niu Date: Sun, 29 Oct 2023 00:01:02 +0800 Subject: [PATCH 21/22] fix(jsonrpc): Limit header size to avoid unexpected OOM (#2466) This patch limits the max size of header to 8Mib to avoid OOM issues. Signed-off-by: Xuewei Niu --- protocol/jsonrpc/server.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/protocol/jsonrpc/server.go b/protocol/jsonrpc/server.go index 4470cb277a..2b3e9a7699 100644 --- a/protocol/jsonrpc/server.go +++ b/protocol/jsonrpc/server.go @@ -57,6 +57,8 @@ const ( DefaultHTTPRspBufferSize = 1024 // PathPrefix ... PathPrefix = byte('/') + // Max HTTP header size in Mib + MaxHeaderSize = 8 * 1024 * 1024 ) // Server is JSON RPC server wrapper @@ -121,7 +123,7 @@ func (s *Server) handlePkg(conn net.Conn) { } for { - bufReader := bufio.NewReader(conn) + bufReader := bufio.NewReader(io.LimitReader(conn, MaxHeaderSize)) r, err := http.ReadRequest(bufReader) if err != nil { logger.Warnf("[ReadRequest] error: %v", err) From 3d97d4c07298566c52979891510048ebacd641d3 Mon Sep 17 00:00:00 2001 From: Wang Guan Date: Mon, 30 Oct 2023 14:39:50 +0800 Subject: [PATCH 22/22] refactor: metrics config (#2465) --- config/metric_config.go | 23 +++++++++-------------- config/metric_config_test.go | 2 -- 2 files changed, 9 insertions(+), 16 deletions(-) diff --git a/config/metric_config.go b/config/metric_config.go index af41eb8532..145200072f 100644 --- a/config/metric_config.go +++ b/config/metric_config.go @@ -39,10 +39,9 @@ type MetricConfig struct { Port string `default:"9090" yaml:"port" json:"port,omitempty" property:"port"` Path string `default:"/metrics" yaml:"path" json:"path,omitempty" property:"path"` Protocol string `default:"prometheus" yaml:"protocol" json:"protocol,omitempty" property:"protocol"` - EnableMetadata *bool `default:"true" yaml:"enable-metadata" json:"enable-metadata,omitempty" property:"enable-metadata"` - EnableRegistry *bool `default:"true" yaml:"enable-registry" json:"enable-registry,omitempty" property:"enable-registry"` - EnableConfigCenter *bool `default:"true" yaml:"enable-config-center" json:"enable-config-center,omitempty" property:"enable-config-center"` - EnableRpc *bool `default:"true" yaml:"enable-rpc" json:"enable-rpc,omitempty" property:"enable-rpc"` + EnableMetadata *bool `default:"false" yaml:"enable-metadata" json:"enable-metadata,omitempty" property:"enable-metadata"` + EnableRegistry *bool `default:"false" yaml:"enable-registry" json:"enable-registry,omitempty" property:"enable-registry"` + EnableConfigCenter *bool `default:"false" yaml:"enable-config-center" json:"enable-config-center,omitempty" property:"enable-config-center"` Prometheus *PrometheusConfig `yaml:"prometheus" json:"prometheus" property:"prometheus"` Aggregation *AggregateConfig `yaml:"aggregation" json:"aggregation" property:"aggregation"` rootConfig *RootConfig @@ -60,7 +59,7 @@ type PrometheusConfig struct { } type Exporter struct { - Enabled *bool `default:"false" yaml:"enabled" json:"enabled,omitempty" property:"enabled"` + Enabled *bool `default:"true" yaml:"enabled" json:"enabled,omitempty" property:"enabled"` } type PushgatewayConfig struct { @@ -93,7 +92,9 @@ func (mc *MetricConfig) Init(rc *RootConfig) error { return err } mc.rootConfig = rc - metrics.Init(mc.toURL()) + if *mc.Enable { + metrics.Init(mc.toURL()) + } return nil } @@ -120,11 +121,6 @@ func (mcb *MetricConfigBuilder) SetConfigCenterEnabled(enabled bool) *MetricConf return mcb } -func (mcb *MetricConfigBuilder) SetRpcEnabled(enabled bool) *MetricConfigBuilder { - mcb.metricConfig.EnableRpc = &enabled - return mcb -} - func (mcb *MetricConfigBuilder) Build() *MetricConfig { return mcb.metricConfig } @@ -137,15 +133,14 @@ func (mc *MetricConfig) DynamicUpdateProperties(newMetricConfig *MetricConfig) { // prometheus://localhost:9090?&histogram.enabled=false&prometheus.exporter.enabled=false func (mc *MetricConfig) toURL() *common.URL { url, _ := common.NewURL("localhost", common.WithProtocol(mc.Protocol)) - url.SetParam(constant.PrometheusExporterEnabledKey, strconv.FormatBool(*mc.Enable)) // for compatibility url.SetParam(constant.PrometheusExporterMetricsPortKey, mc.Port) url.SetParam(constant.PrometheusExporterMetricsPathKey, mc.Path) url.SetParam(constant.ApplicationKey, mc.rootConfig.Application.Name) url.SetParam(constant.AppVersionKey, mc.rootConfig.Application.Version) + url.SetParam(constant.RpcEnabledKey, strconv.FormatBool(*mc.Enable)) url.SetParam(constant.MetadataEnabledKey, strconv.FormatBool(*mc.EnableMetadata)) url.SetParam(constant.RegistryEnabledKey, strconv.FormatBool(*mc.EnableRegistry)) url.SetParam(constant.ConfigCenterEnabledKey, strconv.FormatBool(*mc.EnableConfigCenter)) - url.SetParam(constant.RpcEnabledKey, strconv.FormatBool(*mc.EnableRpc)) if mc.Aggregation != nil { url.SetParam(constant.AggregationEnabledKey, strconv.FormatBool(*mc.Aggregation.Enabled)) url.SetParam(constant.AggregationBucketNumKey, strconv.Itoa(mc.Aggregation.BucketNum)) @@ -154,7 +149,7 @@ func (mc *MetricConfig) toURL() *common.URL { if mc.Prometheus != nil { if mc.Prometheus.Exporter != nil { exporter := mc.Prometheus.Exporter - url.SetParam(constant.PrometheusExporterEnabledKey, strconv.FormatBool(*exporter.Enabled || *mc.Enable)) // for compatibility + url.SetParam(constant.PrometheusExporterEnabledKey, strconv.FormatBool(*exporter.Enabled)) } if mc.Prometheus.Pushgateway != nil { pushGateWay := mc.Prometheus.Pushgateway diff --git a/config/metric_config_test.go b/config/metric_config_test.go index 31a0ac6b7b..1dfd3af636 100644 --- a/config/metric_config_test.go +++ b/config/metric_config_test.go @@ -30,13 +30,11 @@ func TestMetricConfigBuilder(t *testing.T) { SetConfigCenterEnabled(false). SetMetadataEnabled(false). SetRegistryEnabled(false). - SetRpcEnabled(false). Build() enable := false assert.Equal(t, &MetricConfig{ EnableConfigCenter: &enable, EnableMetadata: &enable, EnableRegistry: &enable, - EnableRpc: &enable, }, config) }