tracing: a failed or unsupported TRACE_EXPORTER installs a BatchSpanProcessor over a nil exporter and silently drops every span
Summary
App.initTracer registers a BatchSpanProcessor over the exporter returned by getExporter without checking whether one was actually produced. When it was not, the TracerProvider is installed with a batch processor that silently discards every span, and the application looks correctly configured for tracing.
pkg/gofr/otel.go on development (9bbdbbe2):
exporter, err := a.getExporter(traceExporter, tracerHost, tracerPort, tracerURL)
if err != nil {
a.container.Error(err)
}
batcher := sdktrace.NewBatchSpanProcessor(exporter) // exporter may be nil
tp.RegisterSpanProcessor(batcher)Two ways to reach it
- A builder returns an error. The error is logged, then the nil exporter is used anyway.
- An unsupported
TRACE_EXPORTER. Thedefault:branch ofgetExportercallsa.container.Errorf("unsupported TRACE_EXPORTER: %s", name)and falls through, returning a nil exporter with a nil error — so even theif err != nilabove does not fire.
It does not panic — that is what makes it hard to notice
NewBatchSpanProcessor(nil) is safe: the SDK guards the nil exporter at sdk/trace/batch_span_processor.go:153 (if bsp.e == nil). Confirmed against the pinned go.opentelemetry.io/otel/sdk v1.44.0 — spans are started, ended, and dropped; ForceFlush returns nil.
So there is no crash and no repeated error. There is one error line at startup, after which the service runs with a sampling TracerProvider whose spans go nowhere. TRACE_EXPORTER=otlpp (typo) produces exactly this.
Expected
A failure to build an exporter should degrade to the same place as "tracing not configured": a NeverSample provider, so correlation IDs stay unique and no batch processor is installed over nothing.
Note
#4206 already fixes this as a side effect of moving exporter construction into a registry — exporters.Build returns the NeverSample provider when the builder yields no exporter (pkg/gofr/traces/exporters/provider.go:52-55). Filing separately because the bug is live on development until that merges, and because it is worth fixing on its own terms if #4206 changes shape.
Found by @aryanmehrotra during review of #4205.
Source: gofr-dev/gofr