package fiber_tracing import ( "context" "log" "git.ma-al.com/maal-libraries/observer/pkg/exporters" "github.com/gofiber/fiber/v2" fiberOpentelemetry "github.com/psmarcin/fiber-opentelemetry/pkg/fiber-otel" "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 } func newResource(config Config) *resource.Resource { r := resource.NewWithAttributes( semconv.SchemaURL, semconv.ServiceNameKey.String(config.AppName), semconv.ServiceVersionKey.String(config.Version), attribute.String("service.provider", config.ServiceProvider), ) 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 fiberOpentelemetry.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) { span := trace.SpanFromContext(fiberOpentelemetry.FromCtx(c)) c.SetUserContext(trace.ContextWithSpan(c.UserContext(), span)) return fiberOpentelemetry.Tracer.Start(c.UserContext(), c.Method()+" "+c.Route().Path, opts...) } // Retrieve span using [fiber.Ctx] func SpanFromContext(c *fiber.Ctx) trace.Span { ctx := fiberOpentelemetry.FromCtx(c) c.SetUserContext(trace.ContextWithSpan(c.UserContext(), trace.SpanFromContext(ctx))) return trace.SpanFromContext(ctx) } 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 fiberOpentelemetry.New( fiberOpentelemetry.Config{ Tracer: tracer, SpanName: "{{ .Method }} {{ .Route.Path }}", TracerStartAttributes: []trace.SpanStartOption{ trace.WithSpanKind(trace.SpanKindServer), trace.WithNewRoot(), }, }, ) } func ShutdownTracer() { if err := TP.Shutdown(context.Background()); err != nil { log.Fatal(err) } }