Skip to content

Commit bc7cf9a

Browse files
committed
metrics: remove invalid routes deletion
When validation is enabled and a new invalid route is created, it gets rejected and a metric is emitted. But when the route is later fixed, the old metric is not removed. Once the route is fixed, there is no error, so the corrected route no longer matches the old metric key.
1 parent 19bd6bb commit bc7cf9a

File tree

10 files changed

+27
-99
lines changed

10 files changed

+27
-99
lines changed

metrics/all_kind.go

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -136,11 +136,6 @@ func (a *All) SetInvalidRoute(routeId, reason string) {
136136
a.codaHale.SetInvalidRoute(routeId, reason)
137137
}
138138

139-
func (a *All) DeleteInvalidRoute(routeId string) {
140-
a.prometheus.DeleteInvalidRoute(routeId)
141-
a.codaHale.DeleteInvalidRoute(routeId)
142-
}
143-
144139
func (a *All) Close() {
145140
a.codaHale.Close()
146141
a.prometheus.Close()

metrics/codahale.go

Lines changed: 7 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import (
66
"net/http"
77
"path"
88
"strings"
9-
"sync"
109
"time"
1110

1211
"github.com/rcrowley/go-metrics"
@@ -45,15 +44,13 @@ const (
4544

4645
// CodaHale is the CodaHale format backend, implements Metrics interface in DropWizard's CodaHale metrics format.
4746
type CodaHale struct {
48-
reg metrics.Registry
49-
createTimer func() metrics.Timer
50-
createCounter func() metrics.Counter
51-
createGauge func() metrics.GaugeFloat64
52-
options Options
53-
handler http.Handler
54-
quit chan struct{}
55-
invalidRoutesMu sync.RWMutex
56-
invalidRoutes map[string]string // routeId -> metric key
47+
reg metrics.Registry
48+
createTimer func() metrics.Timer
49+
createCounter func() metrics.Counter
50+
createGauge func() metrics.GaugeFloat64
51+
options Options
52+
handler http.Handler
53+
quit chan struct{}
5754
}
5855

5956
// NewCodaHale returns a new CodaHale backend of metrics.
@@ -64,7 +61,6 @@ func NewCodaHale(o Options) *CodaHale {
6461

6562
c.quit = make(chan struct{})
6663
c.reg = metrics.NewRegistry()
67-
c.invalidRoutes = make(map[string]string)
6864

6965
var createSample func() metrics.Sample
7066
if o.UseExpDecaySample {
@@ -270,24 +266,10 @@ func (c *CodaHale) IncErrorsStreaming(routeId string) {
270266
}
271267

272268
func (c *CodaHale) SetInvalidRoute(routeId, reason string) {
273-
c.invalidRoutesMu.Lock()
274-
defer c.invalidRoutesMu.Unlock()
275-
276269
key := fmt.Sprintf(KeyInvalidRoutes, routeId, reason)
277-
c.invalidRoutes[routeId] = key
278270
c.UpdateGauge(key, 1)
279271
}
280272

281-
func (c *CodaHale) DeleteInvalidRoute(routeId string) {
282-
c.invalidRoutesMu.Lock()
283-
defer c.invalidRoutesMu.Unlock()
284-
285-
if key, exists := c.invalidRoutes[routeId]; exists {
286-
c.UpdateGauge(key, 0)
287-
delete(c.invalidRoutes, routeId)
288-
}
289-
}
290-
291273
func (c *CodaHale) Close() {
292274
close(c.quit)
293275
}

metrics/metrics.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,6 @@ type Metrics interface {
8181
RegisterHandler(path string, handler *http.ServeMux)
8282
UpdateGauge(key string, value float64)
8383
SetInvalidRoute(routeId, reason string)
84-
DeleteInvalidRoute(routeId string)
8584
Close()
8685
}
8786

metrics/metricstest/metricsmock.go

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ package metricstest
55
import (
66
"fmt"
77
"net/http"
8-
"strings"
98
"sync"
109
"time"
1110
)
@@ -230,15 +229,4 @@ func (m *MockMetrics) SetInvalidRoute(routeID, reason string) {
230229
m.UpdateGauge(key, 1)
231230
}
232231

233-
func (m *MockMetrics) DeleteInvalidRoute(routeID string) {
234-
m.WithGauges(func(gauges map[string]float64) {
235-
prefix := fmt.Sprintf("route.invalid.%s.", routeID)
236-
for key := range gauges {
237-
if strings.HasPrefix(key, prefix) {
238-
gauges[key] = 0
239-
}
240-
}
241-
})
242-
}
243-
244232
func (*MockMetrics) Close() {}

metrics/metricstest/metricsmock_test.go

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ func TestMockMetrics(t *testing.T) {
165165
}
166166
})
167167

168-
t.Run("test-measure-backend-request-header", func(t *testing.T) {
168+
t.Run("test-set-invalid-route", func(t *testing.T) {
169169
routeID := "my-route"
170170
reason := "foo"
171171
key := fmt.Sprintf("route.invalid.%s..%s", routeID, reason)
@@ -177,13 +177,6 @@ func TestMockMetrics(t *testing.T) {
177177
} else if f != 1 {
178178
t.Fatalf("Failed to get the right value after inc: %0.2f", f)
179179
}
180-
181-
m.DeleteInvalidRoute(routeID)
182-
if f, ok := m.gauges[key]; !ok {
183-
t.Fatalf("Failed to find value %q for routeID %q", key, routeID)
184-
} else if f != 0 {
185-
t.Fatalf("Failed to get the right value after inc: %0.2f", f)
186-
}
187180
})
188181

189182
t.Run("test-gauge", func(t *testing.T) {

metrics/prometheus.go

Lines changed: 2 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import (
44
"fmt"
55
"net/http"
66
"strings"
7-
"sync"
87
"time"
98

109
"github.com/prometheus/client_golang/prometheus"
@@ -74,10 +73,6 @@ type Prometheus struct {
7473
customGaugeM *prometheus.GaugeVec
7574
invalidRouteM *prometheus.GaugeVec
7675

77-
// Track invalid route metrics for proper cleanup
78-
invalidRoutesMu sync.RWMutex
79-
invalidRouteLabels map[string][]prometheus.Labels // routeId -> []labels
80-
8176
opts Options
8277
registry *prometheus.Registry
8378
handler http.Handler
@@ -88,9 +83,8 @@ func NewPrometheus(opts Options) *Prometheus {
8883
opts = applyCompatibilityDefaults(opts)
8984

9085
p := &Prometheus{
91-
registry: opts.PrometheusRegistry,
92-
opts: opts,
93-
invalidRouteLabels: make(map[string][]prometheus.Labels),
86+
registry: opts.PrometheusRegistry,
87+
opts: opts,
9488
}
9589

9690
if p.registry == nil {
@@ -537,25 +531,6 @@ func (p *Prometheus) IncErrorsStreaming(routeID string) {
537531
// SetInvalidRoute satisfies Metrics interface.
538532
func (p *Prometheus) SetInvalidRoute(routeId, reason string) {
539533
p.invalidRouteM.WithLabelValues(routeId, reason).Set(1)
540-
541-
p.invalidRoutesMu.Lock()
542-
defer p.invalidRoutesMu.Unlock()
543-
544-
labels := prometheus.Labels{"route_id": routeId, "reason": reason}
545-
p.invalidRouteLabels[routeId] = append(p.invalidRouteLabels[routeId], labels)
546-
}
547-
548-
// DeleteInvalidRoute satisfies Metrics interface.
549-
func (p *Prometheus) DeleteInvalidRoute(routeId string) {
550-
p.invalidRoutesMu.Lock()
551-
defer p.invalidRoutesMu.Unlock()
552-
553-
if labels, exists := p.invalidRouteLabels[routeId]; exists {
554-
for _, labelSet := range labels {
555-
p.invalidRouteM.With(labelSet).Set(0)
556-
}
557-
delete(p.invalidRouteLabels, routeId)
558-
}
559534
}
560535

561536
func (p *Prometheus) Close() {}

routing/datasource.go

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -475,7 +475,7 @@ func processTreePredicates(r *Route, predicateList []*eskip.Predicate) error {
475475
// ValidateRoute processes a route definition for the routing table.
476476
// This function is exported to be used by validation webhooks.
477477
func ValidateRoute(o *Options, def *eskip.Route) (*Route, error) {
478-
return processRouteDef(o, mapPredicates(o.Predicates), def)
478+
return processRouteDef(o, mapPredicates(o.Predicates), def) //
479479
}
480480

481481
// processes a route definition for the routing table
@@ -525,9 +525,6 @@ func processRouteDefs(o *Options, defs []*eskip.Route) (routes []*Route, invalid
525525
route, err := processRouteDef(o, cpm, def)
526526
if err == nil {
527527
routes = append(routes, route)
528-
if o.Metrics != nil {
529-
o.Metrics.DeleteInvalidRoute(def.Id)
530-
}
531528
} else {
532529
invalidDefs = append(invalidDefs, def)
533530
o.Log.Errorf("failed to process route %s: %v", def.Id, err)

routing/datasource_test.go

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -594,21 +594,21 @@ func waitForIndividualRouteMetrics(t *testing.T, metrics *metricstest.MockMetric
594594
}
595595
}
596596

597-
func TestRouteMetricsSetToZeroWhenFixed(t *testing.T) {
597+
func TestRouteMetricsStaySetWhenRouteIsFixed(t *testing.T) {
598598
t.Run("MockMetrics", func(t *testing.T) {
599599
synctest.Test(t, func(t *testing.T) {
600-
testRouteMetricsSetToZeroWhenFixedWithMock(t)
600+
testRouteMetricsStaySetWhenRouteIsFixedWithMock(t)
601601
})
602602
})
603603

604604
t.Run("Prometheus", func(t *testing.T) {
605605
synctest.Test(t, func(t *testing.T) {
606-
testRouteMetricsSetToZeroWhenFixedWithPrometheus(t)
606+
testRouteMetricsStaySetWhenRouteIsFixedWithPrometheus(t)
607607
})
608608
})
609609
}
610610

611-
func testRouteMetricsSetToZeroWhenFixedWithMock(t *testing.T) {
611+
func testRouteMetricsStaySetWhenRouteIsFixedWithMock(t *testing.T) {
612612
metrics := &metricstest.MockMetrics{}
613613

614614
// Start with an invalid route
@@ -649,16 +649,16 @@ func testRouteMetricsSetToZeroWhenFixedWithMock(t *testing.T) {
649649
// Wait for the update to be processed
650650
time.Sleep(50 * time.Millisecond)
651651

652-
// Verify the metric is now set to 0 (not deleted)
652+
// Verify the metric remains set (not deleted or zeroed out)
653653
metrics.WithGauges(func(gauges map[string]float64) {
654654
expectedKey := "route.invalid.invalidBackend1..failed_backend_split"
655-
if gauges[expectedKey] != 0 {
656-
t.Errorf("Expected invalid route metric to be set to 0 when route becomes valid, got %f", gauges[expectedKey])
655+
if gauges[expectedKey] != 1 {
656+
t.Errorf("Expected invalid route metric to stay set when route becomes valid, got %f", gauges[expectedKey])
657657
}
658658
})
659659
}
660660

661-
func testRouteMetricsSetToZeroWhenFixedWithPrometheus(t *testing.T) {
661+
func testRouteMetricsStaySetWhenRouteIsFixedWithPrometheus(t *testing.T) {
662662
pm := metrics.NewPrometheus(metrics.Options{})
663663
path := "/metrics"
664664

@@ -708,16 +708,16 @@ func testRouteMetricsSetToZeroWhenFixedWithPrometheus(t *testing.T) {
708708
// Wait for the update to be processed
709709
time.Sleep(50 * time.Millisecond)
710710

711-
// Check that the metric is now set to 0
711+
// Check that the metric stays set (not deleted or zeroed out)
712712
req = httptest.NewRequest("GET", path, nil)
713713
w = httptest.NewRecorder()
714714
mux.ServeHTTP(w, req)
715715
body, _ = io.ReadAll(w.Result().Body)
716716
output = string(body)
717717

718-
expectedZeroLine := `skipper_route_invalid{reason="failed_backend_split",route_id="invalidBackend1"} 0`
719-
if !strings.Contains(output, expectedZeroLine) {
720-
t.Errorf("Expected to find invalid route metric set to 0 when route becomes valid")
718+
expectedLine = `skipper_route_invalid{reason="failed_backend_split",route_id="invalidBackend1"} 1`
719+
if !strings.Contains(output, expectedLine) {
720+
t.Errorf("Expected invalid route metric to remain set when route becomes valid")
721721
t.Logf("Output: %s", output)
722722
}
723723
}

routing/errors.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ func WrapInvalidDefinitionReason(reason string, err error) error {
3030

3131
func HandleValidationError(mtr metrics.Metrics, err error, routeId string) error {
3232
if err == nil {
33-
mtr.DeleteInvalidRoute(routeId)
3433
return nil
3534
}
3635

routing/errors_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package routing
22

33
import (
44
"errors"
5+
"fmt"
56
"strings"
67
"testing"
78

@@ -87,10 +88,9 @@ func TestValidationErrorsNoError(t *testing.T) {
8788
}
8889

8990
mtr.WithGauges(func(g map[string]float64) {
90-
for k, v := range g {
91-
if strings.HasPrefix(k, "route.invalid") && v > 0 {
92-
t.Fatalf("Failed to have no invalid routes %q -> %0.2f", k, v)
93-
}
91+
key := fmt.Sprintf("route.invalid.%s..%s", routeID, errInvalidPredicateParams)
92+
if v := g[key]; v != 1 {
93+
t.Fatalf("Invalid route metric should remain set, got %0.2f", v)
9494
}
9595
})
9696
}

0 commit comments

Comments
 (0)