package mid import ( "context" "fmt" "geeks-accelerator/oss/saas-starter-kit/example-project/internal/platform/web" "gopkg.in/DataDog/dd-trace-go.v1/ddtrace" "gopkg.in/DataDog/dd-trace-go.v1/ddtrace/ext" "gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer" "net/http" ) // Trace adds the base tracing info for requests func Trace() web.Middleware { // This is the actual middleware function to be executed. f := func(before web.Handler) web.Handler { // Wrap this handler around the next one provided. h := func(ctx context.Context, w http.ResponseWriter, r *http.Request, params map[string]string) error { // Span options with request info opts := []ddtrace.StartSpanOption{ tracer.SpanType(ext.SpanTypeWeb), tracer.ResourceName(r.URL.Path), tracer.Tag(ext.HTTPMethod, r.Method), tracer.Tag(ext.HTTPURL, r.RequestURI), } // Continue server side request tracing from previous request. if spanctx, err := tracer.Extract(tracer.HTTPHeadersCarrier(r.Header)); err == nil { opts = append(opts, tracer.ChildOf(spanctx)) } // Start the span for tracking span, ctx := tracer.StartSpanFromContext(ctx, "http.request", opts...) defer span.Finish() // If the context is missing this value, request the service // to be shutdown gracefully. v, ok := ctx.Value(web.KeyValues).(*web.Values) if !ok { return web.NewShutdownError("web value missing from context") } v.TraceID = span.Context().TraceID() v.SpanID = span.Context().SpanID() // Execute the request handler err := before(ctx, w, r, params) // Set the span status code for the trace span.SetTag(ext.HTTPCode, v.StatusCode) // If there was an error, append it to the span if err != nil { span.SetTag(ext.Error, fmt.Sprintf("%+v", err)) } // Return the error so it can be handled further up the chain. return err } return h } return f }