package telemetry import ( "context" "errors" "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc" "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc" "go.opentelemetry.io/otel/propagation" sdkmetric "go.opentelemetry.io/otel/sdk/metric" "go.opentelemetry.io/otel/sdk/resource" sdktrace "go.opentelemetry.io/otel/sdk/trace" semconv "go.opentelemetry.io/otel/semconv/v1.24.0" ) type Config struct { ServiceName string ServiceVersion string Endpoint string Environment string } func Init(ctx context.Context, cfg Config) (func(context.Context) error, error) { res, err := resource.New(ctx, resource.WithAttributes( semconv.ServiceName(cfg.ServiceName), semconv.ServiceVersion(cfg.ServiceVersion), ), ) if err != nil { return nil, err } otel.SetTextMapPropagator( propagation.NewCompositeTextMapPropagator( propagation.TraceContext{}, propagation.Baggage{}, ), ) traceExporter, err := otlptracegrpc.New(ctx, otlptracegrpc.WithInsecure(), // TODO: for local development otlptracegrpc.WithEndpoint(cfg.Endpoint), ) if err != nil { return nil, err } tracerProvider := sdktrace.NewTracerProvider( sdktrace.WithBatcher(traceExporter), sdktrace.WithResource(res), ) metricExporter, err := otlpmetricgrpc.New(ctx, otlpmetricgrpc.WithInsecure(), // TODO: for local development otlpmetricgrpc.WithEndpoint(cfg.Endpoint), ) if err != nil { return nil, err } meterProvider := sdkmetric.NewMeterProvider( sdkmetric.WithReader(sdkmetric.NewPeriodicReader(metricExporter)), sdkmetric.WithResource(res), ) otel.SetTracerProvider(tracerProvider) otel.SetMeterProvider(meterProvider) shutdown := func(ctx context.Context) error { return errors.Join( traceExporter.Shutdown(ctx), meterProvider.Shutdown(ctx), ) } return shutdown, nil }