@@ -10,6 +10,7 @@ import (
1010 "time"
1111
1212 "github.com/stretchr/testify/assert"
13+ "github.com/zalando/skipper/eskip"
1314 "github.com/zalando/skipper/filters"
1415 "github.com/zalando/skipper/filters/builtin"
1516 "github.com/zalando/skipper/logging"
@@ -733,3 +734,96 @@ func testRouteValidationReasonMetricsWithPrometheus(t *testing.T, routes string,
733734 }
734735 }
735736}
737+
738+ func TestProcessRouteDefsMetricsInitialization (t * testing.T ) {
739+ pm := metrics .NewPrometheus (metrics.Options {})
740+ path := "/metrics"
741+
742+ mux := http .NewServeMux ()
743+ pm .RegisterHandler (path , mux )
744+
745+ getMetricsOutput := func () string {
746+ req := httptest .NewRequest ("GET" , path , nil )
747+ w := httptest .NewRecorder ()
748+ mux .ServeHTTP (w , req )
749+
750+ resp := w .Result ()
751+ assert .Equal (t , http .StatusOK , resp .StatusCode )
752+
753+ body , err := io .ReadAll (resp .Body )
754+ assert .NoError (t , err )
755+ return string (body )
756+ }
757+
758+ t .Log ("Phase 1: Initial state - all metrics should be present with 0 values" )
759+ fr := make (filters.Registry )
760+ fr .Register (builtin .NewSetPath ())
761+
762+ opts := & routing.Options {
763+ FilterRegistry : fr ,
764+ Predicates : []routing.PredicateSpec {primitive .NewTrue (), query .New ()},
765+ Metrics : pm ,
766+ Log : & logging.DefaultLog {},
767+ }
768+
769+ t .Log ("Test with all valid routes" )
770+ validRoutes := []* eskip.Route {
771+ {Id : "valid1" , Path : "/foo" , Backend : "https://example.org" },
772+ {Id : "valid2" , Predicates : []* eskip.Predicate {{Name : "Path" , Args : []interface {}{"/bar" }}}, Backend : "https://example.org" },
773+ }
774+
775+ routes , invalidRoutes := routing .ExportProcessRouteDefs (opts , validRoutes )
776+ assert .Len (t , routes , 2 )
777+ assert .Len (t , invalidRoutes , 0 )
778+
779+ output1 := getMetricsOutput ()
780+ assert .Contains (t , output1 , `skipper_route_invalid{reason="unknown_filter"} 0` )
781+ assert .Contains (t , output1 , `skipper_route_invalid{reason="invalid_filter_params"} 0` )
782+ assert .Contains (t , output1 , `skipper_route_invalid{reason="unknown_predicate"} 0` )
783+ assert .Contains (t , output1 , `skipper_route_invalid{reason="invalid_predicate_params"} 0` )
784+ assert .Contains (t , output1 , `skipper_route_invalid{reason="failed_backend_split"} 0` )
785+ assert .Contains (t , output1 , `skipper_route_invalid{reason="invalid_matcher"} 0` )
786+ assert .Contains (t , output1 , `skipper_route_invalid{reason="other"} 0` )
787+
788+ t .Log ("Phase 2: Test with various error types" )
789+ invalidRoutesSet := []* eskip.Route {
790+ {Id : "unknownFilter" , Predicates : []* eskip.Predicate {{Name : "Path" , Args : []interface {}{"/test" }}}, Filters : []* eskip.Filter {{Name : "unknownFilter" }}, Backend : "https://example.org" },
791+ {Id : "invalidFilterParams" , Predicates : []* eskip.Predicate {{Name : "Path" , Args : []interface {}{"/test2" }}}, Filters : []* eskip.Filter {{Name : "setPath" }}, Backend : "https://example.org" },
792+ {Id : "unknownPredicate" , Predicates : []* eskip.Predicate {{Name : "UnknownPredicate" }}, Backend : "https://example.org" },
793+ {Id : "invalidPredicateParams" , Predicates : []* eskip.Predicate {{Name : "QueryParam" }}, Backend : "https://example.org" },
794+ {Id : "failedBackendSplit" , Predicates : []* eskip.Predicate {{Name : "Path" , Args : []interface {}{"/test3" }}}, Backend : "invalid-url" },
795+ {Id : "valid3" , Predicates : []* eskip.Predicate {{Name : "Path" , Args : []interface {}{"/test4" }}}, Backend : "https://example.org" },
796+ }
797+
798+ routes2 , invalidRoutes2 := routing .ExportProcessRouteDefs (opts , invalidRoutesSet )
799+ assert .Len (t , routes2 , 1 )
800+ assert .Len (t , invalidRoutes2 , 5 )
801+
802+ output2 := getMetricsOutput ()
803+ assert .Contains (t , output2 , `skipper_route_invalid{reason="unknown_filter"} 1` )
804+ assert .Contains (t , output2 , `skipper_route_invalid{reason="invalid_filter_params"} 1` )
805+ assert .Contains (t , output2 , `skipper_route_invalid{reason="unknown_predicate"} 1` )
806+ assert .Contains (t , output2 , `skipper_route_invalid{reason="invalid_predicate_params"} 1` )
807+ assert .Contains (t , output2 , `skipper_route_invalid{reason="failed_backend_split"} 1` )
808+ assert .Contains (t , output2 , `skipper_route_invalid{reason="invalid_matcher"} 0` )
809+ assert .Contains (t , output2 , `skipper_route_invalid{reason="other"} 0` )
810+
811+ t .Log ("Phase 3: Test routes are fixed - all metrics should reset to 0" )
812+ allValidRoutes := []* eskip.Route {
813+ {Id : "fixed1" , Predicates : []* eskip.Predicate {{Name : "Path" , Args : []interface {}{"/fixed1" }}}, Backend : "https://example.org" },
814+ {Id : "fixed2" , Predicates : []* eskip.Predicate {{Name : "Path" , Args : []interface {}{"/fixed2" }}}, Backend : "https://example.org" },
815+ }
816+
817+ routes3 , invalidRoutes3 := routing .ExportProcessRouteDefs (opts , allValidRoutes )
818+ assert .Len (t , routes3 , 2 )
819+ assert .Len (t , invalidRoutes3 , 0 )
820+
821+ output3 := getMetricsOutput ()
822+ assert .Contains (t , output3 , `skipper_route_invalid{reason="unknown_filter"} 0` )
823+ assert .Contains (t , output3 , `skipper_route_invalid{reason="invalid_filter_params"} 0` )
824+ assert .Contains (t , output3 , `skipper_route_invalid{reason="unknown_predicate"} 0` )
825+ assert .Contains (t , output3 , `skipper_route_invalid{reason="invalid_predicate_params"} 0` )
826+ assert .Contains (t , output3 , `skipper_route_invalid{reason="failed_backend_split"} 0` )
827+ assert .Contains (t , output3 , `skipper_route_invalid{reason="invalid_matcher"} 0` )
828+ assert .Contains (t , output3 , `skipper_route_invalid{reason="other"} 0` )
829+ }
0 commit comments