diff --git a/CHANGELOG.md b/CHANGELOG.md index 1b0a58c747f..845ba1c31a7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -42,6 +42,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm It is however impossible to emit only the 1.20.0 semantic conventions, as the next release will drop support for that environment variable. (#6899) - Update the Jaeger remote sampler to use "github.com/jaegertracing/jaeger-idl/proto-gen/api_v2" in `go.opentelemetry.io/contrib/samplers/jaegerremote`. (#7061) - Improve performance by reducing allocations in the gRPC stats handler in `go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc`. (#7186) +- Update `http.route` attribute to support `request.Pattern` in `go.opentelemetry.io/contrib/instrumentation/github.com/gorilla/mux/otelmux`. (#7108) ### Fixed diff --git a/instrumentation/github.com/gorilla/mux/otelmux/mux.go b/instrumentation/github.com/gorilla/mux/otelmux/mux.go index 73eec8584f7..95c6514440b 100644 --- a/instrumentation/github.com/gorilla/mux/otelmux/mux.go +++ b/instrumentation/github.com/gorilla/mux/otelmux/mux.go @@ -114,12 +114,15 @@ func (tw traceware) ServeHTTP(w http.ResponseWriter, r *http.Request) { } } - routeStr := "" - route := mux.CurrentRoute(r) - if route != nil { - routeStr, _ = route.GetPathTemplate() - if routeStr == "" { - routeStr, _ = route.GetPathRegexp() + routeStr := r.Pattern + + if routeStr == "" { + route := mux.CurrentRoute(r) + if route != nil { + routeStr, _ = route.GetPathTemplate() + if routeStr == "" { + routeStr, _ = route.GetPathRegexp() + } } } diff --git a/instrumentation/github.com/gorilla/mux/otelmux/test/mux_test.go b/instrumentation/github.com/gorilla/mux/otelmux/test/mux_test.go index cc7531047b0..a837eb45425 100644 --- a/instrumentation/github.com/gorilla/mux/otelmux/test/mux_test.go +++ b/instrumentation/github.com/gorilla/mux/otelmux/test/mux_test.go @@ -94,29 +94,55 @@ func TestSDKIntegration(t *testing.T) { router.HandleFunc("/user/{id:[0-9]+}", ok) router.HandleFunc("/book/{title}", ok) - r0 := httptest.NewRequest("GET", "/user/123", nil) - r1 := httptest.NewRequest("GET", "/book/foo", nil) - w := httptest.NewRecorder() - router.ServeHTTP(w, r0) - router.ServeHTTP(w, r1) + tests := []struct { + name string + path string + reqFunc func(r *http.Request) + expected string + }{ + { + name: "user route", + path: "/user/123", + reqFunc: nil, + expected: "/user/{id:[0-9]+}", + }, + { + name: "book route", + path: "/book/foo", + reqFunc: nil, + expected: "/book/{title}", + }, + { + name: "book route with custom pattern", + path: "/book/bar", + reqFunc: func(r *http.Request) { r.Pattern = "/book/{custom}" }, + expected: "/book/{custom}", + }, + } - require.Len(t, sr.Ended(), 2) - assertSpan(t, sr.Ended()[0], - "/user/{id:[0-9]+}", - trace.SpanKindServer, - attribute.String("server.address", "foobar"), - attribute.Int("http.response.status_code", http.StatusOK), - attribute.String("http.request.method", "GET"), - attribute.String("http.route", "/user/{id:[0-9]+}"), - ) - assertSpan(t, sr.Ended()[1], - "/book/{title}", - trace.SpanKindServer, - attribute.String("server.address", "foobar"), - attribute.Int("http.response.status_code", http.StatusOK), - attribute.String("http.request.method", "GET"), - attribute.String("http.route", "/book/{title}"), - ) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + defer sr.Reset() + + r := httptest.NewRequest("GET", tt.path, nil) + if tt.reqFunc != nil { + tt.reqFunc(r) + } + + w := httptest.NewRecorder() + router.ServeHTTP(w, r) + + require.Len(t, sr.Ended(), 1) + assertSpan(t, sr.Ended()[0], + tt.expected, + trace.SpanKindServer, + attribute.String("server.address", "foobar"), + attribute.Int("http.response.status_code", http.StatusOK), + attribute.String("http.request.method", "GET"), + attribute.String("http.route", tt.expected), + ) + }) + } } func TestNotFoundIsNotError(t *testing.T) {