package fiber_tracing import ( "context" "log" "git.ma-al.com/maal-libraries/observer/pkg/exporters" "github.com/gofiber/fiber/v2" "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/sdk/resource" trc "go.opentelemetry.io/otel/sdk/trace" semconv "go.opentelemetry.io/otel/semconv/v1.25.0" trace "go.opentelemetry.io/otel/trace" ) var ( TracingError error = nil TP trc.TracerProvider ) type Config struct { AppName string Version string // Name of an organization providing the service ServiceProvider string Exporters []exporters.TraceExporter ResourceAttributes []attribute.KeyValue } func newResource(config Config) *resource.Resource { allAttributes := make([]attribute.KeyValue, 0, 3) allAttributes = append( allAttributes, semconv.ServiceName(config.AppName), semconv.ServiceVersion(config.Version), attribute.String("service.provider", config.ServiceProvider), ) allAttributes = append(allAttributes, config.ResourceAttributes...) r := resource.NewWithAttributes(semconv.SchemaURL, allAttributes...) return r } // NOTE: You can use [trace.WithAttributes] as a parameter to opts argument func Start(ctx context.Context, spanName string, opts ...trace.SpanStartOption) (context.Context, trace.Span) { return Tracer.Start(ctx, spanName, opts...) } // NOTE: You can use [trace.WithAttributes] as a parameter to opts argument // Returns [c.UserContext] as [context.Context] func FStart(c *fiber.Ctx, opts ...trace.SpanStartOption) (context.Context, trace.Span) { return Tracer.Start(c.UserContext(), c.Method()+" "+c.Route().Path, opts...) } // Just like [FStart] but makes it possible to assign custom span name. func FStartRenamed(c *fiber.Ctx, spanName string, opts ...trace.SpanStartOption) (context.Context, trace.Span) { return Tracer.Start(c.UserContext(), spanName, opts...) } // Retrieve span using [fiber.Ctx] func SpanFromContext(c *fiber.Ctx) trace.Span { return trace.SpanFromContext(c.UserContext()) } func NewMiddleware(config Config) func(*fiber.Ctx) error { var tracerProviders []trc.TracerProviderOption for _, exp := range config.Exporters { tracerProviders = append(tracerProviders, exp.IntoTraceProviderOption()) } tracerProviders = append(tracerProviders, trc.WithResource(newResource(config))) TP = *trc.NewTracerProvider(tracerProviders...) otel.SetTracerProvider(&TP) otel.SetErrorHandler(otel.ErrorHandlerFunc(func(err error) { if err != TracingError { TracingError = err log.Println(err) } })) tracer := TP.Tracer("_maal-fiber-otel_") return new( middlewareConfig{ Tracer: tracer, TracerStartAttributes: []trace.SpanStartOption{ trace.WithSpanKind(trace.SpanKindServer), trace.WithNewRoot(), }, }, ) } func ShutdownTracer() { if err := TP.Shutdown(context.Background()); err != nil { log.Fatal(err) } }