package main import ( "context" "strings" "github.com/labstack/echo/v4" "go.opentelemetry.io/contrib/instrumentation/github.com/labstack/echo/otelecho" "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc" "go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp" "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc" "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp" "go.opentelemetry.io/otel/exporters/otlp/otlptrace" "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc" "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp" "go.opentelemetry.io/otel/log/global" "go.opentelemetry.io/otel/sdk/log" "go.opentelemetry.io/otel/sdk/metric" "go.opentelemetry.io/otel/sdk/resource" "go.opentelemetry.io/otel/sdk/trace" semconv "go.opentelemetry.io/otel/semconv/v1.26.0" ) func setupOtel(e *echo.Echo) (func(), error) { ctx := context.Background() proto := GetenvOr("OTEL_EXPORTER_OTLP_PROTOCOL", "http/protobuf") res, err := resource.New( ctx, resource.WithAttributes(semconv.ServiceNameKey.String("kyoo.auth")), resource.WithFromEnv(), resource.WithTelemetrySDK(), resource.WithProcess(), resource.WithOS(), resource.WithContainer(), resource.WithHost(), ) if err != nil { return nil, err } var le log.Exporter if proto == "http/protobuf" { le, err = otlploghttp.New(ctx) } else { le, err = otlploggrpc.New(ctx) } if err != nil { return nil, err } lp := log.NewLoggerProvider( log.WithProcessor(log.NewBatchProcessor(le)), log.WithResource(res), ) global.SetLoggerProvider(lp) var me metric.Exporter if proto == "http/protobuf" { me, err = otlpmetrichttp.New(ctx) } else { me, err = otlpmetricgrpc.New(ctx) } if err != nil { return func() {}, err } mp := metric.NewMeterProvider( metric.WithReader( metric.NewPeriodicReader(me), ), metric.WithResource(res), ) otel.SetMeterProvider(mp) var te *otlptrace.Exporter if proto == "http/protobuf" { te, err = otlptracehttp.New(ctx) } else { te, err = otlptracegrpc.New(ctx) } if err != nil { return func() {}, err } tp := trace.NewTracerProvider( trace.WithBatcher(te), trace.WithResource(res), ) otel.SetTracerProvider(tp) e.Use(otelecho.Middleware("kyoo.auth", otelecho.WithSkipper(func(c echo.Context) bool { return c.Path() == "/auth/health" || c.Path() == "/auth/ready" }))) return func() { lp.Shutdown(ctx) mp.Shutdown(ctx) tp.Shutdown(ctx) }, nil } // stolen from https://github.com/exaring/otelpgx/issues/47 func dbGetSpanName(sql string) string { if len(sql) >= 10 && sql[0:9] == "-- name: " { // -- name: {name} :{type} if index := strings.Index(sql[9:], ":"); index != -1 { // remove leading space before : // optimised assuming this comment has been generated by SQLC return sql[9 : 9+(index-1)] } // -- name: {name} if index := strings.Index(sql[9:], "\n"); index != -1 { if sql[len(sql[9:9+index])-1] != ' ' { return sql[9 : 9+index] } return strings.TrimSpace(sql[9 : 9+index]) } } if len(sql) >= 9 && sql[0:8] == "-- name:" { // -- name:{name} if index := strings.Index(sql[8:], "\n"); index != -1 { if sql[len(sql[8:8+index])-1] != ' ' { return sql[8 : 8+index] } return strings.TrimSpace(sql[8 : 8+index]) } } if len(sql) >= 8 && sql[0:7] == "--name:" { // -- name:{name} if index := strings.Index(sql[7:], "\n"); index != -1 { if sql[len(sql[7:7+index])-1] != ' ' { return sql[7 : 7+index] } return strings.TrimSpace(sql[7 : 7+index]) } } return sql }