package main import ( "context" "fmt" "log" "net/http" "time" "github.com/go-chi/chi/v5" "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/exporters/stdout/stdoutmetric" "go.opentelemetry.io/otel/exporters/stdout/stdouttrace" "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.20.0" oteltrace "go.opentelemetry.io/otel/trace" "toastielab.dev/toastie-stuff/otelchi" ) var tracer oteltrace.Tracer func main() { // initialize trace provider tp, mp := initOtelProviders() defer func() { if err := tp.Shutdown(context.Background()); err != nil { log.Printf("Error shutting down tracer provider: %v", err) } if err := mp.Shutdown(context.Background()); err != nil { log.Printf("Error shutting down meter provider: %v", err) } }() // set global tracer provider & text propagators otel.SetTracerProvider(tp) otel.SetMeterProvider(mp) otel.SetTextMapPropagator(propagation.NewCompositeTextMapPropagator(propagation.TraceContext{}, propagation.Baggage{})) // initialize tracer tracer = otel.Tracer("mux-server") // define router r := chi.NewRouter() r.Use(otelchi.Middleware("my-server", otelchi.WithChiRoutes(r))) r.HandleFunc("/users/{id:[0-9]+}", func(w http.ResponseWriter, r *http.Request) { id := chi.URLParam(r, "id") name := getUser(r.Context(), id) reply := fmt.Sprintf("user %s (id %s)\n", name, id) w.Write(([]byte)(reply)) }) // serve router _ = http.ListenAndServe(":8080", r) } func initOtelProviders() (*sdktrace.TracerProvider, *sdkmetric.MeterProvider) { traceExporter, err := stdouttrace.New(stdouttrace.WithPrettyPrint()) if err != nil { log.Fatal(err) } metricExporter, err := stdoutmetric.New(stdoutmetric.WithPrettyPrint()) if err != nil { log.Fatal(err) } res, err := resource.New( context.Background(), resource.WithAttributes( // the service name used to display traces in backends semconv.ServiceNameKey.String("mux-server"), ), ) if err != nil { log.Fatalf("unable to initialize resource due: %v", err) } return sdktrace.NewTracerProvider( sdktrace.WithSampler(sdktrace.AlwaysSample()), sdktrace.WithBatcher(traceExporter), sdktrace.WithResource(res), ), sdkmetric.NewMeterProvider( sdkmetric.WithReader(sdkmetric.NewPeriodicReader(metricExporter, sdkmetric.WithInterval(time.Second*30), )), sdkmetric.WithResource(res), ) } func getUser(ctx context.Context, id string) string { _, span := tracer.Start(ctx, "getUser", oteltrace.WithAttributes(attribute.String("id", id))) defer span.End() if id == "123" { return "otelchi tester" } return "unknown" }