Merge branch 'main' into feature-triple
# Conflicts:
# go.mod
# metrics/prometheus/reporter.go
# metrics/rpc/util.go
diff --git a/Makefile b/Makefile
index 7cee059..233ba53 100644
--- a/Makefile
+++ b/Makefile
@@ -68,6 +68,11 @@
.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
diff --git a/common/constant/default.go b/common/constant/default.go
index 8f5ca55..a27da2f 100644
--- a/common/constant/default.go
+++ b/common/constant/default.go
@@ -59,7 +59,7 @@
// 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/common/constant/key.go b/common/constant/key.go
index 2b6f1ca..2effa04 100644
--- a/common/constant/key.go
+++ b/common/constant/key.go
@@ -185,10 +185,6 @@
const (
ApplicationKey = "application"
- ApplicationNameKey = "application_name"
- ApplicationVersionKey = "application_version"
- HostnameKey = "hostname"
- IpKey = "ip"
OrganizationKey = "organization"
NameKey = "name"
ModuleKey = "module"
@@ -207,10 +203,6 @@
ProvidersCategory = "providers"
RouterKey = "router"
ExportKey = "export"
- GitCommitIdKey = "git_commit_id"
- ConfigCenterKey = "config_center"
- ChangeTypeKey = "change_type"
- KeyKey = "key"
)
// config center keys
@@ -421,7 +413,24 @@
// metrics key
const (
- 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
+const (
+ DefaultMetaCacheName = "dubbo.meta"
+ DefaultMetaFileName = "dubbo.metadata."
+ DefaultEntrySize = 100
)
diff --git a/common/constant/metric.go b/common/constant/metric.go
new file mode 100644
index 0000000..4b35721
--- /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/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 d266fce..9bfeb27 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/metrics.go b/common/extension/metrics.go
deleted file mode 100644
index 639d921..0000000
--- 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 573c4dd..0000000
--- a/common/extension/metrics_test.go
+++ /dev/null
@@ -1,52 +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 (
- "context"
- "testing"
- "time"
-)
-
-import (
- "github.com/stretchr/testify/assert"
-)
-
-import (
- "dubbo.apache.org/dubbo-go/v3/metrics"
- "dubbo.apache.org/dubbo-go/v3/protocol"
-)
-
-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) ReportAfterInvocation(ctx context.Context, invoker protocol.Invoker, invocation protocol.Invocation, cost time.Duration, res protocol.Result) {
-}
-
-func (m *mockReporter) ReportBeforeInvocation(ctx context.Context, invoker protocol.Invoker, invocation protocol.Invocation) {
-}
diff --git a/common/extension/otel_trace.go b/common/extension/otel_trace.go
new file mode 100644
index 0000000..f8023d7
--- /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/common/host_util.go b/common/host_util.go
index 5c411ab..eac0ac1 100644
--- a/common/host_util.go
+++ b/common/host_util.go
@@ -31,8 +31,10 @@
"dubbo.apache.org/dubbo-go/v3/common/constant"
)
-var localIp string
-var localHostname string
+var (
+ localIp string
+ localHostname string
+)
func GetLocalIp() string {
if len(localIp) != 0 {
diff --git a/common/host_util_test.go b/common/host_util_test.go
index b78c4cf..4febece 100644
--- a/common/host_util_test.go
+++ b/common/host_util_test.go
@@ -34,6 +34,10 @@
assert.NotNil(t, GetLocalIp())
}
+func TestGetLocalHostName(t *testing.T) {
+ assert.NotNil(t, GetLocalHostName())
+}
+
func TestHandleRegisterIPAndPort(t *testing.T) {
url := NewURLWithOptions(WithIp("1.2.3.4"), WithPort("20000"))
HandleRegisterIPAndPort(url)
diff --git a/common/url.go b/common/url.go
index 79917a4..cd551c2 100644
--- a/common/url.go
+++ b/common/url.go
@@ -291,6 +291,9 @@
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/metric_config.go b/config/metric_config.go
index a6b8749..0859b57 100644
--- a/config/metric_config.go
+++ b/config/metric_config.go
@@ -18,49 +18,67 @@
package config
import (
- "github.com/creasty/defaults"
+ "strconv"
+)
- "github.com/dubbogo/gost/log/logger"
+import (
+ "github.com/creasty/defaults"
"github.com/pkg/errors"
)
import (
- "dubbo.apache.org/dubbo-go/v3/common/extension"
+ "dubbo.apache.org/dubbo-go/v3/common"
+ "dubbo.apache.org/dubbo-go/v3/common/constant"
"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"`
+ 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
}
-func (mc *MetricConfig) Init() error {
+func (mc *MetricConfig) Init(rc *RootConfig) error {
if mc == nil {
return errors.New("metrics config is null")
}
@@ -70,10 +88,8 @@
if err := verify(mc); err != nil {
return err
}
- metrics.InitAppInfo(GetRootConfig().Application.Name, GetRootConfig().Application.Version)
- config := mc.ToReporterConfig()
- extension.GetMetricReporter(mc.Protocol, config)
- metrics.Init(config)
+ mc.rootConfig = rc
+ metrics.Init(mc.toURL())
return nil
}
@@ -91,12 +107,36 @@
// 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)
+ // TODO update
+}
- extension.GetMetricReporter(mc.Protocol, mc.ToReporterConfig())
+// 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)
+ 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/config/metric_config_test.go b/config/metric_config_test.go
index 14804b3..70dce11 100644
--- a/config/metric_config_test.go
+++ b/config/metric_config_test.go
@@ -27,7 +27,7 @@
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/otel_config.go b/config/otel_config.go
new file mode 100644
index 0000000..6c819ff
--- /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.go b/config/otel_config_test.go
similarity index 66%
copy from filter/otel/trace/version.go
copy to config/otel_config_test.go
index d266fce..af1b302 100644
--- a/filter/otel/trace/version.go
+++ b/config/otel_config_test.go
@@ -15,18 +15,25 @@
* limitations under the License.
*/
-package trace
+package config
import (
- "dubbo.apache.org/dubbo-go/v3/common/constant"
+ "testing"
)
-// Version is the current release version of the dubbogo instrumentation.
-func Version() string {
- return constant.Version
-}
+import (
+ "github.com/stretchr/testify/assert"
+)
-// SemVersion is the semantic version to be supplied to tracer/meter creation.
-func SemVersion() string {
- return "semver:" + Version()
+func TestNewOtelConfigBuilder(t *testing.T) {
+ config := NewOtelConfigBuilder().Build()
+ assert.NotNil(t, config)
+ assert.NotNil(t, config.TraceConfig)
+
+ ac := NewApplicationConfigBuilder().Build()
+ err := config.Init(ac)
+ assert.NoError(t, err)
+
+ tpc := config.TraceConfig.toTraceProviderConfig(ac)
+ assert.NotNil(t, tpc)
}
diff --git a/config/reference_config.go b/config/reference_config.go
index 1d6899e..6b14313 100644
--- a/config/reference_config.go
+++ b/config/reference_config.go
@@ -74,6 +74,7 @@
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"`
}
@@ -100,27 +101,31 @@
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 root.Metric.Enable != nil {
+ rc.metricsEnable = *root.Metric.Enable
}
- 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
- }
return verify(rc)
}
@@ -355,6 +360,9 @@
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/reference_config_test.go b/config/reference_config_test.go
index 8e0d1e3..13a5ed2 100644
--- a/config/reference_config_test.go
+++ b/config/reference_config_test.go
@@ -460,3 +460,10 @@
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)
+}
diff --git a/config/registry_config_test.go b/config/registry_config_test.go
index 1223f6b..83be5ed 100644
--- a/config/registry_config_test.go
+++ b/config/registry_config_test.go
@@ -46,6 +46,7 @@
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 @@
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 @@
}
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) {
diff --git a/config/root_config.go b/config/root_config.go
index 7517702..07e4b8f 100644
--- a/config/root_config.go
+++ b/config/root_config.go
@@ -55,6 +55,7 @@
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"`
@@ -166,19 +167,19 @@
}
// 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
}
}
if err := rc.MetadataReport.Init(rc); err != nil {
return err
}
- if err := rc.Metric.Init(); err != nil {
+ if err := rc.Otel.Init(rc.Application); err != nil {
+ return err
+ }
+ if err := rc.Metric.Init(rc); err != nil {
return err
}
for _, t := range rc.Tracing {
@@ -227,6 +228,7 @@
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 +286,11 @@
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/config/service_config.go b/config/service_config.go
index 6689810..7285ad8 100644
--- a/config/service_config.go
+++ b/config/service_config.go
@@ -82,6 +82,7 @@
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 @@
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)
@@ -267,7 +271,7 @@
}
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()
}
@@ -427,6 +431,9 @@
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 3d6494d..a5000a4 100644
--- a/config/service_config_test.go
+++ b/config/service_config_test.go
@@ -114,7 +114,7 @@
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) {
diff --git a/filter/metrics/filter.go b/filter/metrics/filter.go
index bf59b51..0b623d1 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 @@
"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 fd5614a..f116520 100644
--- a/filter/metrics/filter_test.go
+++ b/filter/metrics/filter_test.go
@@ -19,33 +19,25 @@
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 @@
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/filter/otel/trace/attachment.go b/filter/otel/trace/attachment.go
index 6d84eff..1bda203 100644
--- a/filter/otel/trace/attachment.go
+++ b/filter/otel/trace/attachment.go
@@ -73,7 +73,7 @@
})
}
-// 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 bf3da78..1b9c960 100644
--- a/filter/otel/trace/filter.go
+++ b/filter/otel/trace/filter.go
@@ -37,11 +37,8 @@
"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 @@
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) 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/filter/otel/trace/version_test.go b/filter/otel/trace/version_test.go
deleted file mode 100644
index 332be01..0000000
--- a/filter/otel/trace/version_test.go
+++ /dev/null
@@ -1,63 +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 trace
-
-import (
- "testing"
-)
-
-import (
- "dubbo.apache.org/dubbo-go/v3/common/constant"
-)
-
-type filed struct {
- name string
- want string
-}
-
-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)
- }
- })
- }
-}
-
-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)
- }
- })
- }
-}
diff --git a/go.mod b/go.mod
index 280b4bc..6c53469 100644
--- a/go.mod
+++ b/go.mod
@@ -3,6 +3,7 @@
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 @@
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,20 +21,24 @@
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
github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645
+ github.com/hashicorp/golang-lru v0.5.4
github.com/hashicorp/vault/sdk v0.7.0
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
@@ -47,26 +52,28 @@
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
- golang.org/x/net v0.8.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
)
-
-require (
- github.com/gopherjs/gopherjs v0.0.0-20190910122728-9d188e94fb99 // indirect
- go.uber.org/multierr v1.8.0 // indirect
-)
diff --git a/go.sum b/go.sum
index 5390019..8a4f0a6 100644
--- a/go.sum
+++ b/go.sum
@@ -28,6 +28,7 @@
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.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.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.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.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.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/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/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.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.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.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.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/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 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/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.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.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/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.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/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/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.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.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/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.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=
@@ -801,6 +843,7 @@
github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
+github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc=
github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
@@ -828,6 +871,12 @@
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=
@@ -868,6 +917,7 @@
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=
@@ -877,9 +927,8 @@
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=
@@ -894,6 +943,7 @@
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=
@@ -968,6 +1018,8 @@
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=
@@ -976,7 +1028,13 @@
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=
@@ -988,6 +1046,8 @@
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=
@@ -999,9 +1059,9 @@
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=
@@ -1064,16 +1124,15 @@
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=
@@ -1090,8 +1149,9 @@
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=
@@ -1133,8 +1193,9 @@
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=
@@ -1162,6 +1223,10 @@
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=
@@ -1209,11 +1274,31 @@
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=
@@ -1223,8 +1308,9 @@
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=
@@ -1250,8 +1336,10 @@
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=
@@ -1300,8 +1388,9 @@
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=
@@ -1336,6 +1425,7 @@
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=
@@ -1351,8 +1441,10 @@
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=
@@ -1396,8 +1488,9 @@
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=
@@ -1435,6 +1528,7 @@
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=
@@ -1442,6 +1536,7 @@
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=
@@ -1473,6 +1568,7 @@
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=
@@ -1551,8 +1647,10 @@
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=
@@ -1610,6 +1708,7 @@
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=
@@ -1621,8 +1720,9 @@
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=
@@ -1690,6 +1790,7 @@
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=
@@ -1812,8 +1913,13 @@
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=
@@ -1860,6 +1966,7 @@
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 2e0cef9..3bc668a 100644
--- a/imports/imports.go
+++ b/imports/imports.go
@@ -66,6 +66,10 @@
_ "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/metrics/api.go b/metrics/api.go
index fdc69c1..6a1f519 100644
--- a/metrics/api.go
+++ b/metrics/api.go
@@ -18,63 +18,87 @@
package metrics
import (
+ "encoding/json"
"sync"
)
import (
+ "github.com/dubbogo/gost/log/logger"
+)
+
+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"
)
-var registries = make(map[string]func(*ReporterConfig) MetricRegistry)
-var collectors = make([]CollectorFunc, 0)
-var registry MetricRegistry
+const (
+ DefaultCompression = 100
+ DefaultBucketNum = 10
+ DefaultTimeWindowSeconds = 120
+)
+
+var (
+ 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 {
- // defalut protocol is already set in metricConfig
- regFunc, ok := registries[config.Protocol]
+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[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
}
-// 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)
}
// MetricRegistry data container,data compute、expose、agg
type MetricRegistry interface {
- Counter(*MetricId) CounterMetric // add or update a counter
- Gauge(*MetricId) GaugeMetric // add or update a gauge
- Histogram(*MetricId) HistogramMetric // add a metric num to a histogram
- Summary(*MetricId) SummaryMetric // add a metric num to a summary
- Export() // expose metric data, such as Prometheus http exporter
+ Counter(*MetricId) CounterMetric // add or update a counter
+ Gauge(*MetricId) GaugeMetric // add or update a gauge
+ Histogram(*MetricId) ObservableMetric // add a metric num to a histogram
+ Summary(*MetricId) ObservableMetric // add a metric num to a summary
+ Rt(*MetricId, *RtOpts) ObservableMetric // add a metric num to a rt
+ Export() // expose metric data, such as Prometheus http exporter
// GetMetrics() []*MetricSample // get all metric data
// GetMetricsString() (string, error) // get text format metric data
}
+type RtOpts struct {
+ Aggregate bool
+ BucketNum int // only for aggRt
+ TimeWindowSeconds int64 // only for aggRt
+}
+
// multi registry,like micrometer CompositeMeterRegistry
// type CompositeRegistry struct {
// rs []MetricRegistry
// }
-// Type metric type, save with micrometer
-type Type uint8
+// Type metric type, same with micrometer
+type Type uint8 // TODO check if Type is is useful
const (
Counter Type = iota
@@ -93,8 +117,8 @@
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 {
@@ -109,6 +133,11 @@
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 {
@@ -125,115 +154,275 @@
// GaugeMetric gauge metric
type GaugeMetric interface {
Set(float64)
- // Inc()
- // Dec()
- // Add(float64)
- // Sub(float64)
+ Inc()
+ Dec()
+ Add(float64)
+ Sub(float64)
}
-// HistogramMetric histogram metric
-type HistogramMetric interface {
- Record(float64)
+// histogram summary rt metric
+type ObservableMetric interface {
+ Observe(float64)
}
-// SummaryMetric summary metric
-type SummaryMetric interface {
- Record(float64)
+type BaseCollector struct {
+ R MetricRegistry
}
-// 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)
-}
-
-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()
+ c.R.Counter(NewMetricId(fail, level)).Inc()
}
}
-func (c DefaultStatesMetric) Success() {
- c.r.Counter(c.total).Inc()
- c.r.Counter(c.succ).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)
}
-func (c DefaultStatesMetric) AddSuccess(v float64) {
- c.r.Counter(c.total).Add(v)
- c.r.Counter(c.succ).Add(v)
+// NewCounterVec create a CounterVec default implementation.
+func NewCounterVec(metricRegistry MetricRegistry, metricKey *MetricKey) CounterVec {
+ return &DefaultCounterVec{
+ metricRegistry: metricRegistry,
+ metricKey: metricKey,
+ }
}
-func (c DefaultStatesMetric) Fail() {
- c.r.Counter(c.total).Inc()
- c.r.Counter(c.fail).Inc()
+// DefaultCounterVec is a default CounterVec implementation.
+type DefaultCounterVec struct {
+ metricRegistry MetricRegistry
+ metricKey *MetricKey
}
-func (c DefaultStatesMetric) AddFailed(v float64) {
- c.r.Counter(c.total).Add(v)
- c.r.Counter(c.fail).Add(v)
+func (d *DefaultCounterVec) Inc(labels map[string]string) {
+ d.metricRegistry.Counter(NewMetricIdByLabels(d.metricKey, labels)).Inc()
}
-// 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)
+func (d *DefaultCounterVec) Add(labels map[string]string, v float64) {
+ d.metricRegistry.Counter(NewMetricIdByLabels(d.metricKey, labels)).Add(v)
}
-const (
- defaultBucketNum = 10
- defalutTimeWindowSeconds = 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, defalutTimeWindowSeconds)}
+// 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)
}
-type DefaultTimeMetric struct {
- r MetricRegistry
- agg *aggregate.TimeWindowAggregator
- min, max, avg, sum, last *MetricId
+// NewGaugeVec create a GaugeVec default implementation.
+func NewGaugeVec(metricRegistry MetricRegistry, metricKey *MetricKey) GaugeVec {
+ return &DefaultGaugeVec{
+ metricRegistry: metricRegistry,
+ metricKey: metricKey,
+ }
}
-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)
+// DefaultGaugeVec is a default GaugeVec implementation.
+type DefaultGaugeVec struct {
+ metricRegistry MetricRegistry
+ metricKey *MetricKey
}
-// cache if needed, TimeMetrics must cached
-var metricsCache map[string]interface{} = make(map[string]interface{})
-var metricsCacheMutex sync.RWMutex
+func (d *DefaultGaugeVec) Set(labels map[string]string, v float64) {
+ d.metricRegistry.Gauge(NewMetricIdByLabels(d.metricKey, labels)).Set(v)
+}
-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()
- n := supplier()
- metricsCache[key] = n
- return n
+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/app_info/collector.go b/metrics/app_info/collector.go
index a2bae02..98abeb4 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 @@
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 f0ce9cf..8d8562e 100644
--- a/metrics/common.go
+++ b/metrics/common.go
@@ -64,11 +64,11 @@
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.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 (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 @@
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 (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 7236501..9ae551f 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 16740d3..7125fb1 100644
--- a/metrics/metadata/collector.go
+++ b/metrics/metadata/collector.go
@@ -22,6 +22,7 @@
)
import (
+ "dubbo.apache.org/dubbo-go/v3/common"
"dubbo.apache.org/dubbo-go/v3/common/constant"
"dubbo.apache.org/dubbo-go/v3/metrics"
)
@@ -31,14 +32,14 @@
var ch = make(chan metrics.MetricsEvent, 10)
func init() {
- metrics.AddCollector("metadata", func(mr metrics.MetricRegistry, rc *metrics.ReporterConfig) {
- l := &MetadataMetricCollector{r: mr}
+ metrics.AddCollector("metadata", func(mr metrics.MetricRegistry, _ *common.URL) {
+ l := &MetadataMetricCollector{metrics.BaseCollector{R: mr}}
l.start()
})
}
type MetadataMetricCollector struct {
- r metrics.MetricRegistry
+ metrics.BaseCollector
}
func (c *MetadataMetricCollector) start() {
@@ -63,59 +64,26 @@
}
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 e7ade6e..20d76a3 100644
--- a/metrics/metadata/metric_set.go
+++ b/metrics/metadata/metric_set.go
@@ -47,34 +47,21 @@
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 @@
// 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 @@
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/prometheus/api.go b/metrics/prometheus/api.go
deleted file mode 100644
index 2d01afd..0000000
--- 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/constant.go b/metrics/prometheus/constant.go
deleted file mode 100644
index 41904db..0000000
--- a/metrics/prometheus/constant.go
+++ /dev/null
@@ -1,59 +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 (
- "dubbo.apache.org/dubbo-go/v3/common/constant"
-)
-
-const (
- reporterName = "prometheus"
- 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"
-
- 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/prometheus/metric_set.go b/metrics/prometheus/metric_set.go
deleted file mode 100644
index 5d3caf2..0000000
--- 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 3efd214..0000000
--- 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 70946d6..f84f2ad 100644
--- a/metrics/prometheus/registry.go
+++ b/metrics/prometheus/registry.go
@@ -19,114 +19,182 @@
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/promauto"
+ "github.com/prometheus/client_golang/prometheus/promhttp"
+ "github.com/prometheus/client_golang/prometheus/push"
"github.com/prometheus/common/expfmt"
)
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("prometheus", func(rc *metrics.ReporterConfig) metrics.MetricRegistry {
- return &promMetricRegistry{
- cvm: make(map[string]*prom.CounterVec),
- gvm: make(map[string]*prom.GaugeVec),
- hvm: make(map[string]*prom.HistogramVec),
- svm: make(map[string]*prom.SummaryVec),
- }
+ metrics.SetRegistry(constant.ProtocolPrometheus, func(url *common.URL) metrics.MetricRegistry {
+ return &promMetricRegistry{r: prom.DefaultRegisterer, gather: prom.DefaultGatherer, url: url}
})
}
type promMetricRegistry struct {
- mtx sync.RWMutex // Protects metrics.
- cvm map[string]*prom.CounterVec // prom.CounterVec
- gvm map[string]*prom.GaugeVec // prom.GaugeVec
- hvm map[string]*prom.HistogramVec // prom.HistogramVec
- svm map[string]*prom.SummaryVec // prom.SummaryVec
+ 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() prom.Collector) interface{} {
+ v, ok := p.vecs.Load(key)
+ if !ok {
+ v, ok = p.vecs.LoadOrStore(key, supplier())
+ if !ok {
+ p.r.MustRegister(v.(prom.Collector)) // only registe collector which stored success
+ }
+ }
+ return v
}
func (p *promMetricRegistry) Counter(m *metrics.MetricId) metrics.CounterMetric {
- p.mtx.RLock()
- vec, ok := p.cvm[m.Name]
- p.mtx.RUnlock()
- if !ok {
- p.mtx.Lock()
- vec = promauto.NewCounterVec(prom.CounterOpts{
+ vec := p.getOrComputeVec(m.Name, func() prom.Collector {
+ return prom.NewCounterVec(prom.CounterOpts{
Name: m.Name,
Help: m.Desc,
}, m.TagKeys())
- p.cvm[m.Name] = vec
- p.mtx.Unlock()
- }
- c := vec.With(m.Tags)
- return &counter{pc: c}
+ }).(*prom.CounterVec)
+ return vec.With(m.Tags)
}
func (p *promMetricRegistry) Gauge(m *metrics.MetricId) metrics.GaugeMetric {
- p.mtx.RLock()
- vec, ok := p.gvm[m.Name]
- p.mtx.RUnlock()
- if !ok {
- p.mtx.Lock()
- vec = promauto.NewGaugeVec(prom.GaugeOpts{
+ vec := p.getOrComputeVec(m.Name, func() prom.Collector {
+ return prom.NewGaugeVec(prom.GaugeOpts{
Name: m.Name,
Help: m.Desc,
}, m.TagKeys())
- p.gvm[m.Name] = vec
- p.mtx.Unlock()
- }
- g := vec.With(m.Tags)
- return &gauge{pg: g}
+ }).(*prom.GaugeVec)
+ return vec.With(m.Tags)
}
-func (p *promMetricRegistry) Histogram(m *metrics.MetricId) metrics.HistogramMetric {
- p.mtx.RLock()
- vec, ok := p.hvm[m.Name]
- p.mtx.RUnlock()
- if !ok {
- p.mtx.Lock()
- vec = promauto.NewHistogramVec(prom.HistogramOpts{
+func (p *promMetricRegistry) Histogram(m *metrics.MetricId) metrics.ObservableMetric {
+ vec := p.getOrComputeVec(m.Name, func() prom.Collector {
+ return prom.NewHistogramVec(prom.HistogramOpts{
Name: m.Name,
Help: m.Desc,
}, m.TagKeys())
- p.hvm[m.Name] = vec
- p.mtx.Unlock()
- }
- h := vec.With(m.Tags)
- return &histogram{ph: h.(prom.Histogram)}
+ }).(*prom.HistogramVec)
+ return vec.With(m.Tags)
}
-func (p *promMetricRegistry) Summary(m *metrics.MetricId) metrics.SummaryMetric {
- p.mtx.RLock()
- vec, ok := p.svm[m.Name]
- p.mtx.RUnlock()
- if !ok {
- p.mtx.Lock()
- vec = promauto.NewSummaryVec(prom.SummaryOpts{
+func (p *promMetricRegistry) Summary(m *metrics.MetricId) metrics.ObservableMetric {
+ vec := p.getOrComputeVec(m.Name, func() prom.Collector {
+ return prom.NewSummaryVec(prom.SummaryOpts{
Name: m.Name,
Help: m.Desc,
}, m.TagKeys())
- p.svm[m.Name] = vec
- p.mtx.Unlock()
+ }).(*prom.SummaryVec)
+ return vec.With(m.Tags)
+}
+
+func (p *promMetricRegistry) Rt(m *metrics.MetricId, opts *metrics.RtOpts) metrics.ObservableMetric {
+ key := m.Name
+ var supplier func() prom.Collector
+ if opts != nil && opts.Aggregate {
+ key += "_aggregate"
+ 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,
+ bucketNum: opts.BucketNum,
+ timeWindowSeconds: opts.TimeWindowSeconds,
+ }, m.TagKeys())
+ }
+ } else {
+ supplier = func() prom.Collector {
+ return NewRtVec(&RtOpts{
+ Name: m.Name,
+ Help: m.Desc,
+ }, m.TagKeys())
+ }
}
- s := vec.With(m.Tags)
- return &summary{ps: s.(prom.Summary)}
+ vec := p.getOrComputeVec(key, supplier).(*RtVec)
+ return vec.With(m.Tags)
}
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)
+ }
+ }()
+ }
+ 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 := prom.DefaultRegisterer.(*prom.Registry)
- gathering, err := r.Gather()
+ gathering, err := p.gather.Gather()
if err != nil {
return "", err
}
@@ -138,52 +206,3 @@
}
return out.String(), nil
}
-
-type counter struct {
- pc prom.Counter
-}
-
-func (c *counter) Inc() {
- c.pc.Inc()
-}
-func (c *counter) Add(v float64) {
- c.pc.Add(v)
-}
-
-type gauge struct {
- pg prom.Gauge
-}
-
-// func (g *gauge) Inc() {
-// g.pg.Inc()
-// }
-//
-// func (g *gauge) Dec() {
-// g.pg.Dec()
-// }
-func (g *gauge) Set(v float64) {
- g.pg.Set(v)
-}
-
-// func (g *gauge) Add(v float64) {
-// g.pg.Add(v)
-// }
-// func (g *gauge) Sub(v float64) {
-// g.pg.Sub(v)
-// }
-
-type histogram struct {
- ph prom.Histogram
-}
-
-func (h *histogram) Record(v float64) {
- h.ph.Observe(v)
-}
-
-type summary struct {
- ps prom.Summary
-}
-
-func (s *summary) Record(v float64) {
- s.ps.Observe(v)
-}
diff --git a/metrics/prometheus/registry_test.go b/metrics/prometheus/registry_test.go
new file mode 100644
index 0000000..a3e5e66
--- /dev/null
+++ b/metrics/prometheus/registry_test.go
@@ -0,0 +1,192 @@
+/*
+ * 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 (
+ "io"
+ "net/http"
+ "sync"
+ "testing"
+ "time"
+)
+
+import (
+ prom "github.com/prometheus/client_golang/prometheus"
+
+ "github.com/stretchr/testify/assert"
+)
+
+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 := NewPromMetricRegistry(prom.NewRegistry(), url)
+ p.Counter(metricId).Inc()
+ text, err := p.Scrape()
+ assert.Nil(t, err)
+ 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"} 1`)
+}
+
+func TestPromMetricRegistryGauge(t *testing.T) {
+ p := NewPromMetricRegistry(prom.NewRegistry(), url)
+ p.Gauge(metricId).Set(100)
+ text, err := p.Scrape()
+ assert.Nil(t, err)
+ assert.Contains(t, text, "# HELP dubbo_request request\n# TYPE dubbo_request gauge")
+ assert.Contains(t, text, `dubbo_request{app="dubbo",version="1.0.0"} 100`)
+
+}
+
+func TestPromMetricRegistryHistogram(t *testing.T) {
+ p := NewPromMetricRegistry(prom.NewRegistry(), url)
+ p.Histogram(metricId).Observe(100)
+ text, err := p.Scrape()
+ assert.Nil(t, err)
+ assert.Contains(t, text, "# HELP dubbo_request request\n# TYPE dubbo_request histogram")
+ assert.Contains(t, text, `dubbo_request_bucket{app="dubbo",version="1.0.0",le="+Inf"} 1`)
+ assert.Contains(t, text, `dubbo_request_sum{app="dubbo",version="1.0.0"} 100`)
+ assert.Contains(t, text, `dubbo_request_count{app="dubbo",version="1.0.0"} 1`)
+}
+
+func TestPromMetricRegistrySummary(t *testing.T) {
+ p := NewPromMetricRegistry(prom.NewRegistry(), url)
+ p.Summary(metricId).Observe(100)
+ text, err := p.Scrape()
+ assert.Nil(t, err)
+ assert.Contains(t, text, "# HELP dubbo_request request\n# TYPE dubbo_request summary")
+ assert.Contains(t, text, "dubbo_request_sum{app=\"dubbo\",version=\"1.0.0\"} 100")
+ assert.Contains(t, text, "dubbo_request_count{app=\"dubbo\",version=\"1.0.0\"} 1")
+}
+
+func TestPromMetricRegistryRt(t *testing.T) {
+ p := NewPromMetricRegistry(prom.NewRegistry(), url)
+ for i := 0; i < 10; i++ {
+ p.Rt(metricId, &metrics.RtOpts{}).Observe(10 * float64(i))
+ }
+ text, err := p.Scrape()
+ assert.Nil(t, err)
+ assert.Contains(t, text, "# HELP dubbo_request_avg Average request\n# TYPE dubbo_request_avg gauge\ndubbo_request_avg{app=\"dubbo\",version=\"1.0.0\"} 45")
+ assert.Contains(t, text, "# HELP dubbo_request_last Last request\n# TYPE dubbo_request_last gauge\ndubbo_request_last{app=\"dubbo\",version=\"1.0.0\"} 90")
+ assert.Contains(t, text, "# HELP dubbo_request_max Max request\n# TYPE dubbo_request_max gauge\ndubbo_request_max{app=\"dubbo\",version=\"1.0.0\"} 90")
+ 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 = 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))
+ }
+ text, err = p.Scrape()
+ assert.Nil(t, err)
+ assert.Contains(t, text, "# HELP dubbo_request_avg_milliseconds_aggregate The average request\n# TYPE dubbo_request_avg_milliseconds_aggregate gauge\ndubbo_request_avg_milliseconds_aggregate{app=\"dubbo\",version=\"1.0.0\"} 45")
+ assert.Contains(t, text, "# HELP dubbo_request_max_milliseconds_aggregate The maximum request\n# TYPE dubbo_request_max_milliseconds_aggregate gauge\ndubbo_request_max_milliseconds_aggregate{app=\"dubbo\",version=\"1.0.0\"} 90")
+ assert.Contains(t, text, "# HELP dubbo_request_min_milliseconds_aggregate The minimum request\n# TYPE dubbo_request_min_milliseconds_aggregate gauge\ndubbo_request_min_milliseconds_aggregate{app=\"dubbo\",version=\"1.0.0\"} 0")
+}
+
+func TestPromMetricRegistryCounterConcurrent(t *testing.T) {
+ p := NewPromMetricRegistry(prom.NewRegistry(), url)
+ var wg sync.WaitGroup
+ for i := 0; i < 10; i++ {
+ wg.Add(1)
+ go func() {
+ p.Counter(metricId).Inc()
+ wg.Done()
+ }()
+ }
+ wg.Wait()
+ text, err := p.Scrape()
+ assert.Nil(t, err)
+ 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 0e9fedc..0000000
--- a/metrics/prometheus/reporter.go
+++ /dev/null
@@ -1,214 +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"
- "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
- reporterInitOnce sync.Once
-)
-
-// should initialize after loading configuration
-func init() {
- // newPrometheusReporter()
- extension.SetMetricReporter(reporterName, newPrometheusReporter)
-}
-
-// PrometheusReporter will collect the data for Prometheus
-// if you want to use this feature, you need to initialize your prometheus.
-// https://prometheus.io/docs/guides/go-application/
-type PrometheusReporter struct {
- reporterServer *http.Server
- reporterConfig *metrics.ReporterConfig
- metricSet
- syncMaps
- namespace string
-}
-
-// newPrometheusReporter create new prometheusReporter
-// it will register the metrics into prometheus
-func newPrometheusReporter(reporterConfig *metrics.ReporterConfig) metrics.Reporter {
- if reporterInstance == nil {
- reporterInitOnce.Do(func() {
- ms := &metricSet{}
- ms.init(reporterConfig)
- reporterInstance = &PrometheusReporter{
- reporterConfig: reporterConfig,
- namespace: reporterConfig.Namespace,
- metricSet: *ms,
- }
- })
- }
-
- if reporterConfig.Enable {
- if reporterConfig.Mode == metrics.ReportModePull {
- go reporterInstance.startupServer(reporterConfig)
- }
- // todo pushgateway support
- } else {
- reporterInstance.shutdownServer()
- }
-
- return reporterInstance
-}
-
-func (reporter *PrometheusReporter) startupServer(reporterConfig *metrics.ReporterConfig) {
- // start server
- mux := http.NewServeMux()
- mux.Handle(reporterConfig.Path, promhttp.Handler())
- reporterInstance.reporterServer = &http.Server{Addr: ":" + reporterConfig.Port, Handler: mux}
- if err := reporterInstance.reporterServer.ListenAndServe(); err != nil {
- logger.Warnf("new prometheus reporter with error = %s", err)
- }
-}
-
-func (reporter *PrometheusReporter) 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()
- }
- }
-}
-
-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 b3ca11c..0000000
--- 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/prometheus/rt_vec.go b/metrics/prometheus/rt_vec.go
new file mode 100644
index 0000000..265374c
--- /dev/null
+++ b/metrics/prometheus/rt_vec.go
@@ -0,0 +1,200 @@
+/*
+ * 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 (
+ "bytes"
+ "sync"
+)
+
+import (
+ prom "github.com/prometheus/client_golang/prometheus"
+)
+
+import (
+ "dubbo.apache.org/dubbo-go/v3/metrics/util/aggregate"
+)
+
+type rtMetric struct {
+ nameSuffix string
+ helpPrefix string
+ valueFunc func(*aggregate.Result) float64
+}
+
+func (m *rtMetric) desc(opts *RtOpts, labels []string) *prom.Desc {
+ return prom.NewDesc(prom.BuildFQName(opts.Namespace, opts.Subsystem, opts.Name+m.nameSuffix), m.helpPrefix+opts.Help, labels, opts.ConstLabels)
+}
+
+var (
+ rtMetrics = make([]*rtMetric, 5)
+ aggMetrics = make([]*rtMetric, 3)
+)
+
+func init() {
+ rtMetrics[0] = &rtMetric{nameSuffix: "_sum", helpPrefix: "Sum ", valueFunc: func(r *aggregate.Result) float64 { return r.Total }}
+ rtMetrics[1] = &rtMetric{nameSuffix: "_last", helpPrefix: "Last ", valueFunc: func(r *aggregate.Result) float64 { return r.Last }}
+ rtMetrics[2] = &rtMetric{nameSuffix: "_min", helpPrefix: "Min ", valueFunc: func(r *aggregate.Result) float64 { return r.Min }}
+ rtMetrics[3] = &rtMetric{nameSuffix: "_max", helpPrefix: "Max ", valueFunc: func(r *aggregate.Result) float64 { return r.Max }}
+ rtMetrics[4] = &rtMetric{nameSuffix: "_avg", helpPrefix: "Average ", valueFunc: func(r *aggregate.Result) float64 { return r.Avg }}
+
+ aggMetrics[0] = &rtMetric{nameSuffix: "_avg_milliseconds_aggregate", helpPrefix: "The average ", valueFunc: func(r *aggregate.Result) float64 { return r.Avg }}
+ aggMetrics[1] = &rtMetric{nameSuffix: "_min_milliseconds_aggregate", helpPrefix: "The minimum ", valueFunc: func(r *aggregate.Result) float64 { return r.Min }}
+ aggMetrics[2] = &rtMetric{nameSuffix: "_max_milliseconds_aggregate", helpPrefix: "The maximum ", valueFunc: func(r *aggregate.Result) float64 { return r.Max }}
+}
+
+type RtOpts struct {
+ Namespace string
+ Subsystem string
+ Name string
+ Help string
+ ConstLabels prom.Labels
+ bucketNum int // only for aggRt
+ timeWindowSeconds int64 // only for aggRt
+}
+
+type observer interface {
+ Observe(val float64)
+ result() *aggregate.Result
+}
+
+type aggResult struct {
+ agg *aggregate.TimeWindowAggregator
+}
+
+func (r *aggResult) Observe(val float64) {
+ r.agg.Add(val)
+}
+
+func (r *aggResult) result() *aggregate.Result {
+ return r.agg.Result()
+}
+
+type valueResult struct {
+ mtx sync.RWMutex
+ val *aggregate.Result
+}
+
+func (r *valueResult) Observe(val float64) {
+ r.mtx.Lock()
+ defer r.mtx.Unlock()
+ r.val.Update(val)
+}
+
+func (r *valueResult) result() *aggregate.Result {
+ res := aggregate.NewResult()
+ r.mtx.RLock()
+ res.Merge(r.val)
+ r.mtx.RUnlock()
+ return res.Get()
+}
+
+type Rt struct {
+ tags map[string]string
+ obs observer
+}
+
+func (r *Rt) Observe(val float64) {
+ r.obs.Observe(val)
+}
+
+func buildKey(m map[string]string, labNames []string) string {
+ var buffer bytes.Buffer
+ for _, label := range labNames {
+ if buffer.Len() != 0 {
+ buffer.WriteString("_")
+ }
+ buffer.WriteString(m[label])
+ }
+ return buffer.String()
+}
+
+func buildLabelValues(m map[string]string, labNames []string) []string {
+ values := make([]string, len(labNames))
+ for i, label := range labNames {
+ values[i] = m[label]
+ }
+ return values
+}
+
+type RtVec struct {
+ opts *RtOpts
+ labelNames []string
+ aggMap sync.Map
+ initFunc func(tags map[string]string) *Rt
+ metrics []*rtMetric
+}
+
+func NewRtVec(opts *RtOpts, labNames []string) *RtVec {
+ return &RtVec{
+ opts: opts,
+ labelNames: labNames,
+ metrics: rtMetrics,
+ initFunc: func(tags map[string]string) *Rt {
+ return &Rt{
+ tags: tags,
+ obs: &valueResult{val: aggregate.NewResult()},
+ }
+ },
+ }
+}
+
+func NewAggRtVec(opts *RtOpts, labNames []string) *RtVec {
+ return &RtVec{
+ opts: opts,
+ labelNames: labNames,
+ metrics: aggMetrics,
+ initFunc: func(tags map[string]string) *Rt {
+ return &Rt{
+ tags: tags,
+ obs: &aggResult{agg: aggregate.NewTimeWindowAggregator(opts.bucketNum, opts.timeWindowSeconds)},
+ }
+ },
+ }
+}
+
+func (r *RtVec) With(tags map[string]string) prom.Observer {
+ k := buildKey(tags, r.labelNames)
+ return r.computeIfAbsent(k, func() *Rt {
+ return r.initFunc(tags)
+ })
+}
+
+func (r *RtVec) computeIfAbsent(k string, supplier func() *Rt) *Rt {
+ v, ok := r.aggMap.Load(k)
+ if !ok {
+ v, _ = r.aggMap.LoadOrStore(k, supplier())
+ }
+ return v.(*Rt)
+}
+
+func (r *RtVec) Collect(ch chan<- prom.Metric) {
+ r.aggMap.Range(func(_, val interface{}) bool {
+ v := val.(*Rt)
+ res := v.obs.result()
+ for _, m := range r.metrics {
+ ch <- prom.MustNewConstMetric(m.desc(r.opts, r.labelNames), prom.GaugeValue, m.valueFunc(res), buildLabelValues(v.tags, r.labelNames)...)
+ }
+ return true
+ })
+}
+
+func (r *RtVec) Describe(ch chan<- *prom.Desc) {
+ for _, m := range r.metrics {
+ ch <- m.desc(r.opts, r.labelNames)
+ }
+}
diff --git a/metrics/prometheus/rt_vec_test.go b/metrics/prometheus/rt_vec_test.go
new file mode 100644
index 0000000..8964798
--- /dev/null
+++ b/metrics/prometheus/rt_vec_test.go
@@ -0,0 +1,166 @@
+/*
+ * 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 (
+ "reflect"
+ "sync"
+ "testing"
+)
+
+import (
+ prom "github.com/prometheus/client_golang/prometheus"
+
+ "github.com/stretchr/testify/assert"
+)
+
+import (
+ "dubbo.apache.org/dubbo-go/v3/metrics/util/aggregate"
+)
+
+func TestRtVecCollect(t *testing.T) {
+ opts := &RtOpts{
+ Name: "request_num",
+ bucketNum: 10,
+ timeWindowSeconds: 120,
+ Help: "Request cost",
+ }
+ labels := []string{"app", "version"}
+ vecs := [2]*RtVec{NewRtVec(opts, labels), NewAggRtVec(opts, labels)}
+ for _, r := range vecs {
+ r.With(map[string]string{"app": "dubbo", "version": "1.0.0"}).Observe(100)
+ ch := make(chan prom.Metric, len(r.metrics))
+ r.Collect(ch)
+ close(ch)
+ assert.Equal(t, len(ch), len(r.metrics))
+ for _, m := range r.metrics {
+ metric, ok := <-ch
+ if !ok {
+ t.Error("not enough metrics")
+ } else {
+ str := metric.Desc().String()
+ assert.Contains(t, str, m.nameSuffix)
+ assert.Contains(t, str, m.helpPrefix)
+ assert.Contains(t, str, "app")
+ assert.Contains(t, str, "version")
+ }
+ }
+ }
+}
+
+func TestRtVecDescribe(t *testing.T) {
+ opts := &RtOpts{
+ Name: "request_num",
+ bucketNum: 10,
+ timeWindowSeconds: 120,
+ Help: "Request cost",
+ }
+ labels := []string{"app", "version"}
+ vecs := [2]*RtVec{NewRtVec(opts, labels), NewAggRtVec(opts, labels)}
+ for _, r := range vecs {
+ ch := make(chan *prom.Desc, len(r.metrics))
+ r.Describe(ch)
+ close(ch)
+ assert.Equal(t, len(ch), len(r.metrics))
+ for _, m := range r.metrics {
+ desc, ok := <-ch
+ if !ok {
+ t.Error(t, "not enough desc")
+ } else {
+ str := desc.String()
+ assert.Contains(t, str, m.nameSuffix)
+ assert.Contains(t, str, m.helpPrefix)
+ assert.Contains(t, str, "app")
+ assert.Contains(t, str, "version")
+ }
+ }
+ }
+}
+
+func TestValueObserve(t *testing.T) {
+ rts := []*Rt{
+ {
+ tags: map[string]string{},
+ obs: &aggResult{agg: aggregate.NewTimeWindowAggregator(10, 10)},
+ },
+ {
+ tags: map[string]string{},
+ obs: &valueResult{val: aggregate.NewResult()},
+ },
+ }
+ want := &aggregate.Result{
+ Avg: 1,
+ Min: 1,
+ Max: 1,
+ Count: 1,
+ Total: 1,
+ Last: 1,
+ }
+ for i, v := range rts {
+ v.Observe(float64(1))
+ r := v.obs.result()
+ if i == 0 {
+ r.Last = 1 // agg result no Last, value is NaN
+ }
+ if !reflect.DeepEqual(r, want) {
+ t.Errorf("Result() = %v, want %v", r, want)
+ }
+ }
+}
+
+func TestRtVecWith(t *testing.T) {
+ opts := &RtOpts{
+ Name: "request_num",
+ bucketNum: 10,
+ timeWindowSeconds: 120,
+ Help: "Request cost",
+ }
+ labels := []string{"app", "version"}
+ vecs := [2]*RtVec{NewRtVec(opts, labels), NewAggRtVec(opts, labels)}
+ tags := map[string]string{"app": "dubbo", "version": "1.0.0"}
+ for _, r := range vecs {
+ first := r.With(tags)
+ second := r.With(tags)
+ assert.True(t, first == second) // init once
+ }
+}
+
+func TestRtVecWithConcurrent(t *testing.T) {
+ opts := &RtOpts{
+ Name: "request_num",
+ bucketNum: 10,
+ timeWindowSeconds: 120,
+ Help: "Request cost",
+ }
+ labels := []string{"app", "version"}
+ labelValues := map[string]string{"app": "dubbo", "version": "1.0.0"}
+ vecs := [2]*RtVec{NewRtVec(opts, labels), NewAggRtVec(opts, labels)}
+ for _, r := range vecs {
+ var wg sync.WaitGroup
+ for i := 0; i < 10; i++ {
+ wg.Add(1)
+ go func() {
+ r.With(labelValues).Observe(100)
+ wg.Done()
+ }()
+ }
+ wg.Wait()
+ res := r.With(labelValues).(*Rt).obs.result()
+ assert.True(t, res.Count == uint64(10))
+ }
+}
diff --git a/metrics/registry/collector.go b/metrics/registry/collector.go
index 7479fd2..53a5d71 100644
--- a/metrics/registry/collector.go
+++ b/metrics/registry/collector.go
@@ -18,10 +18,7 @@
package registry
import (
- "time"
-)
-
-import (
+ "dubbo.apache.org/dubbo-go/v3/common"
"dubbo.apache.org/dubbo-go/v3/common/constant"
"dubbo.apache.org/dubbo-go/v3/metrics"
)
@@ -31,15 +28,15 @@
)
func init() {
- metrics.AddCollector("registry", func(m metrics.MetricRegistry, c *metrics.ReporterConfig) {
- rc := ®istryCollector{regRegistry: m}
+ metrics.AddCollector("registry", func(m metrics.MetricRegistry, _ *common.URL) {
+ 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 +60,31 @@
}
}
-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())).Record(float64(event.End.UnixNano()) / float64(time.Second))
- metric := metrics.ComputeIfAbsentCache(dubboNotifyRt, func() interface{} {
- return newTimeMetrics(NotifyRtMillisecondsMin, NotifyRtMillisecondsMax, NotifyRtMillisecondsAvg, NotifyRtMillisecondsSum, NotifyRtMillisecondsLast, metrics.GetApplicationLevel(), rc.regRegistry)
- }).(metrics.TimeMetric)
- metric.Record(event.CostMs())
+ 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 +95,15 @@
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 +113,15 @@
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 02408bd..27ea475 100644
--- a/metrics/registry/metric_set.go
+++ b/metrics/registry/metric_set.go
@@ -40,14 +40,6 @@
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 @@
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")
)
diff --git a/metrics/reporter.go b/metrics/reporter.go
index bf9693b..15ca7e0 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 @@
Path string
PushGatewayAddress string
SummaryMaxAge int64
- Protocol string // MetricsRegistry 扩展配置 ,如:prometheus
+ Protocol string // exporters, like prometheus
}
type ReportMode string
@@ -58,11 +49,8 @@
}
}
-// 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 0000000..dc9fb53
--- /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"
+ "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() {
+ collectorFunc := func(registry metrics.MetricRegistry, c *common.URL) {
+ 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 constant.SideProvider:
+ c.metricSet.provider.qpsTotal.Record(labels)
+ case constant.SideConsumer:
+ c.metricSet.consumer.qpsTotal.Record(labels)
+ }
+}
+
+func (c *rpcCollector) incRequestsTotal(role string, labels map[string]string) {
+ switch role {
+ case constant.SideProvider:
+ c.metricSet.provider.requestsTotal.Inc(labels)
+ c.metricSet.provider.requestsTotalAggregate.Inc(labels)
+ case constant.SideConsumer:
+ 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 constant.SideProvider:
+ c.metricSet.provider.requestsProcessingTotal.Inc(labels)
+ case constant.SideConsumer:
+ c.metricSet.consumer.requestsProcessingTotal.Inc(labels)
+ }
+}
+
+func (c *rpcCollector) decRequestsProcessingTotal(role string, labels map[string]string) {
+ switch role {
+ case constant.SideProvider:
+ c.metricSet.provider.requestsProcessingTotal.Dec(labels)
+ case constant.SideConsumer:
+ c.metricSet.consumer.requestsProcessingTotal.Dec(labels)
+ }
+}
+
+func (c *rpcCollector) incRequestsSucceedTotal(role string, labels map[string]string) {
+ switch role {
+ case constant.SideProvider:
+ c.metricSet.provider.requestsSucceedTotal.Inc(labels)
+ c.metricSet.provider.requestsSucceedTotalAggregate.Inc(labels)
+ case constant.SideConsumer:
+ 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 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 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/event.go b/metrics/rpc/event.go
new file mode 100644
index 0000000..c56ecae
--- /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 0000000..a27d439
--- /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 66%
rename from metrics/prometheus/util.go
rename to metrics/rpc/util.go
index 29e5ebf..e8437bf 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,38 +24,34 @@
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{
- applicationNameKey: url.GetParam(constant.ApplicationKey, ""),
- groupKey: url.Group(),
- hostnameKey: "not implemented yet",
- interfaceKey: url.Service(),
- ipKey: common.GetLocalIp(),
- versionKey: url.GetParam(constant.AppVersionKey, ""),
- methodKey: url.GetParam(constant.MethodKey, ""),
+// buildLabels will build the labels for the rpc metrics
+func buildLabels(url *common.URL, invocation protocol.Invocation) map[string]string {
+ return map[string]string{
+ 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, ""),
}
}
-// 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
+ 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())
diff --git a/metrics/util/aggregate/aggregator.go b/metrics/util/aggregate/aggregator.go
index 0f31f3f..a584cc6 100644
--- a/metrics/util/aggregate/aggregator.go
+++ b/metrics/util/aggregate/aggregator.go
@@ -45,36 +45,49 @@
Max float64
Avg float64
Count uint64
+ Last float64
+}
+
+func NewResult() *Result {
+ return &Result{
+ Min: math.MaxFloat64,
+ Max: math.SmallestNonzeroFloat64,
+ Last: math.NaN(),
+ }
+}
+
+func (r *Result) Update(v float64) {
+ r.Min = math.Min(r.Min, v)
+ r.Max = math.Max(r.Max, v)
+ r.Last = v
+ r.Total += v
+ r.Count++
+}
+
+func (r *Result) Merge(o *Result) {
+ r.Min = math.Min(r.Min, o.Min)
+ r.Max = math.Max(r.Max, o.Max)
+ r.Total += o.Total
+ r.Count += o.Count
+ r.Last = o.Last
+}
+
+func (r *Result) Get() *Result {
+ if r.Count > 0 {
+ r.Avg = r.Total / float64(r.Count)
+ }
+ return r
}
// Result returns the aggregate result of the sliding window by aggregating all panes.
func (t *TimeWindowAggregator) Result() *Result {
t.mux.RLock()
defer t.mux.RUnlock()
-
- res := &Result{}
-
- total := 0.0
- count := uint64(0)
- max := math.SmallestNonzeroFloat64
- min := math.MaxFloat64
-
+ res := NewResult()
for _, v := range t.window.values(time.Now().UnixMilli()) {
- total += v.(*aggregator).total
- count += v.(*aggregator).count
- max = math.Max(max, v.(*aggregator).max)
- min = math.Min(min, v.(*aggregator).min)
+ res.Merge(v.(*Result)) // Last not as expect, but agg result has no Last value
}
-
- if count > 0 {
- res.Avg = total / float64(count)
- res.Count = count
- res.Total = total
- res.Max = max
- res.Min = min
- }
-
- return res
+ return res.Get()
}
// Add adds a value to the sliding window's current pane.
@@ -82,52 +95,9 @@
t.mux.Lock()
defer t.mux.Unlock()
- t.window.currentPane(time.Now().UnixMilli(), t.newEmptyValue).value.(*aggregator).add(v)
+ t.window.currentPane(time.Now().UnixMilli(), t.newEmptyValue).value.(*Result).Update(v)
}
func (t *TimeWindowAggregator) newEmptyValue() interface{} {
- return newAggregator()
-}
-
-// aggregator is a custom struct to aggregate data.
-//
-// It is NOT concurrent-safe.
-// It aggregates data by calculating the min, max, total and count.
-type aggregator struct {
- min float64
- max float64
- total float64
- count uint64
-}
-
-func newAggregator() *aggregator {
- return &aggregator{
- min: math.MaxFloat64,
- max: math.SmallestNonzeroFloat64,
- total: float64(0),
- count: uint64(0),
- }
-}
-
-func (a *aggregator) add(v float64) {
- a.updateMin(v)
- a.updateMax(v)
- a.updateTotal(v)
- a.updateCount()
-}
-
-func (a *aggregator) updateMin(v float64) {
- a.min = math.Min(a.min, v)
-}
-
-func (a *aggregator) updateMax(v float64) {
- a.max = math.Max(a.max, v)
-}
-
-func (a *aggregator) updateTotal(v float64) {
- a.total += v
-}
-
-func (a *aggregator) updateCount() {
- a.count++
+ return NewResult()
}
diff --git a/metrics/util/aggregate/aggregator_test.go b/metrics/util/aggregate/aggregator_test.go
index d3fa4f6..ab661dc 100644
--- a/metrics/util/aggregate/aggregator_test.go
+++ b/metrics/util/aggregate/aggregator_test.go
@@ -48,7 +48,9 @@
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
- if got := timeWindowAggregator.Result(); !reflect.DeepEqual(got, tt.want) {
+ got := timeWindowAggregator.Result()
+ got.Last = 0 // NaN can not equal
+ if !reflect.DeepEqual(got, tt.want) {
t.Errorf("Result() = %v, want %v", got, tt.want)
}
})
diff --git a/otel/trace/exporter.go b/otel/trace/exporter.go
new file mode 100644
index 0000000..454b02a
--- /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 0000000..65a2690
--- /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 0000000..69e2ade
--- /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 0000000..8024c4d
--- /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 0000000..4068872
--- /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
+}
diff --git a/protocol/dubbo3/health/triple_health_v1/health.pb.go b/protocol/dubbo3/health/triple_health_v1/health.pb.go
index e8bc5f9..4997400 100644
--- a/protocol/dubbo3/health/triple_health_v1/health.pb.go
+++ b/protocol/dubbo3/health/triple_health_v1/health.pb.go
@@ -20,23 +20,19 @@
// 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 (
+ protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+ protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
)
-import (
- protoreflect "google.golang.org/protobuf/reflect/protoreflect"
-
- protoimpl "google.golang.org/protobuf/runtime/protoimpl"
-)
-
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
@@ -80,11 +76,11 @@
}
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 @@
// 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 @@
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 (*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 @@
// 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 @@
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 (*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 @@
// 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 @@
return HealthCheckResponse_UNKNOWN
}
-var File_protocol_dubbo3_health_triple_health_v1_health_proto protoreflect.FileDescriptor
+var File_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_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 @@
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 @@
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 @@
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 ae55348..b636b80 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 a63d394..00633cc 100644
--- a/protocol/dubbo3/health/triple_health_v1/health_triple.pb.go
+++ b/protocol/dubbo3/health/triple_health_v1/health_triple.pb.go
@@ -18,32 +18,25 @@
// 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"
- 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"
+ fmt "fmt"
+ 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"
)
// This is a compile-time assertion to ensure that this generated file
@@ -89,7 +82,7 @@
}
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 @@
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 @@
// 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 @@
ServerStreams: true,
},
},
- Metadata: "protocol/dubbo3/health/triple_health_v1/health.proto",
+ Metadata: "health.proto",
}
diff --git a/registry/nacos/listener.go b/registry/nacos/listener.go
index a8e8f96..5201b2d 100644
--- a/registry/nacos/listener.go
+++ b/registry/nacos/listener.go
@@ -75,6 +75,20 @@
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 @@
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 bfb4575..42f1730 100644
--- a/registry/nacos/registry.go
+++ b/registry/nacos/registry.go
@@ -169,35 +169,94 @@
if role != common.CONSUMER {
return nil
}
-
- for {
- if !nr.IsAvailable() {
- logger.Warnf("event listener game over.")
- return perrors.New("nacosRegistry is not available.")
- }
-
- listener, err := nr.subscribe(url)
- defer metrics.Publish(metricsRegistry.NewSubscribeEvent(err == nil))
- if err != nil {
+ serviceName := getServiceName(url)
+ if serviceName == "*" {
+ // Subscribe to all services
+ 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()
+ services, err := nr.getAllSubscribeServiceNames()
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("getAllServices() = 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)
+
+ 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 perrors.New("nacosRegistry is not available.")
+ }
+
+ listener, err := nr.subscribe(url)
+ metrics.Publish(metricsRegistry.NewSubscribeEvent(err == nil))
+ if err != nil {
+ 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
+ }
+ 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)
}
}
@@ -256,6 +315,26 @@
}
}
+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
diff --git a/registry/servicediscovery/service_instances_changed_listener_impl.go b/registry/servicediscovery/service_instances_changed_listener_impl.go
index a0039bd..de2667b 100644
--- a/registry/servicediscovery/service_instances_changed_listener_impl.go
+++ b/registry/servicediscovery/service_instances_changed_listener_impl.go
@@ -18,7 +18,10 @@
package servicediscovery
import (
+ "encoding/gob"
"reflect"
+ "sync"
+ "time"
)
import (
@@ -31,10 +34,27 @@
"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"
)
+var (
+ metaCache *store.CacheManager
+ cacheOnce sync.Once
+)
+
+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)
+ }
+ metaCache = cache
+}
+
// ServiceInstancesChangedListenerImpl The Service Discovery Changed Event Listener
type ServiceInstancesChangedListenerImpl struct {
serviceNames *gxset.HashSet
@@ -45,6 +65,7 @@
}
func NewServiceInstancesChangedListener(services *gxset.HashSet) registry.ServiceInstancesChangedListener {
+ cacheOnce.Do(initCache)
return &ServiceInstancesChangedListenerImpl{
serviceNames: services,
listeners: make(map[string]registry.NotifyListener),
@@ -88,9 +109,14 @@
revisionToInstances[revision] = append(subInstances, instance)
metadataInfo := lstn.revisionToMetadata[revision]
if metadataInfo == nil {
- metadataInfo, err = GetMetadataInfo(instance, revision)
- if err != nil {
- return err
+ if val, ok := metaCache.Get(revision); ok {
+ metadataInfo = val.(*common.MetadataInfo)
+ } else {
+ metadataInfo, err = GetMetadataInfo(instance, revision)
+ if err != nil {
+ return err
+ }
+ metaCache.Set(revision, metadataInfo)
}
}
instance.SetServiceMetadata(metadataInfo)
@@ -104,6 +130,9 @@
newRevisionToMetadata[revision] = metadataInfo
}
lstn.revisionToMetadata = newRevisionToMetadata
+ for revision, metadataInfo := range newRevisionToMetadata {
+ metaCache.Set(revision, metadataInfo)
+ }
for serviceInfo, revisions := range localServiceToRevisions {
revisionsToUrls := protocolRevisionsToUrls[serviceInfo.Protocol]
@@ -187,6 +216,11 @@
// GetMetadataInfo get metadata info when MetadataStorageTypePropertyName is null
func GetMetadataInfo(instance registry.ServiceInstance, revision string) (*common.MetadataInfo, error) {
+ cacheOnce.Do(initCache)
+ if metadataInfo, ok := metaCache.Get(revision); ok {
+ return metadataInfo.(*common.MetadataInfo), nil
+ }
+
var metadataStorageType string
var metadataInfo *common.MetadataInfo
if instance.GetMetadata() == nil {
@@ -212,5 +246,8 @@
return nil, err
}
}
+
+ metaCache.Set(revision, metadataInfo)
+
return metadataInfo, nil
}
diff --git a/registry/servicediscovery/store/cache_manager.go b/registry/servicediscovery/store/cache_manager.go
new file mode 100644
index 0000000..7228bc2
--- /dev/null
+++ b/registry/servicediscovery/store/cache_manager.go
@@ -0,0 +1,198 @@
+/*
+ * 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 store
+
+import (
+ "encoding/gob"
+ "os"
+ "sync"
+ "time"
+)
+
+import (
+ "github.com/dubbogo/gost/log/logger"
+
+ "github.com/hashicorp/golang-lru"
+)
+
+type CacheManager struct {
+ name string // The name of the cache manager
+ cacheFile string // The file path where the cache is stored
+ dumpInterval time.Duration // The duration after which the cache dump
+ stop chan struct{} // Channel used to stop the cache expiration routine
+ cache *lru.Cache // The LRU cache implementation
+ lock sync.Mutex
+ enableDump bool
+}
+
+type Item struct {
+ Key string
+ Value interface{}
+}
+
+// NewCacheManager creates a new CacheManager instance.
+// It initializes the cache manager with the provided parameters and starts a routine for cache dumping.
+func NewCacheManager(name, cacheFile string, dumpInterval time.Duration, maxCacheSize int, enableDump bool) (*CacheManager, error) {
+ cm := &CacheManager{
+ name: name,
+ cacheFile: cacheFile,
+ dumpInterval: dumpInterval,
+ stop: make(chan struct{}),
+ enableDump: enableDump,
+ }
+ cache, err := lru.New(maxCacheSize)
+ if err != nil {
+ return nil, err
+ }
+ cm.cache = cache
+
+ // Check if the cache file exists and load the cache if it does
+ if _, err := os.Stat(cacheFile); err == nil {
+ if err = cm.loadCache(); err != nil {
+ logger.Warnf("Failed to load the cache file:[%s].The err is %v", cm.cacheFile, err)
+ }
+ }
+
+ if enableDump {
+ cm.runDumpTask()
+ }
+
+ return cm, nil
+}
+
+// Get retrieves the value associated with the given key from the cache.
+func (cm *CacheManager) Get(key string) (interface{}, bool) {
+ return cm.cache.Get(key)
+}
+
+// Set sets the value associated with the given key in the cache.
+func (cm *CacheManager) Set(key string, value interface{}) {
+ cm.cache.Add(key, value)
+}
+
+// Delete removes the value associated with the given key from the cache.
+func (cm *CacheManager) Delete(key string) {
+ cm.cache.Remove(key)
+}
+
+// GetAll returns all the key-value pairs in the cache.
+func (cm *CacheManager) GetAll() map[string]interface{} {
+ keys := cm.cache.Keys()
+
+ result := make(map[string]interface{})
+ for _, k := range keys {
+ result[k.(string)], _ = cm.cache.Get(k)
+ }
+
+ return result
+}
+
+// loadCache loads the cache from the cache file.
+func (cm *CacheManager) loadCache() error {
+ cf, err := os.Open(cm.cacheFile)
+ if err != nil {
+ return err
+ }
+
+ decoder := gob.NewDecoder(cf)
+ for {
+ var it Item
+ err = decoder.Decode(&it)
+ if err != nil {
+ if err.Error() == "EOF" {
+ break // Reached end of file
+ }
+ return err
+ }
+ // Add the loaded keys to the front of the LRU list
+ cm.cache.Add(it.Key, it.Value)
+ }
+
+ return cf.Close()
+}
+
+// dumpCache dumps the cache to the cache file.
+func (cm *CacheManager) dumpCache() error {
+
+ cm.lock.Lock()
+ defer cm.lock.Unlock()
+
+ items := cm.GetAll()
+
+ file, err := os.Create(cm.cacheFile)
+ if err != nil {
+ return err
+ }
+ defer file.Close()
+
+ encoder := gob.NewEncoder(file)
+ for k, v := range items {
+ gob.Register(v)
+ err = encoder.Encode(&Item{
+ Key: k,
+ Value: v,
+ })
+ if err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+func (cm *CacheManager) runDumpTask() {
+ go func() {
+ ticker := time.NewTicker(cm.dumpInterval)
+ for {
+ select {
+ case <-ticker.C:
+ // Dump the cache to the file
+ if err := cm.dumpCache(); err != nil {
+ // Handle error
+ logger.Warnf("Failed to dump cache,the err is %v", err)
+ } else {
+ logger.Infof("Dumping [%s] caches, latest entries %d", cm.name, cm.cache.Len())
+ }
+ case <-cm.stop:
+ ticker.Stop()
+ return
+ }
+ }
+ }()
+}
+
+func (cm *CacheManager) StopDump() {
+ cm.lock.Lock()
+ defer cm.lock.Unlock()
+ if cm.enableDump {
+ cm.stop <- struct{}{} // Stop the cache dump routine
+ cm.enableDump = false
+ }
+}
+
+// destroy stops the cache dump routine, clears the cache and removes the cache file.
+func (cm *CacheManager) destroy() {
+ cm.StopDump() // Stop the cache dump routine
+ cm.cache.Purge() // Clear the cache
+
+ // Delete the cache file if it exists
+ if _, err := os.Stat(cm.cacheFile); err == nil {
+ if err := os.Remove(cm.cacheFile); err == nil {
+ logger.Infof("The cacheFile [%s] was cleared", cm.cacheFile)
+ }
+ }
+}
diff --git a/registry/servicediscovery/store/cache_manager_test.go b/registry/servicediscovery/store/cache_manager_test.go
new file mode 100644
index 0000000..3ca24dc
--- /dev/null
+++ b/registry/servicediscovery/store/cache_manager_test.go
@@ -0,0 +1,152 @@
+/*
+ * 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 store
+
+import (
+ "testing"
+ "time"
+)
+
+import (
+ "dubbo.apache.org/dubbo-go/v3/common"
+)
+
+var defaultTime = time.Second * 3
+
+func TestCacheManager(t *testing.T) {
+ cm, err := NewCacheManager("test", "test_cache", defaultTime, 10, true)
+ if err != nil {
+ t.Fatalf("failed to create cache manager: %v", err)
+ }
+
+ // Test Set and Get
+ cm.Set("key1", "value1")
+ cm.Set("key2", "value2")
+ value, ok := cm.Get("key1")
+ if !ok {
+ t.Errorf("failed to get key1: %v", err)
+ }
+ if value != "value1" {
+ t.Errorf("unexpected Value for key1: got %v, want %v", value, "value1")
+ }
+
+ // Test Delete
+ cm.Delete("key2")
+ _, ok = cm.Get("key2")
+ if ok {
+ t.Errorf("key2 was not removed from cache")
+ }
+
+ // Test GetAll
+ cm.Set("key3", "value3")
+ all := cm.GetAll()
+ if len(all) != 2 {
+ t.Errorf("unexpected number of items in cache: got %d, want %d", len(all), 2)
+ }
+
+ // Test cache file creation and loading
+ cm2, err := NewCacheManager("test2", "nonexistent_cache", defaultTime, 10, true)
+ if err != nil {
+ t.Fatalf("failed to create cache manager: %v", err)
+ }
+ cm2.Set("key4", "value4")
+ time.Sleep(time.Second * 4)
+ cm2.StopDump()
+ cm3, err := NewCacheManager("test3", "nonexistent_cache", defaultTime, 10, true)
+ if err != nil {
+ t.Fatalf("failed to create cache manager: %v", err)
+ }
+ all3 := cm3.GetAll()
+ if len(all3) != 1 {
+ t.Errorf("unexpected number of items in cache: got %d, want %d", len(all3), 1)
+ }
+ _, ok = cm3.Get("key4")
+ if !ok {
+ t.Errorf("failed to get key4: %v", err)
+ }
+ cm3.destroy()
+ cm2.destroy()
+ cm.destroy() // clear cache file
+}
+
+func TestMetaInfoCacheManager(t *testing.T) {
+
+ serverInfo := make(map[string]*common.ServiceInfo)
+ serverInfo["1"] = common.NewServiceInfo("1", "1", "1", "1", "1", make(map[string]string))
+ serverInfo["2"] = common.NewServiceInfo("2", "2", "2", "2", "2", make(map[string]string))
+ serverInfo["3"] = common.NewServiceInfo("3", "3", "3", "3", "3", make(map[string]string))
+
+ metadataInfo1 := common.NewMetadataInfo("1", "1", serverInfo)
+ metadataInfo2 := common.NewMetadataInfo("2", "2", serverInfo)
+ metadataInfo3 := common.NewMetadataInfo("3", "3", serverInfo)
+ metadataInfo4 := common.NewMetadataInfo("4", "4", serverInfo)
+
+ cm, err := NewCacheManager("metaTest1", "test_meta_cache", defaultTime, 10, true)
+ if err != nil {
+ t.Fatalf("failed to create cache manager: %v", err)
+ }
+
+ // Test Set and Get
+ cm.Set("key1", metadataInfo1)
+ cm.Set("key2", metadataInfo2)
+ value, ok := cm.Get("key1")
+ if !ok {
+ t.Errorf("failed to get key1: %v", err)
+ }
+ if value != metadataInfo1 {
+ t.Errorf("unexpected Value for key1: got %v, want %v", value, "value1")
+ }
+
+ // Test Delete
+ cm.Delete("key2")
+ _, ok = cm.Get("key2")
+ if ok {
+ t.Errorf("key2 was not removed from cache")
+ }
+
+ // Test GetAll
+ cm.Set("key3", metadataInfo3)
+ all := cm.GetAll()
+ if len(all) != 2 {
+ t.Errorf("unexpected number of items in cache: got %d, want %d", len(all), 2)
+ }
+
+ // Test cache file creation and loading
+ cm2, err := NewCacheManager("metaTest2", "nonexistent_meta_cache", defaultTime, 10, true)
+ if err != nil {
+ t.Fatalf("failed to create cache manager: %v", err)
+ }
+ cm2.Set("key4", metadataInfo4)
+ time.Sleep(time.Second * 4)
+ cm2.StopDump()
+ cm3, err := NewCacheManager("test3", "nonexistent_meta_cache", defaultTime, 10, true)
+ if err != nil {
+ t.Fatalf("failed to create cache manager: %v", err)
+ }
+ all3 := cm3.GetAll()
+ if len(all3) != 1 {
+ t.Errorf("unexpected number of items in cache: got %d, want %d", len(all3), 1)
+ }
+ _, ok = cm3.Get("key4")
+ if !ok {
+ t.Errorf("failed to get key4: %v", err)
+ }
+ cm3.destroy()
+ cm2.destroy()
+ cm.destroy() // clear cache file
+}