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

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


The following commit(s) were added to refs/heads/main by this push:
     new f6fdbfdf7 feat: add some metrics about RT (#2340)
f6fdbfdf7 is described below

commit f6fdbfdf772ad7f82ea64b8d861e4140c3fa17cb
Author: Wang Guan <[email protected]>
AuthorDate: Tue Jul 4 13:34:20 2023 +0800

    feat: add some metrics about RT (#2340)
    
    * feat: add min RT metrics
    
    * refactor: adapt to Go 1.17 and bundle gaugeVec with syncMap
    
    * feat: add max and sum RT metrics
    
    * feat: avg RT metrics
    
    * refactor: RT sum metrics
    
    * feat: last RT metrics
    
    * refactor: file names and method names
---
 metrics/prometheus/after_invocation.go     |  49 ---------
 metrics/prometheus/before_invocation.go    |  40 --------
 metrics/prometheus/constant.go             |   8 +-
 metrics/prometheus/metric_set.go           |  72 ++++++++------
 metrics/prometheus/{common.go => model.go} | 155 ++++++++++++++++++++---------
 metrics/prometheus/reporter.go             |  79 ++++++++++++---
 metrics/prometheus/util.go                 |  75 ++++++++++++++
 7 files changed, 294 insertions(+), 184 deletions(-)

diff --git a/metrics/prometheus/after_invocation.go 
b/metrics/prometheus/after_invocation.go
deleted file mode 100644
index f1235a2d7..000000000
--- a/metrics/prometheus/after_invocation.go
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package prometheus
-
-import (
-       "context"
-       "time"
-)
-
-import (
-       "dubbo.apache.org/dubbo-go/v3/protocol"
-)
-
-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.reportRTSummaryVec(role, &labels, cost.Milliseconds())
-       reporter.reportRequestsTotalCounterVec(role, &labels)
-       reporter.decRequestsProcessingTotalGaugeVec(role, &labels)
-
-       if res != nil && res.Error() == nil {
-               // succeed
-               reporter.incRequestsSucceedTotalCounterVec(role, &labels)
-       }
-}
diff --git a/metrics/prometheus/before_invocation.go 
b/metrics/prometheus/before_invocation.go
deleted file mode 100644
index 7477b1362..000000000
--- a/metrics/prometheus/before_invocation.go
+++ /dev/null
@@ -1,40 +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"
-)
-import (
-       "dubbo.apache.org/dubbo-go/v3/protocol"
-)
-
-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.incRequestsProcessingTotalGaugeVec(role, &labels)
-}
diff --git a/metrics/prometheus/constant.go b/metrics/prometheus/constant.go
index 95e090d46..35858853f 100644
--- a/metrics/prometheus/constant.go
+++ b/metrics/prometheus/constant.go
@@ -34,12 +34,14 @@ const (
 
        requestsField = "requests"
        rtField       = "rt"
-       tpsField      = "tps"
 
        milliSecondsField = "milliseconds"
 
-       counterField = "counter"
-       summaryField = "summary"
+       minField  = "min"
+       maxField  = "max"
+       sumField  = "sum"
+       avgField  = "avg"
+       lastField = "last"
 
        totalField      = "total"
        processingField = "processing"
diff --git a/metrics/prometheus/metric_set.go b/metrics/prometheus/metric_set.go
index 79c020369..115c6ca3d 100644
--- a/metrics/prometheus/metric_set.go
+++ b/metrics/prometheus/metric_set.go
@@ -29,40 +29,56 @@ import (
        "dubbo.apache.org/dubbo-go/v3/metrics"
 )
 
-// metricSet is a set of metrics that are reported to prometheus in dubbo go
+// metricSet is a set of metrics that are reported to prometheus in dubbo-go
 type metricSet struct {
-       // report the consumer-side's rt gauge data
-       consumerRTSummaryVec *prometheus.SummaryVec
-       // report the provider-side's rt gauge data
-       providerRTSummaryVec *prometheus.SummaryVec
+       provider providerMetrics
+       consumer consumerMetrics
+}
+
+func (ms *metricSet) init(reporterConfig *metrics.ReporterConfig) {
+       ms.provider.init(reporterConfig)
+       ms.consumer.init(reporterConfig)
+}
 
-       // report the provider-side's request total counter data
-       providerRequestsTotalCounterVec *prometheus.CounterVec
-       // report the provider-side's processing request counter data
-       providerRequestsProcessingTotalGaugeVec *prometheus.GaugeVec
-       // The number of requests successfully received by the provider
-       providerRequestsSucceedTotalCounterVec *prometheus.CounterVec
+type rpcCommonMetrics struct {
+       requestsTotal           *prometheus.CounterVec
+       requestsProcessingTotal *prometheus.GaugeVec
+       requestsSucceedTotal    *prometheus.CounterVec
+       rtMillisecondsMin       *GaugeVecWithSyncMap
+       rtMillisecondsMax       *GaugeVecWithSyncMap
+       rtMillisecondsSum       *prometheus.CounterVec
+       rtMillisecondsAvg       *GaugeVecWithSyncMap
+       rtMillisecondsLast      *prometheus.GaugeVec
+}
 
-       // report the consumer-side's request total counter data
-       consumerRequestsTotalCounterVec *prometheus.CounterVec
-       // report the consumer-side's processing request counter data
-       consumerRequestsProcessingTotalGaugeVec *prometheus.GaugeVec
-       // The number of successful requests sent by consumers
-       consumerRequestsSucceedTotalCounterVec *prometheus.CounterVec
+type providerMetrics struct {
+       rpcCommonMetrics
 }
 
-var labelNames = []string{applicationNameKey, groupKey, hostnameKey, 
interfaceKey, ipKey, methodKey, versionKey}
+func (pm *providerMetrics) init(reporterConfig *metrics.ReporterConfig) {
+       pm.requestsTotal = newAutoCounterVec(buildMetricsName(providerField, 
requestsField, totalField), 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.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)
+}
+
+type consumerMetrics struct {
+       rpcCommonMetrics
+}
 
-// init metric set and register to prometheus
-func (ms *metricSet) initAndRegister(reporterConfig *metrics.ReporterConfig) {
-       ms.consumerRTSummaryVec = 
newAutoSummaryVec(buildMetricsName(consumerField, rtField, milliSecondsField, 
summaryField), reporterConfig.Namespace, labelNames, 
reporterConfig.SummaryMaxAge)
-       ms.providerRTSummaryVec = 
newAutoSummaryVec(buildMetricsName(providerField, rtField, milliSecondsField, 
summaryField), reporterConfig.Namespace, labelNames, 
reporterConfig.SummaryMaxAge)
-       ms.consumerRequestsTotalCounterVec = 
newAutoCounterVec(buildMetricsName(consumerField, requestsField, totalField), 
reporterConfig.Namespace, labelNames)
-       ms.providerRequestsTotalCounterVec = 
newAutoCounterVec(buildMetricsName(providerField, requestsField, totalField), 
reporterConfig.Namespace, labelNames)
-       ms.consumerRequestsProcessingTotalGaugeVec = 
newAutoGaugeVec(buildMetricsName(consumerField, requestsField, processingField, 
totalField), reporterConfig.Namespace, labelNames)
-       ms.providerRequestsProcessingTotalGaugeVec = 
newAutoGaugeVec(buildMetricsName(providerField, requestsField, processingField, 
totalField), reporterConfig.Namespace, labelNames)
-       ms.consumerRequestsSucceedTotalCounterVec = 
newAutoCounterVec(buildMetricsName(consumerField, requestsField, succeedField, 
totalField), reporterConfig.Namespace, labelNames)
-       ms.providerRequestsSucceedTotalCounterVec = 
newAutoCounterVec(buildMetricsName(providerField, requestsField, succeedField, 
totalField), reporterConfig.Namespace, labelNames)
+func (cm *consumerMetrics) init(reporterConfig *metrics.ReporterConfig) {
+       cm.requestsTotal = newAutoCounterVec(buildMetricsName(consumerField, 
requestsField, totalField), 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.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)
 }
 
 func buildMetricsName(args ...string) string {
diff --git a/metrics/prometheus/common.go b/metrics/prometheus/model.go
similarity index 57%
rename from metrics/prometheus/common.go
rename to metrics/prometheus/model.go
index 32137d1e2..d62734f8f 100644
--- a/metrics/prometheus/common.go
+++ b/metrics/prometheus/model.go
@@ -18,63 +18,17 @@
 package prometheus
 
 import (
-       "strconv"
        "strings"
+       "sync"
+       "sync/atomic"
        "time"
 )
 
 import (
-       "github.com/dubbogo/gost/log/logger"
        "github.com/prometheus/client_golang/prometheus"
        "github.com/prometheus/client_golang/prometheus/promauto"
 )
 
-import (
-       "dubbo.apache.org/dubbo-go/v3/common"
-       "dubbo.apache.org/dubbo-go/v3/common/constant"
-)
-
-var (
-       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, ""),
-       }
-}
-
-// return the role of the application, provider or consumer, if the url is not 
a valid one, return empty string
-func getRole(url *common.URL) (role string) {
-       if isProvider(url) {
-               role = providerField
-       } else if isConsumer(url) {
-               role = consumerField
-       } else {
-               logger.Warnf("The url belongs neither the consumer nor the 
provider, "+
-                       "so the invocation will be ignored. url: %s", 
url.String())
-       }
-       return
-}
-
-// isProvider shows whether this url represents the application received the 
request as server
-func isProvider(url *common.URL) bool {
-       role := url.GetParam(constant.RegistryRoleKey, "")
-       return strings.EqualFold(role, strconv.Itoa(common.PROVIDER))
-}
-
-// isConsumer shows whether this url represents the application sent then 
request as client
-func isConsumer(url *common.URL) bool {
-       role := url.GetParam(constant.RegistryRoleKey, "")
-       return strings.EqualFold(role, strconv.Itoa(common.CONSUMER))
-}
-
 func newHistogramVec(name, namespace string, labels []string) 
*prometheus.HistogramVec {
        return prometheus.NewHistogramVec(
                prometheus.HistogramOpts{
@@ -194,3 +148,108 @@ func newAutoSummaryVec(name, namespace string, labels 
[]string, maxAge int64) *p
                labels,
        )
 }
+
+type GaugeVecWithSyncMap struct {
+       GaugeVec *prometheus.GaugeVec
+       SyncMap  *sync.Map
+}
+
+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
+               }
+       }
+}
diff --git a/metrics/prometheus/reporter.go b/metrics/prometheus/reporter.go
index 8c38c6114..7ca4398bf 100644
--- a/metrics/prometheus/reporter.go
+++ b/metrics/prometheus/reporter.go
@@ -21,6 +21,7 @@ import (
        "context"
        "net/http"
        "sync"
+       "time"
 )
 
 import (
@@ -32,6 +33,7 @@ import (
 import (
        "dubbo.apache.org/dubbo-go/v3/common/extension"
        "dubbo.apache.org/dubbo-go/v3/metrics"
+       "dubbo.apache.org/dubbo-go/v3/protocol"
 )
 
 var (
@@ -62,7 +64,7 @@ func newPrometheusReporter(reporterConfig 
*metrics.ReporterConfig) metrics.Repor
        if reporterInstance == nil {
                reporterInitOnce.Do(func() {
                        ms := &metricSet{}
-                       ms.initAndRegister(reporterConfig)
+                       ms.init(reporterConfig)
                        reporterInstance = &PrometheusReporter{
                                reporterConfig: reporterConfig,
                                namespace:      reporterConfig.Namespace,
@@ -103,47 +105,92 @@ func (reporter *PrometheusReporter) shutdownServer() {
        }
 }
 
-func (reporter *PrometheusReporter) reportRTSummaryVec(role string, labels 
*prometheus.Labels, costMs int64) {
+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.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) incRequestsTotal(role string, labels 
*prometheus.Labels) {
        switch role {
        case providerField:
-               
reporter.providerRTSummaryVec.With(*labels).Observe(float64(costMs))
+               reporter.provider.requestsTotal.With(*labels).Inc()
        case consumerField:
-               
reporter.consumerRTSummaryVec.With(*labels).Observe(float64(costMs))
+               reporter.consumer.requestsTotal.With(*labels).Inc()
        }
 }
 
-func (reporter *PrometheusReporter) reportRequestsTotalCounterVec(role string, 
labels *prometheus.Labels) {
+func (reporter *PrometheusReporter) incRequestsProcessingTotal(role string, 
labels *prometheus.Labels) {
        switch role {
        case providerField:
-               reporter.providerRequestsTotalCounterVec.With(*labels).Inc()
+               reporter.provider.requestsProcessingTotal.With(*labels).Inc()
        case consumerField:
-               reporter.consumerRequestsTotalCounterVec.With(*labels).Inc()
+               reporter.consumer.requestsProcessingTotal.With(*labels).Inc()
        }
 }
 
-func (reporter *PrometheusReporter) incRequestsProcessingTotalGaugeVec(role 
string, labels *prometheus.Labels) {
+func (reporter *PrometheusReporter) decRequestsProcessingTotal(role string, 
labels *prometheus.Labels) {
        switch role {
        case providerField:
-               
reporter.providerRequestsProcessingTotalGaugeVec.With(*labels).Inc()
+               reporter.provider.requestsProcessingTotal.With(*labels).Dec()
        case consumerField:
-               
reporter.consumerRequestsProcessingTotalGaugeVec.With(*labels).Inc()
+               reporter.consumer.requestsProcessingTotal.With(*labels).Dec()
        }
 }
 
-func (reporter *PrometheusReporter) decRequestsProcessingTotalGaugeVec(role 
string, labels *prometheus.Labels) {
+func (reporter *PrometheusReporter) incRequestsSucceedTotal(role string, 
labels *prometheus.Labels) {
        switch role {
        case providerField:
-               
reporter.providerRequestsProcessingTotalGaugeVec.With(*labels).Dec()
+               reporter.provider.requestsSucceedTotal.With(*labels).Inc()
        case consumerField:
-               
reporter.consumerRequestsProcessingTotalGaugeVec.With(*labels).Dec()
+               reporter.consumer.requestsSucceedTotal.With(*labels).Inc()
        }
 }
 
-func (reporter *PrometheusReporter) incRequestsSucceedTotalCounterVec(role 
string, labels *prometheus.Labels) {
+func (reporter *PrometheusReporter) reportRTMilliseconds(role string, labels 
*prometheus.Labels, costMs int64) {
        switch role {
        case providerField:
-               
reporter.providerRequestsSucceedTotalCounterVec.With(*labels).Inc()
+               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)
        case consumerField:
-               
reporter.consumerRequestsSucceedTotalCounterVec.With(*labels).Inc()
+               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)
        }
 }
diff --git a/metrics/prometheus/util.go b/metrics/prometheus/util.go
new file mode 100644
index 000000000..4e1a9c8dc
--- /dev/null
+++ b/metrics/prometheus/util.go
@@ -0,0 +1,75 @@
+/*
+ * 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 (
+       "strconv"
+       "strings"
+)
+
+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"
+)
+
+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, ""),
+       }
+}
+
+// return the role of the application, provider or consumer, if the url is not 
a valid one, return empty string
+func getRole(url *common.URL) (role string) {
+       if isProvider(url) {
+               role = providerField
+       } else if isConsumer(url) {
+               role = consumerField
+       } else {
+               logger.Warnf("The url belongs neither the consumer nor the 
provider, "+
+                       "so the invocation will be ignored. url: %s", 
url.String())
+       }
+       return
+}
+
+// isProvider shows whether this url represents the application received the 
request as server
+func isProvider(url *common.URL) bool {
+       role := url.GetParam(constant.RegistryRoleKey, "")
+       return strings.EqualFold(role, strconv.Itoa(common.PROVIDER))
+}
+
+// isConsumer shows whether this url represents the application sent then 
request as client
+func isConsumer(url *common.URL) bool {
+       role := url.GetParam(constant.RegistryRoleKey, "")
+       return strings.EqualFold(role, strconv.Itoa(common.CONSUMER))
+}

Reply via email to