package middleware import ( "fmt" "net/http" "github.com/gin-gonic/gin" "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/codes" "go.opentelemetry.io/otel/propagation" "go.opentelemetry.io/otel/trace" ) func Tracing(tracer trace.Tracer) gin.HandlerFunc { return func(c *gin.Context) { ctx := otel.GetTextMapPropagator().Extract(c.Request.Context(), propagation.HeaderCarrier(c.Request.Header)) spanName := fmt.Sprintf("%s %s", c.Request.Method, c.Request.URL.Path) ctx, span := tracer.Start( ctx, spanName, trace.WithSpanKind(trace.SpanKindServer), trace.WithAttributes( attribute.String("http.request.method", c.Request.Method), ), ) defer span.End() c.Request = c.Request.WithContext(ctx) c.Next() route := c.FullPath() if route == "" { route = "/unknown" } status := c.Writer.Status() span.SetName(fmt.Sprintf("%s %s", c.Request.Method, route)) span.SetAttributes( attribute.String("http.route", route), attribute.Int("http.response.status_code", status), ) if status >= http.StatusInternalServerError { span.SetStatus(codes.Error, http.StatusText(status)) } if len(c.Errors) > 0 { for _, err := range c.Errors { span.RecordError(err) } span.SetStatus(codes.Error, c.Errors.String()) } } }