diff --git a/common/constant/time.go b/common/constant/time.go
new file mode 100644
index 0000000000000000000000000000000000000000..be1baaca67f474aa92e86e529d03400948ef4612
--- /dev/null
+++ b/common/constant/time.go
@@ -0,0 +1,26 @@
+/*
+ * 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
+
+import (
+ "time"
+)
+
+var (
+ MsToNanoRate = int64(time.Millisecond / time.Nanosecond)
+)
diff --git a/common/extension/metrics.go b/common/extension/metrics.go
new file mode 100644
index 0000000000000000000000000000000000000000..42fca7a2db36614fcef31dd5ba7324a156164d4f
--- /dev/null
+++ b/common/extension/metrics.go
@@ -0,0 +1,44 @@
+/*
+ * 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 (
+ "github.com/apache/dubbo-go/metrics"
+)
+
+var (
+ // we couldn't store the instance because the some instance may initialize before loading configuration
+ // so lazy initialization will be better.
+ metricReporterMap = make(map[string]func() metrics.Reporter, 4)
+)
+
+// SetMetricReporter set a reporter with the name
+func SetMetricReporter(name string, reporterFunc func() metrics.Reporter) {
+ metricReporterMap[name] = reporterFunc
+}
+
+// GetMetricReporter find 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 {
+ reporterFunc, found := metricReporterMap[name]
+ if !found {
+ panic("Cannot find the reporter with name: " + name)
+ }
+ return reporterFunc()
+}
diff --git a/common/extension/metrics_test.go b/common/extension/metrics_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..6a8a3fe538a9cd68c57c91592a88ec257ae4a267
--- /dev/null
+++ b/common/extension/metrics_test.go
@@ -0,0 +1,49 @@
+/*
+ * 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 (
+ "github.com/apache/dubbo-go/metrics"
+ "github.com/apache/dubbo-go/protocol"
+)
+
+func TestGetMetricReporter(t *testing.T) {
+ reporter := &mockReporter{}
+ name := "mock"
+ SetMetricReporter(name, func() metrics.Reporter {
+ return reporter
+ })
+ res := GetMetricReporter(name)
+ assert.Equal(t, reporter, res)
+}
+
+type mockReporter struct {
+}
+
+func (m mockReporter) Report(ctx context.Context, invoker protocol.Invoker, invocation protocol.Invocation, cost time.Duration, res protocol.Result) {
+}
diff --git a/config/base_config.go b/config/base_config.go
index 09495741153cf7caae4bb10ada0aaa686fbf0325..f38ef9b953997888ce47a7bc8aaa2e6577cfe377 100644
--- a/config/base_config.go
+++ b/config/base_config.go
@@ -40,12 +40,14 @@ type multiConfiger interface {
Prefix() string
}
-// BaseConfig ...
+// BaseConfig is the common configuration for provider and consumer
type BaseConfig struct {
ConfigCenterConfig *ConfigCenterConfig `yaml:"config_center" json:"config_center,omitempty"`
configCenterUrl *common.URL
prefix string
fatherConfig interface{}
+
+ MetricConfig *MetricConfig `yaml:"metrics" json:"metrics,omitempty"`
}
func (c *BaseConfig) startConfigCenter(ctx context.Context) error {
diff --git a/config/config_loader.go b/config/config_loader.go
index d6eb7ff524a53c6949d22a2b34eb965274a75232..875d1f6ddb84434d32296076cd31be96c1385b8a 100644
--- a/config/config_loader.go
+++ b/config/config_loader.go
@@ -31,9 +31,11 @@ import (
)
var (
- consumerConfig *ConsumerConfig
- providerConfig *ProviderConfig
- maxWait = 3
+ consumerConfig *ConsumerConfig
+ providerConfig *ProviderConfig
+ metricConfig *MetricConfig
+ applicationConfig *ApplicationConfig
+ maxWait = 3
)
// loaded consumer & provider config from xxx.yml, and log config from xxx.xml
@@ -75,6 +77,10 @@ func Load() {
if consumerConfig == nil {
logger.Warnf("consumerConfig is nil!")
} else {
+
+ metricConfig = consumerConfig.MetricConfig
+ applicationConfig = consumerConfig.ApplicationConfig
+
checkApplicationName(consumerConfig.ApplicationConfig)
if err := configCenterRefreshConsumer(); err != nil {
logger.Errorf("[consumer config center refresh] %#v", err)
@@ -131,6 +137,11 @@ func Load() {
if providerConfig == nil {
logger.Warnf("providerConfig is nil!")
} else {
+
+ // so, you should know that the consumer's config will be override
+ metricConfig = providerConfig.MetricConfig
+ applicationConfig = providerConfig.ApplicationConfig
+
checkApplicationName(providerConfig.ApplicationConfig)
if err := configCenterRefreshProvider(); err != nil {
logger.Errorf("[provider config center refresh] %#v", err)
@@ -162,3 +173,42 @@ func GetRPCService(name string) common.RPCService {
func RPCService(service common.RPCService) {
consumerConfig.References[service.Reference()].Implement(service)
}
+
+// GetMetricConfig find the MetricConfig
+// if it is nil, create a new one
+func GetMetricConfig() *MetricConfig {
+ if metricConfig == nil {
+ metricConfig = &MetricConfig{}
+ }
+ return metricConfig
+}
+
+// GetApplicationConfig find the application config
+// if not, we will create one
+// Usually applicationConfig will be initialized when system start
+func GetApplicationConfig() *ApplicationConfig {
+ if applicationConfig == nil {
+ applicationConfig = &ApplicationConfig{}
+ }
+ return applicationConfig
+}
+
+// GetProviderConfig find the provider config
+// if not found, create new one
+func GetProviderConfig() ProviderConfig {
+ if providerConfig == nil {
+ logger.Warnf("providerConfig is nil!")
+ return ProviderConfig{}
+ }
+ return *providerConfig
+}
+
+// GetConsumerConfig find the consumer config
+// if not found, create new one
+func GetConsumerConfig() ConsumerConfig {
+ if consumerConfig == nil {
+ logger.Warnf("consumerConfig is nil!")
+ return ConsumerConfig{}
+ }
+ return *consumerConfig
+}
diff --git a/config/consumer_config.go b/config/consumer_config.go
index 7756f3b51c0f46a19687affb4dc6eadf9ef711c7..1bfa761fc9e4f88373163e26379d21639693aadf 100644
--- a/config/consumer_config.go
+++ b/config/consumer_config.go
@@ -85,15 +85,6 @@ func SetConsumerConfig(c ConsumerConfig) {
consumerConfig = &c
}
-// GetConsumerConfig ...
-func GetConsumerConfig() ConsumerConfig {
- if consumerConfig == nil {
- logger.Warnf("consumerConfig is nil!")
- return ConsumerConfig{}
- }
- return *consumerConfig
-}
-
// ConsumerInit ...
func ConsumerInit(confConFile string) error {
if confConFile == "" {
diff --git a/config/metric_config.go b/config/metric_config.go
new file mode 100644
index 0000000000000000000000000000000000000000..73a3ca1cfe4f1461db2e225947dd13199b2ad55e
--- /dev/null
+++ b/config/metric_config.go
@@ -0,0 +1,37 @@
+/*
+ * 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
+
+var (
+ defaultHistogramBucket = []float64{10, 50, 100, 200, 500, 1000, 10000}
+)
+
+// This is the config struct for all metrics implementation
+type MetricConfig struct {
+ Reporters []string `yaml:"reporters" json:"reporters,omitempty"`
+ HistogramBucket []float64 `yaml:"histogram_bucket" json:"histogram_bucket,omitempty"`
+}
+
+// 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
+ }
+ return mc.HistogramBucket
+}
diff --git a/config/metric_config_test.go b/config/metric_config_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..fe9d2493f37c0bd563931f5acf133105d72d0e53
--- /dev/null
+++ b/config/metric_config_test.go
@@ -0,0 +1,31 @@
+/*
+ * 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 (
+ "testing"
+)
+
+import (
+ "github.com/stretchr/testify/assert"
+)
+
+func TestGetMetricConfig(t *testing.T) {
+ empty := GetMetricConfig()
+ assert.NotNil(t, empty)
+}
diff --git a/config/provider_config.go b/config/provider_config.go
index 0bfa78647b58d9b6eb961adc5485207faffe1e1e..0f5c71a7de055219992c433f7fcc5d639e4b3503 100644
--- a/config/provider_config.go
+++ b/config/provider_config.go
@@ -76,15 +76,6 @@ func SetProviderConfig(p ProviderConfig) {
providerConfig = &p
}
-// GetProviderConfig ...
-func GetProviderConfig() ProviderConfig {
- if providerConfig == nil {
- logger.Warnf("providerConfig is nil!")
- return ProviderConfig{}
- }
- return *providerConfig
-}
-
// ProviderInit ...
func ProviderInit(confProFile string) error {
if len(confProFile) == 0 {
diff --git a/config_center/zookeeper/impl.go b/config_center/zookeeper/impl.go
index a20f5496d0f68c461cd988d9aa4e77b671fc929b..70fb196a1eedb994eae38576de35d36deb450aaa 100644
--- a/config_center/zookeeper/impl.go
+++ b/config_center/zookeeper/impl.go
@@ -24,8 +24,8 @@ import (
)
import (
+ "github.com/dubbogo/go-zookeeper/zk"
perrors "github.com/pkg/errors"
- "github.com/samuel/go-zookeeper/zk"
)
import (
diff --git a/config_center/zookeeper/impl_test.go b/config_center/zookeeper/impl_test.go
index e614009faa5b32873c6245dea5c85cc2747e19ea..cca4427587534c1c4d0f9324f932f8018502521c 100644
--- a/config_center/zookeeper/impl_test.go
+++ b/config_center/zookeeper/impl_test.go
@@ -24,7 +24,7 @@ import (
)
import (
- "github.com/samuel/go-zookeeper/zk"
+ "github.com/dubbogo/go-zookeeper/zk"
"github.com/stretchr/testify/assert"
)
diff --git a/filter/filter_impl/metrics_filter.go b/filter/filter_impl/metrics_filter.go
new file mode 100644
index 0000000000000000000000000000000000000000..f4734172b74c8bbcdac5c9a9743acb4df5fcb6b5
--- /dev/null
+++ b/filter/filter_impl/metrics_filter.go
@@ -0,0 +1,93 @@
+/*
+ * 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 filter_impl
+
+import (
+ "context"
+ "time"
+)
+
+import (
+ "github.com/apache/dubbo-go/common/extension"
+ "github.com/apache/dubbo-go/config"
+ "github.com/apache/dubbo-go/filter"
+ "github.com/apache/dubbo-go/metrics"
+ "github.com/apache/dubbo-go/protocol"
+)
+
+const (
+ metricFilterName = "metrics"
+)
+
+var (
+ metricFilterInstance filter.Filter
+)
+
+// must initialized before using the filter and after loading configuration
+func init() {
+ extension.SetFilter(metricFilterName, newMetricsFilter)
+}
+
+// metricFilter will calculate the invocation's duration and the report to the reporters
+// If you want to use this filter to collect the metrics,
+// Adding this into your configuration file, like:
+// filter: "metrics"
+// metrics:
+// reporter:
+// - "your reporter" # here you should specify the reporter, for example 'prometheus'
+// more info please take a look at dubbo-samples projects
+type metricsFilter struct {
+ reporters []metrics.Reporter
+}
+
+// Invoke collect the duration of invocation and then report the duration by using goroutine
+func (p *metricsFilter) Invoke(ctx context.Context, invoker protocol.Invoker, invocation protocol.Invocation) protocol.Result {
+ start := time.Now()
+ res := invoker.Invoke(ctx, invocation)
+ end := time.Now()
+ duration := end.Sub(start)
+ go func() {
+ for _, reporter := range p.reporters {
+ reporter.Report(ctx, invoker, invocation, duration, res)
+ }
+ }()
+ return res
+}
+
+// OnResponse do nothing and return the result
+func (p *metricsFilter) OnResponse(ctx context.Context, res protocol.Result, invoker protocol.Invoker, invocation protocol.Invocation) protocol.Result {
+ return res
+}
+
+// newMetricsFilter the metricsFilter is singleton.
+// it's lazy initialization
+// make sure that the configuration had been loaded before invoking this method.
+func newMetricsFilter() filter.Filter {
+ if metricFilterInstance == nil {
+ reporterNames := config.GetMetricConfig().Reporters
+ reporters := make([]metrics.Reporter, 0, len(reporterNames))
+ for _, name := range reporterNames {
+ reporters = append(reporters, extension.GetMetricReporter(name))
+ }
+ metricFilterInstance = &metricsFilter{
+ reporters: reporters,
+ }
+ }
+
+ return metricFilterInstance
+}
diff --git a/filter/filter_impl/metrics_filter_test.go b/filter/filter_impl/metrics_filter_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..83697f0f29bc699eb005b72192ae8eb87d6a730f
--- /dev/null
+++ b/filter/filter_impl/metrics_filter_test.go
@@ -0,0 +1,84 @@
+/*
+ * 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 filter_impl
+
+import (
+ "context"
+ "sync"
+ "testing"
+ "time"
+)
+
+import (
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/mock"
+)
+
+import (
+ "github.com/apache/dubbo-go/common"
+ "github.com/apache/dubbo-go/common/extension"
+ "github.com/apache/dubbo-go/config"
+ "github.com/apache/dubbo-go/metrics"
+ "github.com/apache/dubbo-go/protocol"
+ "github.com/apache/dubbo-go/protocol/invocation"
+)
+
+func TestMetricsFilter_Invoke(t *testing.T) {
+
+ // prepare the mock reporter
+ config.GetMetricConfig().Reporters = []string{"mock"}
+ mk := &mockReporter{}
+ extension.SetMetricReporter("mock", func() metrics.Reporter {
+ return mk
+ })
+
+ instance := extension.GetFilter(metricFilterName)
+
+ url, _ := common.NewURL(context.Background(),
+ "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]string, 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)
+ assert.NotNil(t, result)
+ mk.AssertNotCalled(t, "Report", 1)
+ // it will do nothing
+ result = instance.OnResponse(ctx, nil, invoker, inv)
+ assert.Nil(t, result)
+}
+
+type mockReporter struct {
+ mock.Mock
+ wg sync.WaitGroup
+}
+
+func (m *mockReporter) Report(ctx context.Context, invoker protocol.Invoker, invocation protocol.Invocation, cost time.Duration, res protocol.Result) {
+ m.Called(ctx, invoker, invocation)
+ m.wg.Done()
+}
diff --git a/go.mod b/go.mod
index db6dc92c63176334f6dfa0436889ffab6f3c9c53..54b39d322e83e05c4c54ffdf166dd4f0aa039249 100644
--- a/go.mod
+++ b/go.mod
@@ -13,6 +13,7 @@ require (
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f // indirect
github.com/creasty/defaults v1.3.0
github.com/dubbogo/getty v1.3.2
+ github.com/dubbogo/go-zookeeper v1.0.0
github.com/dubbogo/gost v1.5.2
github.com/fastly/go-utils v0.0.0-20180712184237-d95a45783239 // indirect
github.com/go-errors/errors v1.0.1 // indirect
@@ -37,8 +38,7 @@ require (
github.com/nacos-group/nacos-sdk-go v0.0.0-20190723125407-0242d42e3dbb
github.com/opentracing/opentracing-go v1.1.0
github.com/pkg/errors v0.8.1
- github.com/prometheus/client_golang v1.1.0 // indirect
- github.com/samuel/go-zookeeper v0.0.0-20180130194729-c4fab1ac1bec
+ github.com/prometheus/client_golang v1.1.0
github.com/satori/go.uuid v1.2.0
github.com/smartystreets/goconvey v0.0.0-20190710185942-9d28bd7c0945 // indirect
github.com/soheilhy/cmux v0.1.4 // indirect
diff --git a/go.sum b/go.sum
index f215a81b209579c0bb5de0123153b10b7a36767b..0461f29653568944637306d65a6addbd79df664f 100644
--- a/go.sum
+++ b/go.sum
@@ -22,8 +22,6 @@ github.com/SAP/go-hdb v0.12.0 h1:5hBQZ2jjyZ268qjDmoDZJuCyLzR6oRLI60eYzmTW9m4=
github.com/SAP/go-hdb v0.12.0/go.mod h1:etBT+FAi1t5k3K3tf5vQTnosgYmhDkRi8jEnQqCnxF0=
github.com/SermoDigital/jose v0.0.0-20180104203859-803625baeddc h1:LkkwnbY+S8WmwkWq1SVyRWMH9nYWO1P5XN3OD1tts/w=
github.com/SermoDigital/jose v0.0.0-20180104203859-803625baeddc/go.mod h1:ARgCUhI1MHQH+ONky/PAtmVHQrP5JlGY0F3poXOp/fA=
-github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
-github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 h1:fLjPD/aNc3UIOA6tDi6QXUemppXK3P9BI7mr2hd6gx8=
github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
github.com/Workiva/go-datastructures v1.0.50 h1:slDmfW6KCHcC7U+LP3DDBbm4fqTwZGn1beOFPfGaLvo=
@@ -106,18 +104,16 @@ github.com/docker/go-units v0.3.3 h1:Xk8S3Xj5sLGlG5g67hJmYMmUgXv5N4PhkjJHHqrwnTk
github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/dubbogo/getty v1.3.2 h1:l1KVSs/1CtTKbIPTrkTtBT6S9ddvmswDGoAnnl2CDpM=
github.com/dubbogo/getty v1.3.2/go.mod h1:ANbVQ9tbpZ2b0xdR8nRrgS/oXIsZAeRxzvPSOn/7mbk=
+github.com/dubbogo/go-zookeeper v1.0.0 h1:RsYdlGwhDW+iKXM3eIIcvt34P2swLdmQfuIJxsHlGoM=
+github.com/dubbogo/go-zookeeper v1.0.0/go.mod h1:fn6n2CAEer3novYgk9ULLwAjuV8/g4DdC2ENwRb6E+c=
github.com/dubbogo/gost v1.5.1 h1:oG5dzaWf1KYynBaBoUIOkgT+YD0niHV6xxI0Odq7hDg=
github.com/dubbogo/gost v1.5.1/go.mod h1:pPTjVyoJan3aPxBPNUX0ADkXjPibLo+/Ib0/fADXSG8=
github.com/dubbogo/gost v1.5.2 h1:ri/03971hdpnn3QeCU+4UZgnRNGDXLDGDucR/iozZm8=
github.com/dubbogo/gost v1.5.2/go.mod h1:pPTjVyoJan3aPxBPNUX0ADkXjPibLo+/Ib0/fADXSG8=
github.com/duosecurity/duo_api_golang v0.0.0-20190308151101-6c680f768e74 h1:2MIhn2R6oXQbgW5yHfS+d6YqyMfXiu2L55rFZC4UD/M=
github.com/duosecurity/duo_api_golang v0.0.0-20190308151101-6c680f768e74/go.mod h1:UqXY1lYT/ERa4OEAywUqdok1T4RCRdArkhic1Opuavo=
-github.com/eapache/go-resiliency v1.1.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/elazarl/go-bindata-assetfs v0.0.0-20160803192304-e1a2a7ec64b0 h1:ZoRgc53qJCfSLimXqJDrmBhnt5GChDsExMCK7t48o0Y=
github.com/elazarl/go-bindata-assetfs v0.0.0-20160803192304-e1a2a7ec64b0/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo7R71Vk1u8bnjau5yw4=
-github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g=
github.com/envoyproxy/go-control-plane v0.8.0 h1:uE6Fp4fOcAJdc1wTQXLJ+SYistkbG1dNoi6Zs1+Ybvk=
github.com/envoyproxy/go-control-plane v0.8.0/go.mod h1:GSSbY9P1neVhdY7G4wu+IK1rk/dqhiCC/4ExuWJZVuk=
github.com/envoyproxy/protoc-gen-validate v0.0.14 h1:YBW6/cKy9prEGRYLnaGa4IDhzxZhRCtKsax8srGKDnM=
@@ -152,7 +148,6 @@ github.com/gocql/gocql v0.0.0-20180617115710-e06f8c1bcd78/go.mod h1:4Fw1eo5iaEhD
github.com/gogo/googleapis v1.1.0 h1:kFkMAZBNAn4j7K0GiZr8cRYzejq68VbheufiV3YuyFI=
github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
-github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE=
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
github.com/goji/httpauth v0.0.0-20160601135302-2da839ab0f4d/go.mod h1:nnjvkQ9ptGaCkuDUx6wNykzzlUixGxvkme+H/lnzb+A=
@@ -191,9 +186,6 @@ github.com/gophercloud/gophercloud v0.0.0-20180828235145-f29afc2cceca/go.mod h1:
github.com/gopherjs/gopherjs v0.0.0-20180825215210-0210a2f0f73c/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
-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/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q=
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/gotestyourself/gotestyourself v2.2.0+incompatible h1:AQwinXlbQR2HvPjQZOmDhRqsv5mZf+Jb1RnSLxcqZcI=
@@ -329,7 +321,6 @@ github.com/lestrrat/go-strftime v0.0.0-20180220042222-ba3bf9c1d042 h1:Bvq8AziQ5j
github.com/lestrrat/go-strftime v0.0.0-20180220042222-ba3bf9c1d042/go.mod h1:TPpsiPUEh0zFL1Snz4crhMlBe60PYxRHr5oFF3rRYg0=
github.com/lib/pq v0.0.0-20180523175426-90697d60dd84 h1:it29sI2IM490luSc3RAhp5WuCYnc6RtbfLVAB7nmC5M=
github.com/lib/pq v0.0.0-20180523175426-90697d60dd84/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
-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=
github.com/mattn/go-colorable v0.0.9 h1:UVL0vNpWh04HeJXV0KLcaT7r06gOH2l4OW6ddYRUIY4=
@@ -372,22 +363,16 @@ github.com/nicolai86/scaleway-sdk v1.10.2-0.20180628010248-798f60e20bb2/go.mod h
github.com/oklog/run v0.0.0-20180308005104-6934b124db28 h1:Hbr3fbVPXea52oPQeP7KLSxP52g6SFaNY1IqAmUyEW0=
github.com/oklog/run v0.0.0-20180308005104-6934b124db28/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
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/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
github.com/onsi/gomega v1.4.2/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
-github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/opencontainers/go-digest v1.0.0-rc1 h1:WzifXhOVOEOuFYOJAW6aQqW0TooG2iki3E3Ii+WN7gQ=
github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
github.com/opencontainers/image-spec v1.0.1 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI=
github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
github.com/opencontainers/runc v0.1.1 h1:GlxAyO6x8rfZYN9Tt0Kti5a/cP41iuiO2yYT0IJGY8Y=
github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
-github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis=
github.com/opentracing/opentracing-go v1.1.0 h1:pWlfV3Bxv7k65HYwkikxat0+s3pV4bsqf19k25Ur8rU=
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
-github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA=
-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/ory/dockertest v3.3.4+incompatible h1:VrpM6Gqg7CrPm3bL4Wm1skO+zFWLbh7/Xb5kGEbJRh8=
github.com/ory/dockertest v3.3.4+incompatible/go.mod h1:1vX4m9wsvi00u5bseYwXaSnhNrne+V0E6LAcBILJdPs=
github.com/packethost/packngo v0.1.1-0.20180711074735-b9cb5096f54c h1:vwpFWvAO8DeIZfFeqASzZfsxuWPno9ncAebBEP0N3uE=
@@ -399,11 +384,9 @@ github.com/patrickmn/go-cache v0.0.0-20180527043350-9f6ff22cfff8 h1:BR6MM54q4W9p
github.com/patrickmn/go-cache v0.0.0-20180527043350-9f6ff22cfff8/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI=
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
-github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
-github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/posener/complete v1.1.1 h1:ccV59UEOTzVDnDUEFdT95ZzHVZ+5+158q8+SJb2QV5w=
@@ -425,15 +408,12 @@ github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.0.3 h1:CTwfnzjQ+8dS6MhHHu4YswVAD99sL2wjPqP+VkURmKE=
github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ=
-github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
github.com/renier/xmlrpc v0.0.0-20170708154548-ce4a1a486c03 h1:Wdi9nwnhFNAlseAOekn6B5G/+GMtks9UKbvRU/CMM/o=
github.com/renier/xmlrpc v0.0.0-20170708154548-ce4a1a486c03/go.mod h1:gRAiPF5C5Nd0eyyRdqIu9qTiFSoZzpTq727b5B8fkkU=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
github.com/ryanuber/go-glob v0.0.0-20170128012129-256dc444b735 h1:7YvPJVmEeFHR1Tj9sZEYsmarJEQfMVYpd/Vyy/A8dqE=
github.com/ryanuber/go-glob v0.0.0-20170128012129-256dc444b735/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc=
-github.com/samuel/go-zookeeper v0.0.0-20180130194729-c4fab1ac1bec h1:6ncX5ko6B9LntYM0YBRXkiSaZMmLYeZ/NWcmeB43mMY=
-github.com/samuel/go-zookeeper v0.0.0-20180130194729-c4fab1ac1bec/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E=
github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww=
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I=
@@ -460,7 +440,6 @@ github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4k
github.com/spf13/pflag v1.0.2/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
-github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
@@ -480,7 +459,6 @@ github.com/toolkits/concurrent v0.0.0-20150624120057-a4371d70e3e3 h1:kF/7m/ZU+0D
github.com/toolkits/concurrent v0.0.0-20150624120057-a4371d70e3e3/go.mod h1:QDlpd3qS71vYtakd2hmdpqhJ9nwv6mD6A30bQ1BPBFE=
github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926 h1:G3dpKMzFDjgEh2q1Z7zUUtKa8ViPtH+ocF0bE0g00O8=
github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM=
-github.com/uber/jaeger-client-go v2.17.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk=
github.com/vmware/govmomi v0.18.0 h1:f7QxSmP7meCtoAmiKZogvVbLInT+CZx6Px6K5rYsJZo=
github.com/vmware/govmomi v0.18.0/go.mod h1:URlwyTFZX72RmxtxuaFL2Uj3fD1JTvZdx59bHWk6aFU=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8=
@@ -559,7 +537,6 @@ google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8 h1:Nw54tB0rB7hY/N0
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.19.1/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
-google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM=
google.golang.org/grpc v1.22.1 h1:/7cs52RnTJmD43s3uxzlq2U7nqVTd/37viQwMrMNlOM=
google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U=
diff --git a/metrics/prometheus/reporter.go b/metrics/prometheus/reporter.go
new file mode 100644
index 0000000000000000000000000000000000000000..1636b14da2fe5ab714853aa662eaa774ddbc1791
--- /dev/null
+++ b/metrics/prometheus/reporter.go
@@ -0,0 +1,184 @@
+/*
+ * 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"
+ "strconv"
+ "strings"
+ "sync"
+ "time"
+)
+import (
+ "github.com/prometheus/client_golang/prometheus"
+)
+
+import (
+ "github.com/apache/dubbo-go/common"
+ "github.com/apache/dubbo-go/common/constant"
+ "github.com/apache/dubbo-go/common/extension"
+ "github.com/apache/dubbo-go/common/logger"
+ "github.com/apache/dubbo-go/config"
+ "github.com/apache/dubbo-go/metrics"
+ "github.com/apache/dubbo-go/protocol"
+)
+
+const (
+ reporterName = "prometheus"
+ serviceKey = constant.SERVICE_KEY
+ groupKey = constant.GROUP_KEY
+ versionKey = constant.VERSION_KEY
+ methodKey = constant.METHOD_KEY
+ timeoutKey = constant.TIMEOUT_KEY
+
+ providerKey = "provider"
+ consumerKey = "consumer"
+
+ // to identify the metric's type
+ histogramSuffix = "_histogram"
+ // to identify the metric's type
+ summarySuffix = "_summary"
+)
+
+var (
+ labelNames = []string{serviceKey, groupKey, versionKey, methodKey, timeoutKey}
+ namespace = config.GetApplicationConfig().Name
+ reporterInstance *PrometheusReporter
+ reporterInitOnce sync.Once
+)
+
+// should initialize after loading configuration
+func init() {
+
+ extension.SetMetricReporter(reporterName, newPrometheusReporter)
+}
+
+// PrometheusReporter
+// it will collect the data for Prometheus
+// if you want to use this, you should initialize your prometheus.
+// https://prometheus.io/docs/guides/go-application/
+type PrometheusReporter struct {
+
+ // report the consumer-side's summary data
+ consumerSummaryVec *prometheus.SummaryVec
+ // report the provider-side's summary data
+ providerSummaryVec *prometheus.SummaryVec
+
+ // report the provider-side's histogram data
+ providerHistogramVec *prometheus.HistogramVec
+ // report the consumer-side's histogram data
+ consumerHistogramVec *prometheus.HistogramVec
+}
+
+// Report report the duration to Prometheus
+// the role in url must be consumer or provider
+// or it will be ignored
+func (reporter *PrometheusReporter) Report(ctx context.Context, invoker protocol.Invoker, invocation protocol.Invocation, cost time.Duration, res protocol.Result) {
+ url := invoker.GetUrl()
+ var sumVec *prometheus.SummaryVec
+ var hisVec *prometheus.HistogramVec
+ if isProvider(url) {
+ sumVec = reporter.providerSummaryVec
+ hisVec = reporter.providerHistogramVec
+ } else if isConsumer(url) {
+ sumVec = reporter.consumerSummaryVec
+ hisVec = reporter.consumerHistogramVec
+ } else {
+ logger.Warnf("The url is not the consumer's or provider's, "+
+ "so the invocation will be ignored. url: %s", url.String())
+ return
+ }
+
+ labels := prometheus.Labels{
+ serviceKey: url.Service(),
+ groupKey: url.GetParam(groupKey, ""),
+ versionKey: url.GetParam(versionKey, ""),
+ methodKey: invocation.MethodName(),
+ timeoutKey: url.GetParam(timeoutKey, ""),
+ }
+
+ costMs := float64(cost.Nanoseconds() / constant.MsToNanoRate)
+ sumVec.With(labels).Observe(costMs)
+ hisVec.With(labels).Observe(costMs)
+}
+
+func newHistogramVec(side string) *prometheus.HistogramVec {
+ mc := config.GetMetricConfig()
+ return prometheus.NewHistogramVec(
+ prometheus.HistogramOpts{
+ Namespace: namespace,
+ Subsystem: side,
+ Name: serviceKey + histogramSuffix,
+ Help: "This is the dubbo's histogram metrics",
+ Buckets: mc.GetHistogramBucket(),
+ },
+ labelNames)
+}
+
+// whether this url represents the application received the request as server
+func isProvider(url common.URL) bool {
+ role := url.GetParam(constant.ROLE_KEY, "")
+ return strings.EqualFold(role, strconv.Itoa(common.PROVIDER))
+}
+
+// whether this url represents the application sent then request as client
+func isConsumer(url common.URL) bool {
+ role := url.GetParam(constant.ROLE_KEY, "")
+ return strings.EqualFold(role, strconv.Itoa(common.CONSUMER))
+}
+
+// newSummaryVec create SummaryVec, the Namespace is dubbo
+// the objectives is from my experience.
+func newSummaryVec(side string) *prometheus.SummaryVec {
+ return prometheus.NewSummaryVec(
+ prometheus.SummaryOpts{
+ Namespace: namespace,
+ Help: "This is the dubbo's summary metrics",
+ Subsystem: side,
+ Name: serviceKey + summarySuffix,
+ 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,
+ },
+ },
+ labelNames,
+ )
+}
+
+// newPrometheusReporter create new prometheusReporter
+// it will register the metrics into prometheus
+func newPrometheusReporter() metrics.Reporter {
+ if reporterInstance == nil {
+ reporterInitOnce.Do(func() {
+ reporterInstance = &PrometheusReporter{
+ consumerSummaryVec: newSummaryVec(consumerKey),
+ providerSummaryVec: newSummaryVec(providerKey),
+
+ consumerHistogramVec: newHistogramVec(consumerKey),
+ providerHistogramVec: newHistogramVec(providerKey),
+ }
+ prometheus.MustRegister(reporterInstance.consumerSummaryVec, reporterInstance.providerSummaryVec,
+ reporterInstance.consumerHistogramVec, reporterInstance.providerHistogramVec)
+ })
+ }
+ return reporterInstance
+}
diff --git a/metrics/prometheus/reporter_test.go b/metrics/prometheus/reporter_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..d1741d16d03f09ffc19b227e6a405f60bf306f9b
--- /dev/null
+++ b/metrics/prometheus/reporter_test.go
@@ -0,0 +1,72 @@
+/*
+ * 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 (
+ "github.com/apache/dubbo-go/common"
+ "github.com/apache/dubbo-go/common/extension"
+ "github.com/apache/dubbo-go/protocol"
+ "github.com/apache/dubbo-go/protocol/invocation"
+)
+
+func TestPrometheusReporter_Report(t *testing.T) {
+ reporter := extension.GetMetricReporter(reporterName)
+ url, _ := common.NewURL(context.Background(),
+ "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]string, 10)
+ inv := invocation.NewRPCInvocation("MethodName", []interface{}{"OK", "Hello"}, attach)
+
+ assert.False(t, isConsumer(url))
+ ctx := context.Background()
+ reporter.Report(ctx, invoker, inv, 100*time.Millisecond, nil)
+
+ // consumer side
+ url, _ = common.NewURL(context.Background(),
+ "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.Report(ctx, invoker, inv, 100*time.Millisecond, nil)
+
+ // invalid role
+ url, _ = common.NewURL(context.Background(),
+ "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.Report(ctx, invoker, inv, 100*time.Millisecond, nil)
+}
diff --git a/metrics/reporter.go b/metrics/reporter.go
new file mode 100644
index 0000000000000000000000000000000000000000..85ef1dcdf0dad275edecc1f3a85502c1493c1395
--- /dev/null
+++ b/metrics/reporter.go
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package metrics
+
+import (
+ "context"
+ "time"
+)
+import (
+ "github.com/apache/dubbo-go/protocol"
+)
+
+const (
+ NameSpace = "dubbo"
+)
+
+// it will be use to report the invocation's duration
+type Reporter interface {
+ // report the duration of an invocation
+ Report(ctx context.Context, invoker protocol.Invoker, invocation protocol.Invocation,
+ cost time.Duration, res protocol.Result)
+}
diff --git a/registry/zookeeper/registry.go b/registry/zookeeper/registry.go
index 30b3ab29b0e8c9993bf97925a4f7c4bd89fe14e2..877c4e3f2320cd2c3f59ff538d22b9b3254aa917 100644
--- a/registry/zookeeper/registry.go
+++ b/registry/zookeeper/registry.go
@@ -26,8 +26,8 @@ import (
)
import (
+ "github.com/dubbogo/go-zookeeper/zk"
perrors "github.com/pkg/errors"
- "github.com/samuel/go-zookeeper/zk"
)
import (
diff --git a/remoting/zookeeper/client.go b/remoting/zookeeper/client.go
index 594d87b14ca932c3a2e8c1e271757c9d94d93bb8..f95231b374230c93036e0fbd74aeca4ecfe57f46 100644
--- a/remoting/zookeeper/client.go
+++ b/remoting/zookeeper/client.go
@@ -25,8 +25,8 @@ import (
)
import (
+ "github.com/dubbogo/go-zookeeper/zk"
perrors "github.com/pkg/errors"
- "github.com/samuel/go-zookeeper/zk"
)
import (
@@ -506,7 +506,7 @@ func (z *ZookeeperClient) GetChildrenW(path string) ([]string, <-chan zk.Event,
err error
children []string
stat *zk.Stat
- event <-chan zk.Event
+ watcher *zk.Watcher
)
err = errNilZkClientConn
@@ -514,7 +514,7 @@ func (z *ZookeeperClient) GetChildrenW(path string) ([]string, <-chan zk.Event,
conn := z.Conn
z.Unlock()
if conn != nil {
- children, stat, event, err = conn.ChildrenW(path)
+ children, stat, watcher, err = conn.ChildrenW(path)
}
if err != nil {
@@ -534,7 +534,7 @@ func (z *ZookeeperClient) GetChildrenW(path string) ([]string, <-chan zk.Event,
return nil, nil, errNilChildren
}
- return children, event, nil
+ return children, watcher.EvtCh, nil
}
// GetChildren ...
@@ -573,9 +573,9 @@ func (z *ZookeeperClient) GetChildren(path string) ([]string, error) {
// ExistW ...
func (z *ZookeeperClient) ExistW(zkPath string) (<-chan zk.Event, error) {
var (
- exist bool
- err error
- event <-chan zk.Event
+ exist bool
+ err error
+ watcher *zk.Watcher
)
err = errNilZkClientConn
@@ -583,7 +583,7 @@ func (z *ZookeeperClient) ExistW(zkPath string) (<-chan zk.Event, error) {
conn := z.Conn
z.Unlock()
if conn != nil {
- exist, _, event, err = conn.ExistsW(zkPath)
+ exist, _, watcher, err = conn.ExistsW(zkPath)
}
if err != nil {
@@ -595,7 +595,7 @@ func (z *ZookeeperClient) ExistW(zkPath string) (<-chan zk.Event, error) {
return nil, perrors.Errorf("zkClient{%s} App zk path{%s} does not exist.", z.name, zkPath)
}
- return event, nil
+ return watcher.EvtCh, nil
}
// GetContent ...
diff --git a/remoting/zookeeper/client_test.go b/remoting/zookeeper/client_test.go
index 17b9f0f33128eab7fc682fd37aeb454c8c2c5066..cb41eb326be95470e39694fc5df233fdf073b905 100644
--- a/remoting/zookeeper/client_test.go
+++ b/remoting/zookeeper/client_test.go
@@ -24,7 +24,7 @@ import (
)
import (
- "github.com/samuel/go-zookeeper/zk"
+ "github.com/dubbogo/go-zookeeper/zk"
"github.com/stretchr/testify/assert"
)
diff --git a/remoting/zookeeper/facade_test.go b/remoting/zookeeper/facade_test.go
index 9c17bd4852596e13e918175b2231335e1a1c4d4f..175d758b76bd8aede8fa0d63c92003dfc6b4f35c 100644
--- a/remoting/zookeeper/facade_test.go
+++ b/remoting/zookeeper/facade_test.go
@@ -24,7 +24,7 @@ import (
"time"
)
import (
- "github.com/samuel/go-zookeeper/zk"
+ "github.com/dubbogo/go-zookeeper/zk"
"github.com/stretchr/testify/assert"
)
import (
diff --git a/remoting/zookeeper/listener.go b/remoting/zookeeper/listener.go
index 43ee54f81f71ff74064aa5756ea11c70ba2055fa..4493c06dc3f13d59b9388268613fe9e08a14033e 100644
--- a/remoting/zookeeper/listener.go
+++ b/remoting/zookeeper/listener.go
@@ -25,8 +25,8 @@ import (
import (
"github.com/dubbogo/getty"
+ "github.com/dubbogo/go-zookeeper/zk"
perrors "github.com/pkg/errors"
- "github.com/samuel/go-zookeeper/zk"
)
import (
diff --git a/remoting/zookeeper/listener_test.go b/remoting/zookeeper/listener_test.go
index 1276e5363f5e3f1fcde9a36d8a94e671e030e6c3..43e9aca3f44470873c3c97ec2447bebcc57e5545 100644
--- a/remoting/zookeeper/listener_test.go
+++ b/remoting/zookeeper/listener_test.go
@@ -24,7 +24,7 @@ import (
"time"
)
import (
- "github.com/samuel/go-zookeeper/zk"
+ "github.com/dubbogo/go-zookeeper/zk"
"github.com/stretchr/testify/assert"
)
import (