Double-Init Guard
Double-Init Guard
setup_telemetry should be called once per process. Calling it twice was previously a silent failure: the OTel SDK logs a warning about provider override but otherwise carries on, producing subtly broken telemetry that is hard to diagnose.
As of the architectural fixes, a second call with config.enabled=True raises RuntimeError. This page explains why, how, and how to escape it if you really need to.
The Problem
OTel SDK enforces a one-shot rule: trace.set_tracer_provider(p) only works if no provider has been set yet. Later calls log a warning and silently no-op. Same for MeterProvider.
Before the guard, this failure mode was invisible to NeMo Lens callers:
The result: partial observability, no error, no easy diagnosis. Instrumentation sites that use handle.tracer silently produce no data.
The Guard
NeMo Lens tracks whether setup_telemetry has succeeded with config.enabled=True:
The error is immediate and actionable. Callers learn about the mistake during development, not from a half-broken trace in production.
When the Guard Does Not Fire
The guard does not fire when calling with a disabled configuration or during testing.
Calling Twice with a Disabled Configuration
Calling setup_telemetry(config_disabled) twice is fine. No provider is installed either time, so there is no conflict. The _INITIALIZED flag stays False.
Testing
Tests need to call setup_telemetry many times — each test wants a fresh state. Two options:
-
Reset the flag in a fixture (the NeMo Lens approach):
-
Pass
_allow_reinit=True(for individual test cases):
The leading underscore signals “internal, don’t use in production code.” Tests are the only legitimate use.
Double Import
If your app imports a module that calls setup_telemetry twice due to a broken module system, you will hit the guard immediately. Fix the import; do not pass _allow_reinit.
What to Do When You See the Error
First, find the second call. The stack trace points at it. Common causes:
- A test runner without the reset fixture.
- Two entry points that both call
setup_telemetry(e.g., training script and inference server sharing a module). - A main program that calls a library which calls
setup_telemetryinternally.
The fix depends on the cause:
- Test runner: add or repair the reset fixture.
- Two entry points: make one of them check whether telemetry is already initialized (expose a getter) and skip its call.
- Library that initializes telemetry: probably should not. Libraries should accept a
TelemetryHandle(or nothing) and let the application decide whether to initialize.
Do not try: setup_telemetry() except RuntimeError: pass. That hides the real bug.
Why This Is Not Configurable
The natural alternative would be a force_reinit public parameter rather than _allow_reinit. The underscore name signals that this is not a supported workflow.
Production code should call setup_telemetry exactly once at startup. If re-initialization is needed, there is likely a structural problem: a library is initializing something the application should own, or two subsystems are competing over global state.
The escape hatch exists for testing; making it public would encourage working around the bug instead of fixing it.
Interaction with the Global OTel State
The guard tracks the NeMo Lens _INITIALIZED flag. The OTel SDK’s own one-shot rule also still applies. Resetting _INITIALIZED in a test without also resetting the SDK’s _TRACER_PROVIDER_SET_ONCE would cause NeMo Lens to permit reinitialization while the SDK blocks it. The test would produce spans on a no-op provider and assertions would fail mysteriously.
The NeMo Lens conftest.py resets both. If you have a test infrastructure that needs to reset state, copy the pattern from there.