feat: add request processing total and request succeed total metrics (#2331)
diff --git a/common/extension/metrics_test.go b/common/extension/metrics_test.go
index 4739516..30df7d3 100644
--- a/common/extension/metrics_test.go
+++ b/common/extension/metrics_test.go
@@ -40,5 +40,8 @@
type mockReporter struct{}
// implement the interface of Reporter
-func (m mockReporter) ReportAfterInvocation(ctx context.Context, invoker protocol.Invoker, invocation protocol.Invocation, cost time.Duration, res protocol.Result) {
+func (m *mockReporter) ReportAfterInvocation(ctx context.Context, invoker protocol.Invoker, invocation protocol.Invocation, cost time.Duration, res protocol.Result) {
+}
+
+func (m *mockReporter) ReportBeforeInvocation(ctx context.Context, invoker protocol.Invoker, invocation protocol.Invocation) {
}
diff --git a/filter/metrics/filter.go b/filter/metrics/filter.go
index 9782c0d..3e36404 100644
--- a/filter/metrics/filter.go
+++ b/filter/metrics/filter.go
@@ -44,6 +44,11 @@
// Invoke collect the duration of invocation and then report the duration by using goroutine
func (p *Filter) Invoke(ctx context.Context, invoker protocol.Invoker, invocation protocol.Invocation) protocol.Result {
+ go func() {
+ for _, reporter := range p.reporters {
+ reporter.ReportBeforeInvocation(ctx, invoker, invocation)
+ }
+ }()
start := time.Now()
res := invoker.Invoke(ctx, invocation)
end := time.Now()
diff --git a/filter/metrics/filter_test.go b/filter/metrics/filter_test.go
index c12247d..f18b760 100644
--- a/filter/metrics/filter_test.go
+++ b/filter/metrics/filter_test.go
@@ -76,3 +76,8 @@
m.Called(ctx, invoker, invocation)
m.wg.Done()
}
+
+func (m *mockReporter) ReportBeforeInvocation(ctx context.Context, invoker protocol.Invoker, invocation protocol.Invocation) {
+ m.Called(ctx, invoker, invocation)
+ m.wg.Done()
+}
diff --git a/metrics/prometheus/after_invocation.go b/metrics/prometheus/after_invocation.go
index 62e0501..f1235a2 100644
--- a/metrics/prometheus/after_invocation.go
+++ b/metrics/prometheus/after_invocation.go
@@ -23,61 +23,27 @@
)
import (
- "dubbo.apache.org/dubbo-go/v3/common"
- "dubbo.apache.org/dubbo-go/v3/common/constant"
"dubbo.apache.org/dubbo-go/v3/protocol"
)
-import (
- "github.com/dubbogo/gost/log/logger"
- "github.com/prometheus/client_golang/prometheus"
-)
-
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()
- var role string // provider or consumer
- 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())
+ role := getRole(url)
+ if role == "" {
return
}
- labels := prometheus.Labels{
- applicationNameKey: url.GetParam(constant.ApplicationKey, ""),
- groupKey: url.Group(),
- hostnameKey: "",
- interfaceKey: url.Service(),
- ipKey: common.GetLocalIp(),
- versionKey: url.GetParam(constant.AppVersionKey, ""),
- methodKey: invocation.MethodName(),
- }
+ labels := buildLabels(url)
reporter.reportRTSummaryVec(role, &labels, cost.Milliseconds())
- reporter.reportRequestTotalCounterVec(role, &labels)
-}
+ reporter.reportRequestsTotalCounterVec(role, &labels)
+ reporter.decRequestsProcessingTotalGaugeVec(role, &labels)
-func (r *PrometheusReporter) reportRTSummaryVec(role string, labels *prometheus.Labels, costMs int64) {
- switch role {
- case providerField:
- r.providerRTSummaryVec.With(*labels).Observe(float64(costMs))
- case consumerField:
- r.consumerRTSummaryVec.With(*labels).Observe(float64(costMs))
- }
-}
-
-func (r *PrometheusReporter) reportRequestTotalCounterVec(role string, labels *prometheus.Labels) {
- switch role {
- case providerField:
- r.providerRequestTotalCounterVec.With(*labels).Inc()
- case consumerField:
- r.consumerRequestTotalCounterVec.With(*labels).Inc()
+ 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
index aa288e5..7477b13 100644
--- a/metrics/prometheus/before_invocation.go
+++ b/metrics/prometheus/before_invocation.go
@@ -16,3 +16,25 @@
*/
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/common.go b/metrics/prometheus/common.go
index 7df0389..32137d1 100644
--- a/metrics/prometheus/common.go
+++ b/metrics/prometheus/common.go
@@ -24,6 +24,7 @@
)
import (
+ "github.com/dubbogo/gost/log/logger"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
)
@@ -33,6 +34,35 @@
"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, "")
diff --git a/metrics/prometheus/constant.go b/metrics/prometheus/constant.go
index b4d5e1c..95e090d 100644
--- a/metrics/prometheus/constant.go
+++ b/metrics/prometheus/constant.go
@@ -41,5 +41,7 @@
counterField = "counter"
summaryField = "summary"
- totalField = "total"
+ totalField = "total"
+ processingField = "processing"
+ succeedField = "succeed"
)
diff --git a/metrics/prometheus/metric_set.go b/metrics/prometheus/metric_set.go
index 4226771..79c0203 100644
--- a/metrics/prometheus/metric_set.go
+++ b/metrics/prometheus/metric_set.go
@@ -35,14 +35,20 @@
consumerRTSummaryVec *prometheus.SummaryVec
// report the provider-side's rt gauge data
providerRTSummaryVec *prometheus.SummaryVec
+
// report the provider-side's request total counter data
- providerRequestTotalCounterVec *prometheus.CounterVec
- // report the consumer-side's request total counter data
- consumerRequestTotalCounterVec *prometheus.CounterVec
+ providerRequestsTotalCounterVec *prometheus.CounterVec
// report the provider-side's processing request counter data
- // providerRequestProcessingGaugeVec *prometheus.GaugeVec
+ providerRequestsProcessingTotalGaugeVec *prometheus.GaugeVec
+ // The number of requests successfully received by the provider
+ providerRequestsSucceedTotalCounterVec *prometheus.CounterVec
+
+ // report the consumer-side's request total counter data
+ consumerRequestsTotalCounterVec *prometheus.CounterVec
// report the consumer-side's processing request counter data
- // consumerRequestProcessingGaugeVec *prometheus.GaugeVec
+ consumerRequestsProcessingTotalGaugeVec *prometheus.GaugeVec
+ // The number of successful requests sent by consumers
+ consumerRequestsSucceedTotalCounterVec *prometheus.CounterVec
}
var labelNames = []string{applicationNameKey, groupKey, hostnameKey, interfaceKey, ipKey, methodKey, versionKey}
@@ -51,8 +57,12 @@
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.consumerRequestTotalCounterVec = newAutoCounterVec(buildMetricsName(consumerField, requestsField, totalField), reporterConfig.Namespace, labelNames)
- ms.providerRequestTotalCounterVec = newAutoCounterVec(buildMetricsName(providerField, requestsField, totalField), reporterConfig.Namespace, labelNames)
+ 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 buildMetricsName(args ...string) string {
diff --git a/metrics/prometheus/reporter.go b/metrics/prometheus/reporter.go
index 249510f..8c38c61 100644
--- a/metrics/prometheus/reporter.go
+++ b/metrics/prometheus/reporter.go
@@ -25,6 +25,7 @@
import (
"github.com/dubbogo/gost/log/logger"
+ "github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
)
@@ -34,9 +35,8 @@
)
var (
- reporterInstance *PrometheusReporter
- reporterInitOnce sync.Once
- defaultHistogramBucket = []float64{10, 50, 100, 200, 500, 1000, 10000}
+ reporterInstance *PrometheusReporter
+ reporterInitOnce sync.Once
)
// should initialize after loading configuration
@@ -102,3 +102,48 @@
}
}
}
+
+func (reporter *PrometheusReporter) reportRTSummaryVec(role string, labels *prometheus.Labels, costMs int64) {
+ switch role {
+ case providerField:
+ reporter.providerRTSummaryVec.With(*labels).Observe(float64(costMs))
+ case consumerField:
+ reporter.consumerRTSummaryVec.With(*labels).Observe(float64(costMs))
+ }
+}
+
+func (reporter *PrometheusReporter) reportRequestsTotalCounterVec(role string, labels *prometheus.Labels) {
+ switch role {
+ case providerField:
+ reporter.providerRequestsTotalCounterVec.With(*labels).Inc()
+ case consumerField:
+ reporter.consumerRequestsTotalCounterVec.With(*labels).Inc()
+ }
+}
+
+func (reporter *PrometheusReporter) incRequestsProcessingTotalGaugeVec(role string, labels *prometheus.Labels) {
+ switch role {
+ case providerField:
+ reporter.providerRequestsProcessingTotalGaugeVec.With(*labels).Inc()
+ case consumerField:
+ reporter.consumerRequestsProcessingTotalGaugeVec.With(*labels).Inc()
+ }
+}
+
+func (reporter *PrometheusReporter) decRequestsProcessingTotalGaugeVec(role string, labels *prometheus.Labels) {
+ switch role {
+ case providerField:
+ reporter.providerRequestsProcessingTotalGaugeVec.With(*labels).Dec()
+ case consumerField:
+ reporter.consumerRequestsProcessingTotalGaugeVec.With(*labels).Dec()
+ }
+}
+
+func (reporter *PrometheusReporter) incRequestsSucceedTotalCounterVec(role string, labels *prometheus.Labels) {
+ switch role {
+ case providerField:
+ reporter.providerRequestsSucceedTotalCounterVec.With(*labels).Inc()
+ case consumerField:
+ reporter.consumerRequestsSucceedTotalCounterVec.With(*labels).Inc()
+ }
+}
diff --git a/metrics/prometheus/reporter_test.go b/metrics/prometheus/reporter_test.go
index af3def4..de4283e 100644
--- a/metrics/prometheus/reporter_test.go
+++ b/metrics/prometheus/reporter_test.go
@@ -50,6 +50,7 @@
assert.False(t, isConsumer(url))
ctx := context.Background()
+ reporter.ReportBeforeInvocation(ctx, invoker, inv)
reporter.ReportAfterInvocation(ctx, invoker, inv, 100*time.Millisecond, nil)
// consumer side
@@ -60,6 +61,7 @@
"BDTService&organization=ikurento.com&owner=ZX®istry.role=0&retries=&" +
"service.filter=echo%2Ctoken%2Caccesslog×tamp=1569153406&token=934804bf-b007-4174-94eb-96e3e1d60cc7&version=&warmup=100")
invoker = protocol.NewBaseInvoker(url)
+ reporter.ReportBeforeInvocation(ctx, invoker, inv)
reporter.ReportAfterInvocation(ctx, invoker, inv, 100*time.Millisecond, nil)
// invalid role
@@ -70,5 +72,6 @@
"BDTService&organization=ikurento.com&owner=ZX®istry.role=9&retries=&" +
"service.filter=echo%2Ctoken%2Caccesslog×tamp=1569153406&token=934804bf-b007-4174-94eb-96e3e1d60cc7&version=&warmup=100")
invoker = protocol.NewBaseInvoker(url)
+ reporter.ReportBeforeInvocation(ctx, invoker, inv)
reporter.ReportAfterInvocation(ctx, invoker, inv, 100*time.Millisecond, nil)
}
diff --git a/metrics/reporter.go b/metrics/reporter.go
index 9439f02..604d412 100644
--- a/metrics/reporter.go
+++ b/metrics/reporter.go
@@ -63,4 +63,5 @@
type Reporter interface {
ReportAfterInvocation(ctx context.Context, invoker protocol.Invoker, invocation protocol.Invocation,
cost time.Duration, res protocol.Result)
+ ReportBeforeInvocation(ctx context.Context, invoker protocol.Invoker, invocation protocol.Invocation)
}