diff --git a/integration/simple_test.go b/integration/simple_test.go index 0972abf71..9bbce5ba5 100644 --- a/integration/simple_test.go +++ b/integration/simple_test.go @@ -333,21 +333,24 @@ func (s *SimpleSuite) TestMetricsPrometheusTwoRoutersOneService(c *check.C) { err = try.GetRequest("http://127.0.0.1:8000/whoami2", 1*time.Second, try.StatusCodeIs(http.StatusOK)) c.Assert(err, checker.IsNil) - request, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8080/metrics", nil) - c.Assert(err, checker.IsNil) + // adding a loop to test if metrics are not deleted + for i := 0; i < 10; i++ { + request, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8080/metrics", nil) + c.Assert(err, checker.IsNil) - response, err := http.DefaultClient.Do(request) - c.Assert(err, checker.IsNil) - c.Assert(response.StatusCode, checker.Equals, http.StatusOK) + response, err := http.DefaultClient.Do(request) + c.Assert(err, checker.IsNil) + c.Assert(response.StatusCode, checker.Equals, http.StatusOK) - body, err := io.ReadAll(response.Body) - c.Assert(err, checker.IsNil) + body, err := io.ReadAll(response.Body) + c.Assert(err, checker.IsNil) - // Reqs count of 1 for both routers - c.Assert(string(body), checker.Contains, "traefik_router_requests_total{code=\"200\",method=\"GET\",protocol=\"http\",router=\"router1@docker\",service=\"whoami1-integrationtestbase\"} 1") - c.Assert(string(body), checker.Contains, "traefik_router_requests_total{code=\"200\",method=\"GET\",protocol=\"http\",router=\"router2@docker\",service=\"whoami1-integrationtestbase\"} 1") - // Reqs count of 2 for service behind both routers - c.Assert(string(body), checker.Contains, "traefik_service_requests_total{code=\"200\",method=\"GET\",protocol=\"http\",service=\"whoami1-integrationtestbase@docker\"} 2") + // Reqs count of 1 for both routers + c.Assert(string(body), checker.Contains, "traefik_router_requests_total{code=\"200\",method=\"GET\",protocol=\"http\",router=\"router1@docker\",service=\"whoami1-integrationtestbase@docker\"} 1") + c.Assert(string(body), checker.Contains, "traefik_router_requests_total{code=\"200\",method=\"GET\",protocol=\"http\",router=\"router2@docker\",service=\"whoami1-integrationtestbase@docker\"} 1") + // Reqs count of 2 for service behind both routers + c.Assert(string(body), checker.Contains, "traefik_service_requests_total{code=\"200\",method=\"GET\",protocol=\"http\",service=\"whoami1-integrationtestbase@docker\"} 2") + } } func (s *SimpleSuite) TestMultipleProviderSameBackendName(c *check.C) { diff --git a/pkg/metrics/prometheus.go b/pkg/metrics/prometheus.go index f98752726..745a74c2f 100644 --- a/pkg/metrics/prometheus.go +++ b/pkg/metrics/prometheus.go @@ -380,6 +380,12 @@ func (ps *prometheusState) isOutdated(collector *collector) bool { return true } + if routerName, ok := labels["router"]; ok { + if !ps.dynamicConfig.hasRouter(routerName) { + return true + } + } + if serviceName, ok := labels["service"]; ok { if !ps.dynamicConfig.hasService(serviceName) { return true @@ -420,6 +426,11 @@ func (d *dynamicConfig) hasService(serviceName string) bool { return ok } +func (d *dynamicConfig) hasRouter(routerName string) bool { + _, ok := d.routers[routerName] + return ok +} + func (d *dynamicConfig) hasServerURL(serviceName, serverURL string) bool { if service, hasService := d.services[serviceName]; hasService { _, ok := service[serverURL] diff --git a/pkg/metrics/prometheus_test.go b/pkg/metrics/prometheus_test.go index 4a4ce235d..7e1154a03 100644 --- a/pkg/metrics/prometheus_test.go +++ b/pkg/metrics/prometheus_test.go @@ -364,7 +364,7 @@ func TestPrometheusMetricRemoval(t *testing.T) { // Reset state of global promState. defer promState.reset() - prometheusRegistry := RegisterPrometheus(context.Background(), &types.Prometheus{AddEntryPointsLabels: true, AddServicesLabels: true}) + prometheusRegistry := RegisterPrometheus(context.Background(), &types.Prometheus{AddEntryPointsLabels: true, AddServicesLabels: true, AddRoutersLabels: true}) defer promRegistry.Unregister(promState) conf := dynamic.Configuration{ @@ -401,11 +401,14 @@ func TestPrometheusMetricRemoval(t *testing.T) { ServiceServerUpGauge(). With("service", "service1", "url", "http://localhost:9999"). Set(1) - - delayForTrackingCompletion() + prometheusRegistry. + RouterReqsCounter(). + With("router", "router2", "service", "service2", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet, "protocol", "http"). + Add(1) assertMetricsExist(t, mustScrape(), entryPointReqsTotalName, serviceReqsTotalName, serviceServerUpName) assertMetricsAbsent(t, mustScrape(), entryPointReqsTotalName, serviceReqsTotalName, serviceServerUpName) + assertMetricsAbsent(t, mustScrape(), routerReqsTotalName, routerReqDurationName, routerOpenConnsName) // To verify that metrics belonging to active configurations are not removed // here the counter examples. @@ -413,11 +416,17 @@ func TestPrometheusMetricRemoval(t *testing.T) { EntryPointReqsCounter(). With("entrypoint", "entrypoint1", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet, "protocol", "http"). Add(1) + prometheusRegistry. + RouterReqsCounter(). + With("router", "foo@providerName", "service", "bar@providerName", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet, "protocol", "http"). + Add(1) delayForTrackingCompletion() assertMetricsExist(t, mustScrape(), entryPointReqsTotalName) assertMetricsExist(t, mustScrape(), entryPointReqsTotalName) + assertMetricsExist(t, mustScrape(), routerReqsTotalName) + assertMetricsExist(t, mustScrape(), routerReqsTotalName) } func TestPrometheusRemovedMetricsReset(t *testing.T) { diff --git a/pkg/server/router/router.go b/pkg/server/router/router.go index 285120989..7f9c40d0f 100644 --- a/pkg/server/router/router.go +++ b/pkg/server/router/router.go @@ -184,7 +184,7 @@ func (m *Manager) buildHTTPHandler(ctx context.Context, router *runtime.RouterIn chain := alice.New() if m.metricsRegistry != nil && m.metricsRegistry.IsRouterEnabled() { - chain = chain.Append(metricsMiddle.WrapRouterHandler(ctx, m.metricsRegistry, routerName, router.Service)) + chain = chain.Append(metricsMiddle.WrapRouterHandler(ctx, m.metricsRegistry, routerName, provider.GetQualifiedName(ctx, router.Service))) } return chain.Extend(*mHandler).Append(tHandler).Then(sHandler)