tracinghandler.go 1.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
  1. package handler
  2. import (
  3. "net/http"
  4. "sync"
  5. "github.com/zeromicro/go-zero/core/lang"
  6. "github.com/zeromicro/go-zero/core/trace"
  7. "go.opentelemetry.io/otel"
  8. "go.opentelemetry.io/otel/propagation"
  9. semconv "go.opentelemetry.io/otel/semconv/v1.4.0"
  10. oteltrace "go.opentelemetry.io/otel/trace"
  11. )
  12. var dontTracingSpanNames sync.Map
  13. // DontTracingSpanName disable tracing for the specified spanName.
  14. func DontTracingSpanName(spanName string) {
  15. dontTracingSpanNames.Store(spanName, lang.Placeholder)
  16. }
  17. // TracingHandler return a middleware that process the opentelemetry.
  18. func TracingHandler(serviceName, path string) func(http.Handler) http.Handler {
  19. return func(next http.Handler) http.Handler {
  20. propagator := otel.GetTextMapPropagator()
  21. tracer := otel.GetTracerProvider().Tracer(trace.TraceName)
  22. return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  23. defer func() {
  24. next.ServeHTTP(w, r)
  25. }()
  26. ctx := propagator.Extract(r.Context(), propagation.HeaderCarrier(r.Header))
  27. spanName := path
  28. if len(spanName) == 0 {
  29. spanName = r.URL.Path
  30. }
  31. _, ok := dontTracingSpanNames.Load(spanName)
  32. if ok {
  33. return
  34. }
  35. spanCtx, span := tracer.Start(
  36. ctx,
  37. spanName,
  38. oteltrace.WithSpanKind(oteltrace.SpanKindServer),
  39. oteltrace.WithAttributes(semconv.HTTPServerAttributesFromHTTPRequest(
  40. serviceName, spanName, r)...),
  41. )
  42. defer span.End()
  43. // convenient for tracking error messages
  44. propagator.Inject(spanCtx, propagation.HeaderCarrier(w.Header()))
  45. r = r.WithContext(spanCtx)
  46. })
  47. }
  48. }