From 9ae5f8913778f792da14be6739525ecde432c2c1 Mon Sep 17 00:00:00 2001 From: "Gregory Markou (ai)" Date: Mon, 27 Apr 2026 15:52:58 +0300 Subject: [PATCH] feat: surface OpenTelemetry export errors and config Three small additions to the metric provider init in app.Run that turn silent OTLP failures into observable startup signals: 1. Register a global otel.SetErrorHandler that routes SDK errors (export failures, malformed URLs, TLS handshake errors, context deadlines) to zerolog. Without this the SDK swallows export errors and the relayer prints nothing. 2. Log the configured collector URL at INFO before initializing the provider, so container logs show the target the relayer is actually using. 3. Treat an empty OpenTelemetryCollectorURL as "telemetry disabled" and substitute a noop.MeterProvider with a WARN log, instead of the current behavior where url.Parse("") succeeds and the OTLP HTTP exporter silently falls back to localhost:4318. No behavior change when the collector URL is set correctly. Co-Authored-By: Claude --- app/app.go | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/app/app.go b/app/app.go index f6bb9ad9..9f08694b 100644 --- a/app/app.go +++ b/app/app.go @@ -61,6 +61,10 @@ import ( "github.com/sygmaprotocol/sygma-core/relayer/message" "github.com/sygmaprotocol/sygma-core/store" "github.com/sygmaprotocol/sygma-core/store/lvldb" + + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/metric" + "go.opentelemetry.io/otel/metric/noop" ) var Version string @@ -111,13 +115,25 @@ func Run() error { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - mp, err := observability.InitMetricProvider(context.Background(), configuration.RelayerConfig.OpenTelemetryCollectorURL) - panicOnError(err) - defer func() { - if err := mp.Shutdown(context.Background()); err != nil { - log.Error().Msgf("Error shutting down meter provider: %v", err) - } - }() + otel.SetErrorHandler(otel.ErrorHandlerFunc(func(err error) { + log.Error().Err(err).Msg("OpenTelemetry SDK error") + })) + + var mp metric.MeterProvider + if url := configuration.RelayerConfig.OpenTelemetryCollectorURL; url == "" { + log.Warn().Msg("OpenTelemetry disabled: collector URL not configured") + mp = noop.NewMeterProvider() + } else { + log.Info().Str("url", url).Msg("Initializing OpenTelemetry metric provider") + sdkMp, err := observability.InitMetricProvider(context.Background(), url) + panicOnError(err) + defer func() { + if err := sdkMp.Shutdown(context.Background()); err != nil { + log.Error().Msgf("Error shutting down meter provider: %v", err) + } + }() + mp = sdkMp + } sygmaMetrics, err := metrics.NewSprinterMetrics(ctx, mp.Meter("relayer-metric-provider"), configuration.RelayerConfig.Env, configuration.RelayerConfig.Id, Version) panicOnError(err)