You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dubbo.apache.org by la...@apache.org on 2021/10/26 14:04:42 UTC

[dubbo-go] 01/01: fix: add metrics basic support

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

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

commit ddda316ac356c0f2934fc16a5d3fd85a338d7e23
Author: LaurenceLiZhixin <38...@qq.com>
AuthorDate: Tue Oct 26 22:04:27 2021 +0800

    fix: add metrics basic support
---
 common/extension/metrics.go         |  8 ++--
 common/extension/metrics_test.go    |  4 +-
 config/metric_config.go             | 88 +++++++++++++++++-----------------
 filter/metrics/filter.go            |  2 +-
 filter/metrics/filter_test.go       |  4 +-
 go.mod                              |  3 +-
 go.sum                              | 12 +++++
 metrics/prometheus/reporter.go      | 94 ++++++++++++++++++++-----------------
 metrics/prometheus/reporter_test.go |  3 +-
 metrics/reporter.go                 | 25 +++++++++-
 10 files changed, 139 insertions(+), 104 deletions(-)

diff --git a/common/extension/metrics.go b/common/extension/metrics.go
index 107c65c..639d921 100644
--- a/common/extension/metrics.go
+++ b/common/extension/metrics.go
@@ -23,20 +23,20 @@ import (
 
 // 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() metrics.Reporter, 4)
+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() metrics.Reporter) {
+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) metrics.Reporter {
+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()
+	return reporterFunc(config)
 }
diff --git a/common/extension/metrics_test.go b/common/extension/metrics_test.go
index be6e21c..c4cdc41 100644
--- a/common/extension/metrics_test.go
+++ b/common/extension/metrics_test.go
@@ -35,10 +35,10 @@ import (
 func TestGetMetricReporter(t *testing.T) {
 	reporter := &mockReporter{}
 	name := "mock"
-	SetMetricReporter(name, func() metrics.Reporter {
+	SetMetricReporter(name, func(config *metrics.ReporterConfig) metrics.Reporter {
 		return reporter
 	})
-	res := GetMetricReporter(name)
+	res := GetMetricReporter(name, metrics.NewReporterConfig())
 	assert.Equal(t, reporter, res)
 }
 
diff --git a/config/metric_config.go b/config/metric_config.go
index 64f6b2d..458485c 100644
--- a/config/metric_config.go
+++ b/config/metric_config.go
@@ -17,27 +17,56 @@
 
 package config
 
-var defaultHistogramBucket = []float64{10, 50, 100, 200, 500, 1000, 10000}
+import (
+	"github.com/creasty/defaults"
+
+	"github.com/pkg/errors"
+)
+
+import (
+	"dubbo.apache.org/dubbo-go/v3/common/extension"
+	"dubbo.apache.org/dubbo-go/v3/metrics"
+)
 
 // MetricConfig This is the config struct for all metrics implementation
 type MetricConfig struct {
-	Reporters []string `yaml:"reporters" json:"reporters,omitempty"`
-	// TODO s?
-	HistogramBucket []float64 `yaml:"histogram_bucket" json:"histogram_bucket,omitempty"`
+	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             string `default:"true" 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"`
 }
 
-// nolint
-func (mc *MetricConfig) Init() error {
-	return nil
+func (m *MetricConfig) ToReporterConfig() *metrics.ReporterConfig {
+	defaultMetricsReportConfig := metrics.NewReporterConfig()
+	if m.Mode == metrics.ReportModePush {
+		defaultMetricsReportConfig.Mode = metrics.ReportModePush
+	}
+	if m.Namespace != "" {
+		defaultMetricsReportConfig.Namespace = m.Namespace
+	}
+
+	defaultMetricsReportConfig.Enable = m.Enable == "1"
+	defaultMetricsReportConfig.Port = m.Port
+	defaultMetricsReportConfig.Path = m.Path
+	defaultMetricsReportConfig.PushGatewayAddress = m.PushGatewayAddress
+	return defaultMetricsReportConfig
 }
 
-// GetHistogramBucket find the histogram bucket
-// if it's empty, the default value will be return
-func (mc *MetricConfig) GetHistogramBucket() []float64 {
-	if len(mc.HistogramBucket) == 0 {
-		mc.HistogramBucket = defaultHistogramBucket
+// nolint
+func (mc *MetricConfig) Init() error {
+	if mc == nil {
+		return errors.New("metrics config is null")
+	}
+	if err := defaults.Set(mc); err != nil {
+		return err
 	}
-	return mc.HistogramBucket
+	if err := verify(mc); err != nil {
+		return err
+	}
+	extension.GetMetricReporter("prometheus", mc.ToReporterConfig())
+	return nil
 }
 
 type MetricConfigBuilder struct {
@@ -50,39 +79,6 @@ func NewMetricConfigBuilder() *MetricConfigBuilder {
 }
 
 // nolint
-func (mcb *MetricConfigBuilder) SetReporters(reporters []string) *MetricConfigBuilder {
-	mcb.metricConfig.Reporters = reporters
-	return mcb
-}
-
-// nolint
-func (mcb *MetricConfigBuilder) AddReporter(reporter string) *MetricConfigBuilder {
-	if mcb.metricConfig.Reporters == nil {
-		mcb.metricConfig.Reporters = make([]string, 0)
-	}
-	mcb.metricConfig.Reporters = append(mcb.metricConfig.Reporters, reporter)
-	return mcb
-}
-
-// nolint
-func (mcb *MetricConfigBuilder) SetHistogramBucket(histogramBucket []float64) *MetricConfigBuilder {
-	mcb.metricConfig.HistogramBucket = histogramBucket
-	return mcb
-}
-
-// nolint
-func (mcb *MetricConfigBuilder) AddBucket(bucket float64) *MetricConfigBuilder {
-	if mcb.metricConfig.HistogramBucket == nil {
-		mcb.metricConfig.HistogramBucket = make([]float64, 0)
-	}
-	mcb.metricConfig.HistogramBucket = append(mcb.metricConfig.HistogramBucket, bucket)
-	return mcb
-}
-
-// nolint
 func (mcb *MetricConfigBuilder) Build() *MetricConfig {
-	if err := mcb.metricConfig.Init(); err != nil {
-		panic(err)
-	}
 	return mcb.metricConfig
 }
diff --git a/filter/metrics/filter.go b/filter/metrics/filter.go
index 7b29305..8f31c2b 100644
--- a/filter/metrics/filter.go
+++ b/filter/metrics/filter.go
@@ -74,7 +74,7 @@ func (p *Filter) OnResponse(ctx context.Context, res protocol.Result, invoker pr
 func newFilter() filter.Filter {
 	if metricFilterInstance == nil {
 		reporters := make([]metrics.Reporter, 0, 1)
-		reporters = append(reporters, extension.GetMetricReporter("prometheus"))
+		reporters = append(reporters, extension.GetMetricReporter("prometheus", metrics.NewReporterConfig()))
 		metricFilterInstance = &Filter{
 			reporters: reporters,
 		}
diff --git a/filter/metrics/filter_test.go b/filter/metrics/filter_test.go
index 11e19d3..5b7b6cd 100644
--- a/filter/metrics/filter_test.go
+++ b/filter/metrics/filter_test.go
@@ -32,7 +32,6 @@ import (
 import (
 	"dubbo.apache.org/dubbo-go/v3/common"
 	"dubbo.apache.org/dubbo-go/v3/common/extension"
-	"dubbo.apache.org/dubbo-go/v3/config"
 	"dubbo.apache.org/dubbo-go/v3/metrics"
 	_ "dubbo.apache.org/dubbo-go/v3/metrics/prometheus"
 	"dubbo.apache.org/dubbo-go/v3/protocol"
@@ -41,9 +40,8 @@ import (
 
 func TestMetricsFilterInvoke(t *testing.T) {
 	// prepare the mock reporter
-	config.GetMetricConfig().Reporters = []string{"mock"}
 	mk := &mockReporter{}
-	extension.SetMetricReporter("mock", func() metrics.Reporter {
+	extension.SetMetricReporter("mock", func(config *metrics.ReporterConfig) metrics.Reporter {
 		return mk
 	})
 
diff --git a/go.mod b/go.mod
index 3804e96..abd0813 100644
--- a/go.mod
+++ b/go.mod
@@ -3,6 +3,7 @@ module dubbo.apache.org/dubbo-go/v3
 go 1.15
 
 require (
+	contrib.go.opencensus.io/exporter/prometheus v0.4.0
 	github.com/RoaringBitmap/roaring v0.7.1
 	github.com/Workiva/go-datastructures v1.0.52
 	github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5
@@ -19,7 +20,6 @@ require (
 	github.com/go-co-op/gocron v1.9.0
 	github.com/go-playground/validator/v10 v10.9.0
 	github.com/go-resty/resty/v2 v2.3.0
-	github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
 	github.com/golang/mock v1.4.4
 	github.com/golang/protobuf v1.5.2
 	github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645
@@ -34,7 +34,6 @@ require (
 	github.com/opentracing/opentracing-go v1.2.0
 	github.com/pkg/errors v0.9.1
 	github.com/prometheus/client_golang v1.11.0
-	github.com/prometheus/common v0.28.0 // indirect
 	github.com/satori/go.uuid v1.2.1-0.20181028125025-b2ce2384e17b
 	github.com/stretchr/testify v1.7.0
 	github.com/zouyx/agollo/v3 v3.4.5
diff --git a/go.sum b/go.sum
index 98295ab..4e1e73e 100644
--- a/go.sum
+++ b/go.sum
@@ -32,6 +32,8 @@ cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0Zeo
 cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
 cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
 cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
+contrib.go.opencensus.io/exporter/prometheus v0.4.0 h1:0QfIkj9z/iVZgK31D9H9ohjjIDApI2GOPScCKwxedbs=
+contrib.go.opencensus.io/exporter/prometheus v0.4.0/go.mod h1:o7cosnyfuPVK0tB8q0QmaQNhGnptITnPQB+z1+qeFB0=
 dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
 github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
 github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI=
@@ -240,12 +242,14 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2
 github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
 github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
 github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o=
+github.com/go-kit/log v0.1.0 h1:DGJh0Sm43HbOeYDNnVZFl8BvcYVvjD5bqYJvp0REbwQ=
 github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
 github.com/go-ldap/ldap v3.0.2+incompatible/go.mod h1:qfd9rJvER9Q0/D/Sqn1DfHRoBp40uXYvFoEVrNEPqRc=
 github.com/go-ldap/ldap/v3 v3.1.3/go.mod h1:3rbOH3jRS2u6jg2rJnKAMLE/xQyCKIveG2Sa/Cohzb8=
 github.com/go-ldap/ldap/v3 v3.1.10/go.mod h1:5Zun81jBTabRaI8lzN7E1JjyEl1g6zI6u9pd8luAK4Q=
 github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
 github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
+github.com/go-logfmt/logfmt v0.5.0 h1:TrB8swr/68K7m9CcGut2g3UOihhbcbiMAYiuTXdEih4=
 github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
 github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
 github.com/go-ole/go-ole v1.2.4 h1:nNBDSCOigTSiarFpYE9J/KtEA1IOW4CNeqT9TQDqCxI=
@@ -266,6 +270,7 @@ github.com/go-resty/resty/v2 v2.3.0 h1:JOOeAvjSlapTT92p8xiS19Zxev1neGikoHsXJeOq8
 github.com/go-resty/resty/v2 v2.3.0/go.mod h1:UpN9CgLZNsv4e9XG50UU8xdI0F43UQ4HmxLBDwaroHU=
 github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
 github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
+github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
 github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
 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=
@@ -328,6 +333,7 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
 github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
 github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
@@ -665,6 +671,8 @@ github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4O
 github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
 github.com/prometheus/procfs v0.6.0 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4=
 github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
+github.com/prometheus/statsd_exporter v0.21.0 h1:hA05Q5RFeIjgwKIYEdFd59xu5Wwaznf33yKI+pyX6T8=
+github.com/prometheus/statsd_exporter v0.21.0/go.mod h1:rbT83sZq2V+p73lHhPZfMc3MLCHmSHelCh9hSGYNLTQ=
 github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
 github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
 github.com/rhnvrm/simples3 v0.6.1/go.mod h1:Y+3vYm2V7Y4VijFoJHHTrja6OgPrJ2cBti8dPGkC3sA=
@@ -799,6 +807,8 @@ go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
 go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
 go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
 go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
+go.opencensus.io v0.23.0 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M=
+go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
 go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
 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=
@@ -912,6 +922,7 @@ golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81R
 golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
 golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
 golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
+golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
 golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
 golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
 golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
@@ -1168,6 +1179,7 @@ google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM
 google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
 google.golang.org/grpc v1.32.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
 google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
+google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
 google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
 google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
 google.golang.org/grpc v1.41.0 h1:f+PlOh7QV4iIJkPrx5NQ7qaNGFQ3OTse67yaDHfju4E=
diff --git a/metrics/prometheus/reporter.go b/metrics/prometheus/reporter.go
index 295d018..55d1bd6 100644
--- a/metrics/prometheus/reporter.go
+++ b/metrics/prometheus/reporter.go
@@ -19,6 +19,7 @@ package prometheus
 
 import (
 	"context"
+	"net/http"
 	"strconv"
 	"strings"
 	"sync"
@@ -26,6 +27,8 @@ import (
 )
 
 import (
+	ocprom "contrib.go.opencensus.io/exporter/prometheus"
+
 	"github.com/prometheus/client_golang/prometheus"
 	prom "github.com/prometheus/client_golang/prometheus"
 )
@@ -35,7 +38,6 @@ import (
 	"dubbo.apache.org/dubbo-go/v3/common/constant"
 	"dubbo.apache.org/dubbo-go/v3/common/extension"
 	"dubbo.apache.org/dubbo-go/v3/common/logger"
-	"dubbo.apache.org/dubbo-go/v3/config"
 	"dubbo.apache.org/dubbo-go/v3/metrics"
 	"dubbo.apache.org/dubbo-go/v3/protocol"
 )
@@ -60,7 +62,6 @@ const (
 
 var (
 	labelNames             = []string{serviceKey, groupKey, versionKey, methodKey, timeoutKey}
-	namespace              = config.GetApplicationConfig().Name
 	reporterInstance       *PrometheusReporter
 	reporterInitOnce       sync.Once
 	defaultHistogramBucket = []float64{10, 50, 100, 200, 500, 1000, 10000}
@@ -91,6 +92,8 @@ type PrometheusReporter struct {
 	userCounterVec sync.Map
 	userGaugeVec   sync.Map
 	userSummaryVec sync.Map
+
+	namespace string
 }
 
 // Report reports the duration to Prometheus
@@ -124,59 +127,62 @@ func (reporter *PrometheusReporter) Report(ctx context.Context, invoker protocol
 	hisVec.With(labels).Observe(costMs)
 }
 
-func newHistogramVec(name string, labels []string) *prometheus.HistogramVec {
+func newHistogramVec(name, namespace string, labels []string) *prometheus.HistogramVec {
 	return prometheus.NewHistogramVec(
 		prometheus.HistogramOpts{
 			Namespace: namespace,
 			Name:      name,
-			Help:      "This is the dubbo's histogram metrics",
 			Buckets:   defaultHistogramBucket,
 		},
 		labels)
 }
 
-func newCounter(name string) prometheus.Counter {
+func newCounter(name, namespace string) prometheus.Counter {
 	return prometheus.NewCounter(
 		prometheus.CounterOpts{
-			Name: name,
+			Namespace: namespace,
+			Name:      name,
 		})
 }
 
-func newCounterVec(name string, labels []string) *prometheus.CounterVec {
+func newCounterVec(name, namespace string, labels []string) *prometheus.CounterVec {
 	return prometheus.NewCounterVec(
 		prometheus.CounterOpts{
-			Name: name,
+			Name:      name,
+			Namespace: namespace,
 		}, labels)
 }
 
-func newGauge(name string) prometheus.Gauge {
+func newGauge(name, namespace string) prometheus.Gauge {
 	return prometheus.NewGauge(
 		prometheus.GaugeOpts{
-			Name: name,
+			Name:      name,
+			Namespace: namespace,
 		})
 }
 
-func newGaugeVec(name string, labels []string) *prometheus.GaugeVec {
+func newGaugeVec(name, namespace string, labels []string) *prometheus.GaugeVec {
 	return prometheus.NewGaugeVec(
 		prometheus.GaugeOpts{
-			Name: name,
+			Name:      name,
+			Namespace: namespace,
 		}, labels)
 }
 
-func newSummary(name string) prometheus.Summary {
+func newSummary(name, namespace string) prometheus.Summary {
 	return prometheus.NewSummary(
 		prometheus.SummaryOpts{
-			Name: name,
+			Name:      name,
+			Namespace: namespace,
 		})
 }
 
 // newSummaryVec create SummaryVec, the Namespace is dubbo
 // the objectives is from my experience.
-func newSummaryVec(name string, labels []string) *prometheus.SummaryVec {
+func newSummaryVec(name, namespace string, labels []string) *prometheus.SummaryVec {
 	return prometheus.NewSummaryVec(
 		prometheus.SummaryOpts{
 			Namespace: namespace,
-			Help:      "This is the dubbo's summary metrics",
 			Name:      name,
 			Objectives: map[float64]float64{
 				0.5:   0.01,
@@ -205,34 +211,34 @@ func isConsumer(url *common.URL) bool {
 
 // newPrometheusReporter create new prometheusReporter
 // it will register the metrics into prometheus
-func newPrometheusReporter() metrics.Reporter {
+func newPrometheusReporter(reporterConfig *metrics.ReporterConfig) metrics.Reporter {
 	if reporterInstance == nil {
 		reporterInitOnce.Do(func() {
 			reporterInstance = &PrometheusReporter{
-				consumerSummaryVec: newSummaryVec(consumerPrefix+serviceKey+summarySuffix, labelNames),
-				providerSummaryVec: newSummaryVec(providerPrefix+serviceKey+summarySuffix, labelNames),
-
-				consumerHistogramVec: newHistogramVec(consumerPrefix+serviceKey+histogramSuffix, labelNames),
-				providerHistogramVec: newHistogramVec(providerPrefix+serviceKey+histogramSuffix, labelNames),
+				consumerSummaryVec:   newSummaryVec(consumerPrefix+serviceKey+summarySuffix, reporterConfig.Namespace, labelNames),
+				providerSummaryVec:   newSummaryVec(providerPrefix+serviceKey+summarySuffix, reporterConfig.Namespace, labelNames),
+				namespace:            reporterConfig.Namespace,
+				consumerHistogramVec: newHistogramVec(consumerPrefix+serviceKey+histogramSuffix, reporterConfig.Namespace, labelNames),
+				providerHistogramVec: newHistogramVec(providerPrefix+serviceKey+histogramSuffix, reporterConfig.Namespace, labelNames),
 			}
 
 			prom.DefaultRegisterer.MustRegister(reporterInstance.consumerSummaryVec, reporterInstance.providerSummaryVec,
 				reporterInstance.consumerHistogramVec, reporterInstance.providerHistogramVec)
-			// todo open prometheus metrics service
-			//metricsExporter, err := ocprom.NewExporter(ocprom.Options{
-			//	Registry: prom.DefaultRegisterer.(*prom.Registry),
-			//})
-			//if err != nil {
-			//	logger.Errorf("new prometheus reporter with error = %s", err)
-			//	return
-			//}
-			//go func() {
-			//	mux := http.NewServeMux()
-			//	mux.Handle("/metrics", metricsExporter)
-			//	if err := http.ListenAndServe(":9090", mux); err != nil {
-			//		logger.Errorf("new prometheus reporter with error = %s", err)
-			//	}
-			//}()
+
+			metricsExporter, err := ocprom.NewExporter(ocprom.Options{
+				Registry: prom.DefaultRegisterer.(*prom.Registry),
+			})
+			if err != nil {
+				logger.Errorf("new prometheus reporter with error = %s", err)
+				return
+			}
+			go func() {
+				mux := http.NewServeMux()
+				mux.Handle(reporterConfig.Path, metricsExporter)
+				if err := http.ListenAndServe(":"+reporterConfig.Port, mux); err != nil {
+					logger.Errorf("new prometheus reporter with error = %s", err)
+				}
+			}()
 		})
 	}
 	return reporterInstance
@@ -244,7 +250,7 @@ func (reporter *PrometheusReporter) setGauge(gaugeName string, toSetValue float6
 	if len(labelMap) == 0 {
 		// gauge
 		if val, exist := reporter.userGauge.Load(gaugeName); !exist {
-			newGauge := newGauge(gaugeName)
+			newGauge := newGauge(gaugeName, reporter.namespace)
 			_ = prom.DefaultRegisterer.Register(newGauge)
 
 			reporter.userGauge.Store(gaugeName, newGauge)
@@ -261,7 +267,7 @@ func (reporter *PrometheusReporter) setGauge(gaugeName string, toSetValue float6
 		for k, _ := range labelMap {
 			keyList = append(keyList, k)
 		}
-		newGaugeVec := newGaugeVec(gaugeName, keyList)
+		newGaugeVec := newGaugeVec(gaugeName, reporter.namespace, keyList)
 		_ = prom.DefaultRegisterer.Register(newGaugeVec)
 		reporter.userGaugeVec.Store(gaugeName, newGaugeVec)
 		newGaugeVec.With(labelMap).Set(toSetValue)
@@ -276,7 +282,7 @@ func (reporter *PrometheusReporter) incCounter(counterName string, labelMap prom
 	if len(labelMap) == 0 {
 		// counter
 		if val, exist := reporter.userCounter.Load(counterName); !exist {
-			newCounter := newCounter(counterName)
+			newCounter := newCounter(counterName, reporter.namespace)
 			_ = prom.DefaultRegisterer.Register(newCounter)
 			reporter.userCounter.Store(counterName, newCounter)
 			newCounter.Inc()
@@ -292,9 +298,9 @@ func (reporter *PrometheusReporter) incCounter(counterName string, labelMap prom
 		for k, _ := range labelMap {
 			keyList = append(keyList, k)
 		}
-		newCounterVec := newCounterVec(counterName, keyList)
+		newCounterVec := newCounterVec(counterName, reporter.namespace, keyList)
 		_ = prom.DefaultRegisterer.Register(newCounterVec)
-		reporter.userSummaryVec.Store(counterName, newCounterVec)
+		reporter.userCounterVec.Store(counterName, newCounterVec)
 		newCounterVec.With(labelMap).Inc()
 	} else {
 		val.(*prometheus.CounterVec).With(labelMap).Inc()
@@ -307,7 +313,7 @@ func (reporter *PrometheusReporter) incSummary(summaryName string, toSetValue fl
 	if len(labelMap) == 0 {
 		// summary
 		if val, exist := reporter.userSummary.Load(summaryName); !exist {
-			newSummary := newSummary(summaryName)
+			newSummary := newSummary(summaryName, reporter.namespace)
 			_ = prom.DefaultRegisterer.Register(newSummary)
 			reporter.userSummary.Store(summaryName, newSummary)
 			newSummary.Observe(toSetValue)
@@ -323,7 +329,7 @@ func (reporter *PrometheusReporter) incSummary(summaryName string, toSetValue fl
 		for k, _ := range labelMap {
 			keyList = append(keyList, k)
 		}
-		newSummaryVec := newSummaryVec(summaryName, keyList)
+		newSummaryVec := newSummaryVec(summaryName, reporter.namespace, keyList)
 		_ = prom.DefaultRegisterer.Register(newSummaryVec)
 		reporter.userSummaryVec.Store(summaryName, newSummaryVec)
 		newSummaryVec.With(labelMap).Observe(toSetValue)
diff --git a/metrics/prometheus/reporter_test.go b/metrics/prometheus/reporter_test.go
index 7f6d150..8ea17d1 100644
--- a/metrics/prometheus/reporter_test.go
+++ b/metrics/prometheus/reporter_test.go
@@ -30,12 +30,13 @@ import (
 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)
+	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." +
diff --git a/metrics/reporter.go b/metrics/reporter.go
index e0615b1..cd775df 100644
--- a/metrics/reporter.go
+++ b/metrics/reporter.go
@@ -26,10 +26,33 @@ import (
 	"dubbo.apache.org/dubbo-go/v3/protocol"
 )
 
+type ReporterConfig struct {
+	Enable             bool
+	Namespace          string
+	Mode               ReportMode
+	Port               string
+	Path               string
+	PushGatewayAddress string
+}
+
+type ReportMode string
+
 const (
-	NameSpace = "dubbo"
+	ReportModePull = "pull"
+	ReportModePush = "push"
 )
 
+func NewReporterConfig() *ReporterConfig {
+	return &ReporterConfig{
+		Enable:             true,
+		Namespace:          "dubbo",
+		Port:               "9090",
+		Path:               "/metrics",
+		Mode:               ReportModePull,
+		PushGatewayAddress: "",
+	}
+}
+
 // Reporter will be used to report the invocation's duration
 type Reporter interface {
 	// report the duration of an invocation