diff --git a/backend/internal/otelsetup/otelsetup.go b/backend/internal/otelsetup/otelsetup.go index f457501..09d58cb 100644 --- a/backend/internal/otelsetup/otelsetup.go +++ b/backend/internal/otelsetup/otelsetup.go @@ -2,7 +2,10 @@ // // It reads two environment variables: // -// OTEL_EXPORTER_OTLP_ENDPOINT — OTLP/HTTP endpoint, e.g. http://otel-collector:4318 +// OTEL_EXPORTER_OTLP_ENDPOINT — OTLP/HTTP endpoint; accepts either a full +// URL ("https://otel.example.com") or a bare +// host[:port] ("otel-collector:4318"). +// TLS is used when the value starts with "https://". // OTEL_SERVICE_NAME — service name reported in traces (default: "backend") // // When OTEL_EXPORTER_OTLP_ENDPOINT is empty the function is a no-op: it @@ -21,6 +24,7 @@ import ( "fmt" "log/slog" "os" + "strings" "time" "go.opentelemetry.io/contrib/bridges/otelslog" @@ -41,11 +45,17 @@ import ( // - logger: an slog.Logger bridged to OTel logs (falls back to default when disabled). // - err: non-nil only on SDK initialisation failure. func Init(ctx context.Context, version string) (shutdown func(), logger *slog.Logger, err error) { - endpoint := os.Getenv("OTEL_EXPORTER_OTLP_ENDPOINT") - if endpoint == "" { + rawEndpoint := os.Getenv("OTEL_EXPORTER_OTLP_ENDPOINT") + if rawEndpoint == "" { return nil, slog.Default(), nil // OTel disabled — not an error } + // WithEndpoint expects a host[:port] value — no scheme. + // Support both "https://otel.example.com" and "otel-collector:4318". + useTLS := strings.HasPrefix(rawEndpoint, "https://") + endpoint := strings.TrimPrefix(rawEndpoint, "https://") + endpoint = strings.TrimPrefix(endpoint, "http://") + serviceName := os.Getenv("OTEL_SERVICE_NAME") if serviceName == "" { serviceName = "backend" @@ -63,10 +73,11 @@ func Init(ctx context.Context, version string) (shutdown func(), logger *slog.Lo } // ── Trace provider ──────────────────────────────────────────────────────── - traceExp, err := otlptracehttp.New(ctx, - otlptracehttp.WithEndpoint(endpoint), - otlptracehttp.WithInsecure(), // collector is on the internal Docker network - ) + traceOpts := []otlptracehttp.Option{otlptracehttp.WithEndpoint(endpoint)} + if !useTLS { + traceOpts = append(traceOpts, otlptracehttp.WithInsecure()) + } + traceExp, err := otlptracehttp.New(ctx, traceOpts...) if err != nil { return nil, slog.Default(), fmt.Errorf("otelsetup: create OTLP trace exporter: %w", err) } @@ -79,10 +90,11 @@ func Init(ctx context.Context, version string) (shutdown func(), logger *slog.Lo otel.SetTracerProvider(tp) // ── Log provider ────────────────────────────────────────────────────────── - logExp, err := otlploghttp.New(ctx, - otlploghttp.WithEndpoint(endpoint), - otlploghttp.WithInsecure(), - ) + logOpts := []otlploghttp.Option{otlploghttp.WithEndpoint(endpoint)} + if !useTLS { + logOpts = append(logOpts, otlploghttp.WithInsecure()) + } + logExp, err := otlploghttp.New(ctx, logOpts...) if err != nil { return nil, slog.Default(), fmt.Errorf("otelsetup: create OTLP log exporter: %w", err) }