package trace import ( "net/http" "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/propagation" "go.opentelemetry.io/otel/trace" ) type recorder struct { http.ResponseWriter status int } func (r *recorder) WriteHeader(code int) { r.status = code r.ResponseWriter.WriteHeader(code) } func Middleware(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { ctx := otel.GetTextMapPropagator().Extract(r.Context(), propagation.HeaderCarrier(r.Header)) tracer := otel.Tracer("") spanName := r.Method + " " + r.URL.Path ctx, span := tracer.Start(ctx, spanName, trace.WithAttributes( attribute.String("http.method", r.Method), attribute.String("http.target", r.URL.String()), attribute.String("http.host", r.Host), attribute.String("http.scheme", scheme(r)), ), ) defer span.End() rec := &recorder{ResponseWriter: w, status: http.StatusOK} next.ServeHTTP(rec, r.WithContext(ctx)) span.SetAttributes( attribute.Int("http.status_code", rec.status), attribute.String("http.status_text", http.StatusText(rec.status)), ) }) } func scheme(r *http.Request) string { if r.TLS != nil { return "https" } return "http" }