Global TracerProvider registration and Tracer retrieval
(OTel trace/api.md §TracerProvider, L88-L157).
Holds the process-wide pointer to the installed
TracerProvider implementation. When no SDK is installed,
all operations resolve to the no-op tracer
(Otel.API.Trace.Tracer.Noop, matching the
{otel_tracer_noop, []} fallback in
opentelemetry-erlang).
No API-level Tracer cache
get_tracer/1 does not cache the Tracer it returns.
Every call delegates to the registered provider's
get_tracer/2 callback (or returns Noop if none). This
avoids a bootstrap race: if an early get_tracer/1 is
made before the SDK registers, a cached Noop would
survive provider installation and silently drop every
subsequent span.
The spec's "identical for identical parameters"
requirement (trace/api.md L136-L140) is still satisfied
because SDK implementations return structurally-equal
Tracer tuples for equal scopes, and the Noop case is
trivially {Noop, []} on every call.
This is an intentional divergence from
opentelemetry-erlang — its opentelemetry.erl caches
tracers in persistent_term keyed by scope components.
Our implementation trades that micro-optimisation for
bootstrap-safety correctness. SDK implementations that
care about Tracer-instance reuse should cache internally
on their own get_tracer/2 path.
Storage
The global provider pointer lives in :persistent_term.
This diverges from erlang — its
otel_tracer_provider.erl uses a registered gen_server
reached via gen_server:call/2, while we read a
persistent_term slot directly to avoid the round-trip
on the hot path.
All functions are safe for concurrent use (spec L842).
Public API
| Function | Role |
|---|---|
get_tracer/1 | Application (OTel API MUST) — Get a Tracer (L107-L157) |
@callback get_tracer/2 | SDK (OTel API MUST) — Dispatch callback (L107-L157) |
get_provider/0 | SDK (installation hook) — access global provider (L95-L97) |
set_provider/1 | SDK (installation hook) — register global provider (L95-L97) |
References
- OTel Trace API §TracerProvider:
opentelemetry-specification/specification/trace/api.mdL88-L157, L842 - Reference impl (tracer cache):
opentelemetry-erlang/apps/opentelemetry_api/src/opentelemetry.erl - Reference impl (global provider):
opentelemetry-erlang/apps/opentelemetry_api/src/otel_tracer_provider.erl
Summary
Callbacks
SDK (OTel API MUST) — Dispatch callback invoked by
get_tracer/1.
Functions
SDK (installation hook) — access the global TracerProvider
(trace/api.md L95-L97).
Application (OTel API MUST) — "Get a Tracer" (trace/api.md
L107-L157).
SDK (installation hook) — register the global
TracerProvider (trace/api.md L95-L97).
Types
A {dispatcher_module, state} pair.
The API layer treats the state as opaque; only
dispatcher_module knows how to use it. This mirrors
Otel.API.Trace.Tracer.t/0 and keeps the API decoupled from
SDK internals (GenServer, Registry, etc.).
dispatcher_module MUST implement the
Otel.API.Trace.TracerProvider behaviour.
Callbacks
@callback get_tracer( state :: term(), instrumentation_scope :: Otel.API.InstrumentationScope.t() ) :: Otel.API.Trace.Tracer.t()
SDK (OTel API MUST) — Dispatch callback invoked by
get_tracer/1.
Implementations receive the opaque state they registered
via set_provider/1 along with the requested instrumentation
scope, and return a Tracer. The get_tracer/2 shape is the
API↔SDK dispatch contract for §"Get a Tracer"
(trace/api.md L107-L157).
Functions
@spec get_provider() :: t() | nil
SDK (installation hook) — access the global TracerProvider
(trace/api.md L95-L97).
"the API SHOULD provide a way to set/register and access a global default
TracerProvider."
Returns the currently registered provider, or nil if
none is registered.
@spec get_tracer(instrumentation_scope :: Otel.API.InstrumentationScope.t()) :: Otel.API.Trace.Tracer.t()
Application (OTel API MUST) — "Get a Tracer" (trace/api.md
L107-L157).
Returns a Tracer for the given instrumentation scope. Each
call delegates to the registered provider's get_tracer/2
callback, or returns the noop tracer when no provider is
installed (spec L120-121: invalid or unresolved scope
MUST still yield a working Tracer rather than crash) —
no API-level cache, see the module's "No API-level
Tracer cache" section.
@spec set_provider(provider :: t()) :: :ok
SDK (installation hook) — register the global
TracerProvider (trace/api.md L95-L97).
"the API SHOULD provide a way to set/register and access a global default
TracerProvider."
Registers the given {module, state} as the global
TracerProvider. The SDK TracerProvider calls this from its
init/1 with {__MODULE__, server_ref}; module must
implement the Otel.API.Trace.TracerProvider behaviour.