1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980 |
- package handler
- import (
- "net/http"
- "github.com/zeromicro/go-zero/core/collection"
- "github.com/zeromicro/go-zero/core/trace"
- "github.com/zeromicro/go-zero/rest/internal/response"
- "go.opentelemetry.io/otel"
- "go.opentelemetry.io/otel/propagation"
- semconv "go.opentelemetry.io/otel/semconv/v1.4.0"
- oteltrace "go.opentelemetry.io/otel/trace"
- )
- type (
- // TracingOption defines the method to customize an tracingOptions.
- TracingOption func(options *tracingOptions)
- // tracingOptions is TracingHandler options.
- tracingOptions struct {
- traceIgnorePaths []string
- }
- )
- // TracingHandler return a middleware that process the opentelemetry.
- func TracingHandler(serviceName, path string, opts ...TracingOption) func(http.Handler) http.Handler {
- var tracingOpts tracingOptions
- for _, opt := range opts {
- opt(&tracingOpts)
- }
- ignorePaths := collection.NewSet()
- ignorePaths.AddStr(tracingOpts.traceIgnorePaths...)
- traceHandler := func(checkIgnore bool) func(http.Handler) http.Handler {
- return func(next http.Handler) http.Handler {
- propagator := otel.GetTextMapPropagator()
- tracer := otel.GetTracerProvider().Tracer(trace.TraceName)
- return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- spanName := path
- if len(spanName) == 0 {
- spanName = r.URL.Path
- }
- if checkIgnore && ignorePaths.Contains(spanName) {
- next.ServeHTTP(w, r)
- return
- }
- ctx := propagator.Extract(r.Context(), propagation.HeaderCarrier(r.Header))
- spanCtx, span := tracer.Start(
- ctx,
- spanName,
- oteltrace.WithSpanKind(oteltrace.SpanKindServer),
- oteltrace.WithAttributes(semconv.HTTPServerAttributesFromHTTPRequest(
- serviceName, spanName, r)...),
- )
- defer span.End()
- // convenient for tracking error messages
- propagator.Inject(spanCtx, propagation.HeaderCarrier(w.Header()))
- trw := &response.WithCodeResponseWriter{Writer: w, Code: http.StatusOK}
- next.ServeHTTP(trw, r.WithContext(spanCtx))
- span.SetAttributes(semconv.HTTPAttributesFromHTTPStatusCode(trw.Code)...)
- span.SetStatus(semconv.SpanStatusFromHTTPStatusCodeAndSpanKind(trw.Code, oteltrace.SpanKindServer))
- })
- }
- }
- checkIgnore := ignorePaths.Count() > 0
- return traceHandler(checkIgnore)
- }
- // WithTraceIgnorePaths specifies the traceIgnorePaths option for TracingHandler.
- func WithTraceIgnorePaths(traceIgnorePaths []string) TracingOption {
- return func(options *tracingOptions) {
- options.traceIgnorePaths = append(options.traceIgnorePaths, traceIgnorePaths...)
- }
- }
|