Add OpenTelemetry instrumentation with middleware-only approach
This commit is contained in:
100
pkg/telemetry/telemetry.go
Normal file
100
pkg/telemetry/telemetry.go
Normal file
@@ -0,0 +1,100 @@
|
||||
// Package telemetry provides OpenTelemetry instrumentation for the DanceLessonsCoach application
|
||||
package telemetry
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
|
||||
"go.opentelemetry.io/otel"
|
||||
"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc"
|
||||
"go.opentelemetry.io/otel/propagation"
|
||||
"go.opentelemetry.io/otel/sdk/resource"
|
||||
sdktrace "go.opentelemetry.io/otel/sdk/trace"
|
||||
semconv "go.opentelemetry.io/otel/semconv/v1.21.0"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
)
|
||||
|
||||
// Setup initializes OpenTelemetry tracing with the given configuration
|
||||
type Setup struct {
|
||||
ServiceName string
|
||||
OTLPEndpoint string
|
||||
Insecure bool
|
||||
SamplerType string
|
||||
SamplerRatio float64
|
||||
}
|
||||
|
||||
// InitializeTracing sets up OpenTelemetry tracing provider
|
||||
func (s *Setup) InitializeTracing(ctx context.Context) (*sdktrace.TracerProvider, error) {
|
||||
// Create OTLP gRPC exporter
|
||||
exporter, err := otlptracegrpc.New(ctx,
|
||||
otlptracegrpc.WithEndpoint(s.OTLPEndpoint),
|
||||
otlptracegrpc.WithInsecure(),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Create resource with service name
|
||||
res, err := resource.New(ctx,
|
||||
resource.WithAttributes(
|
||||
semconv.ServiceName(s.ServiceName),
|
||||
),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Create sampler based on configuration
|
||||
sampler := s.getSampler()
|
||||
|
||||
// Create trace provider
|
||||
tp := sdktrace.NewTracerProvider(
|
||||
sdktrace.WithBatcher(exporter),
|
||||
sdktrace.WithResource(res),
|
||||
sdktrace.WithSampler(sampler),
|
||||
)
|
||||
|
||||
// Set global tracer provider and propagator
|
||||
otel.SetTracerProvider(tp)
|
||||
otel.SetTextMapPropagator(propagation.NewCompositeTextMapPropagator(
|
||||
propagation.TraceContext{},
|
||||
propagation.Baggage{},
|
||||
))
|
||||
|
||||
return tp, nil
|
||||
}
|
||||
|
||||
// Shutdown performs cleanup of the tracer provider
|
||||
func Shutdown(ctx context.Context, tp *sdktrace.TracerProvider) error {
|
||||
if tp == nil {
|
||||
return nil
|
||||
}
|
||||
return tp.Shutdown(ctx)
|
||||
}
|
||||
|
||||
// getSampler returns the appropriate sampler based on configuration
|
||||
func (s *Setup) getSampler() sdktrace.Sampler {
|
||||
switch s.SamplerType {
|
||||
case "always_on":
|
||||
return sdktrace.AlwaysSample()
|
||||
case "always_off":
|
||||
return sdktrace.NeverSample()
|
||||
case "traceidratio":
|
||||
return sdktrace.TraceIDRatioBased(s.SamplerRatio)
|
||||
case "parentbased_always_on":
|
||||
return sdktrace.ParentBased(sdktrace.AlwaysSample())
|
||||
case "parentbased_always_off":
|
||||
return sdktrace.ParentBased(sdktrace.NeverSample())
|
||||
case "parentbased_traceidratio":
|
||||
return sdktrace.ParentBased(sdktrace.TraceIDRatioBased(s.SamplerRatio))
|
||||
default:
|
||||
log.Printf("Unknown sampler type: %s, defaulting to always_on", s.SamplerType)
|
||||
return sdktrace.AlwaysSample()
|
||||
}
|
||||
}
|
||||
|
||||
// GetTracer returns a named tracer from the global provider
|
||||
// Returns a no-op tracer if OpenTelemetry is not initialized
|
||||
func GetTracer(name string) trace.Tracer {
|
||||
return otel.Tracer(name)
|
||||
}
|
||||
Reference in New Issue
Block a user