diff --git a/staging/src/k8s.io/apiserver/pkg/endpoints/filters/traces.go b/staging/src/k8s.io/apiserver/pkg/endpoints/filters/traces.go index 1ecf59d4543..6e36ffec862 100644 --- a/staging/src/k8s.io/apiserver/pkg/endpoints/filters/traces.go +++ b/staging/src/k8s.io/apiserver/pkg/endpoints/filters/traces.go @@ -22,6 +22,7 @@ import ( "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp" semconv "go.opentelemetry.io/otel/semconv/v1.17.0" "go.opentelemetry.io/otel/trace" + "k8s.io/apiserver/pkg/endpoints/request" tracing "k8s.io/component-base/tracing" ) @@ -32,6 +33,14 @@ func WithTracing(handler http.Handler, tp trace.TracerProvider) http.Handler { otelhttp.WithPropagators(tracing.Propagators()), otelhttp.WithPublicEndpoint(), otelhttp.WithTracerProvider(tp), + otelhttp.WithSpanNameFormatter(func(operation string, r *http.Request) string { + ctx := r.Context() + info, exist := request.RequestInfoFrom(ctx) + if !exist || !info.IsResourceRequest { + return r.Method + } + return getSpanNameFromRequestInfo(info, r) + }), } wrappedHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { // Add the http.target attribute to the otelhttp span @@ -45,3 +54,22 @@ func WithTracing(handler http.Handler, tp trace.TracerProvider) http.Handler { // See https://github.com/open-telemetry/opentelemetry-go/tree/main/example/passthrough return otelhttp.NewHandler(wrappedHandler, "KubernetesAPI", opts...) } + +func getSpanNameFromRequestInfo(info *request.RequestInfo, r *http.Request) string { + spanName := "/" + info.APIPrefix + if info.APIGroup != "" { + spanName += "/" + info.APIGroup + } + spanName += "/" + info.APIVersion + if info.Namespace != "" { + spanName += "/namespaces/{:namespace}" + } + spanName += "/" + info.Resource + if info.Name != "" { + spanName += "/" + "{:name}" + } + if info.Subresource != "" { + spanName += "/" + info.Subresource + } + return r.Method + " " + spanName +} diff --git a/test/integration/apiserver/tracing/tracing_test.go b/test/integration/apiserver/tracing/tracing_test.go index c3cdc15bb5e..60b49c7ed15 100644 --- a/test/integration/apiserver/tracing/tracing_test.go +++ b/test/integration/apiserver/tracing/tracing_test.go @@ -309,7 +309,7 @@ endpoint: %s`, listener.Addr().String())), os.FileMode(0755)); err != nil { }, expectedTrace: []*spanExpectation{ { - name: "KubernetesAPI", + name: "POST /api/v1/nodes", attributes: map[string]func(*commonv1.AnyValue) bool{ "http.user_agent": func(v *commonv1.AnyValue) bool { return strings.HasPrefix(v.GetStringValue(), "tracing.test") @@ -428,7 +428,7 @@ endpoint: %s`, listener.Addr().String())), os.FileMode(0755)); err != nil { }, expectedTrace: []*spanExpectation{ { - name: "KubernetesAPI", + name: "GET /api/v1/nodes/{:name}", attributes: map[string]func(*commonv1.AnyValue) bool{ "http.user_agent": func(v *commonv1.AnyValue) bool { return strings.HasPrefix(v.GetStringValue(), "tracing.test") @@ -518,7 +518,7 @@ endpoint: %s`, listener.Addr().String())), os.FileMode(0755)); err != nil { }, expectedTrace: []*spanExpectation{ { - name: "KubernetesAPI", + name: "GET /api/v1/nodes", attributes: map[string]func(*commonv1.AnyValue) bool{ "http.user_agent": func(v *commonv1.AnyValue) bool { return strings.HasPrefix(v.GetStringValue(), "tracing.test") @@ -636,7 +636,7 @@ endpoint: %s`, listener.Addr().String())), os.FileMode(0755)); err != nil { }, expectedTrace: []*spanExpectation{ { - name: "KubernetesAPI", + name: "PUT /api/v1/nodes/{:name}", attributes: map[string]func(*commonv1.AnyValue) bool{ "http.user_agent": func(v *commonv1.AnyValue) bool { return strings.HasPrefix(v.GetStringValue(), "tracing.test") @@ -780,7 +780,7 @@ endpoint: %s`, listener.Addr().String())), os.FileMode(0755)); err != nil { }, expectedTrace: []*spanExpectation{ { - name: "KubernetesAPI", + name: "PATCH /api/v1/nodes/{:name}", attributes: map[string]func(*commonv1.AnyValue) bool{ "http.user_agent": func(v *commonv1.AnyValue) bool { return strings.HasPrefix(v.GetStringValue(), "tracing.test") @@ -901,7 +901,7 @@ endpoint: %s`, listener.Addr().String())), os.FileMode(0755)); err != nil { }, expectedTrace: []*spanExpectation{ { - name: "KubernetesAPI", + name: "DELETE /api/v1/nodes/{:name}", attributes: map[string]func(*commonv1.AnyValue) bool{ "http.user_agent": func(v *commonv1.AnyValue) bool { return strings.HasPrefix(v.GetStringValue(), "tracing.test")