Add internal/tracing: env-gated OTel setup, span/log helpers, decorators

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2026-08-24 10:43:55 +02:00
parent b1a16774bf
commit 6b34f68469
12 changed files with 929 additions and 1 deletions

View File

@@ -0,0 +1,73 @@
package tracing
import (
"context"
"io"
"net/http"
"net/http/httptest"
"testing"
sdktrace "go.opentelemetry.io/otel/sdk/trace"
"go.opentelemetry.io/otel/sdk/trace/tracetest"
"go.opentelemetry.io/otel/trace"
)
func TestRestConfigWrapper_parentGated(t *testing.T) {
t.Parallel()
var gotTraceparent string
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
gotTraceparent = r.Header.Get("traceparent")
w.WriteHeader(http.StatusOK)
}))
t.Cleanup(srv.Close)
sr := tracetest.NewSpanRecorder()
tp := sdktrace.NewTracerProvider(sdktrace.WithSpanProcessor(sr))
t.Cleanup(func() { _ = tp.Shutdown(context.Background()) })
rt := RestConfigWrapper(WithTracerProvider(tp))(http.DefaultTransport)
do := func(ctx context.Context) {
t.Helper()
req, err := http.NewRequestWithContext(ctx, http.MethodGet, srv.URL, nil)
if err != nil {
t.Fatal(err)
}
resp, err := rt.RoundTrip(req)
if err != nil {
t.Fatal(err)
}
_, _ = io.Copy(io.Discard, resp.Body)
_ = resp.Body.Close()
}
// No parent span: informer watches, leader election. Must not trace.
do(context.Background())
if len(sr.Ended()) != 0 {
t.Fatalf("request without parent span produced %d spans, want 0", len(sr.Ended()))
}
if gotTraceparent != "" {
t.Fatalf("request without parent span injected traceparent %q", gotTraceparent)
}
// Under a parent span: one client child span, traceparent injected.
ctx, parent := tp.Tracer("test").Start(context.Background(), "reconcile")
do(ctx)
parent.End()
var client sdktrace.ReadOnlySpan
for _, s := range sr.Ended() {
if s.SpanKind() == trace.SpanKindClient {
client = s
}
}
if client == nil {
t.Fatalf("no client span recorded, got %d spans", len(sr.Ended()))
}
if got := client.Parent().SpanID(); got != parent.SpanContext().SpanID() {
t.Errorf("client span parent = %s, want %s", got, parent.SpanContext().SpanID())
}
if gotTraceparent == "" {
t.Error("traceparent header not injected under a parent span")
}
}