AuroraMeter. OpenTelemetry. Bridge
(Aurora Meter v1.0.0)
View Source
Internal. Not part of the supported API (see API inventory).
It may change in any release, including a patch. Hosts call
AuroraMeter.OpenTelemetry.attach/1.
Everything the OpenTelemetry bridge does, with the tracer as a parameter.
AuroraMeter.OpenTelemetry is compiled only when opentelemetry_api is
installed, and it is four lines of delegation into this module plus the
implementation of AuroraMeter.OpenTelemetry.Tracer that calls the real API.
All of the behaviour lives here so that it is compiled, and tested, in a build
with no OpenTelemetry at all.
What gets a span, and what deliberately does not
Slow work: the durable write, the flush, a replay batch, a hold reconciliation, an outbox delivery, a provider round trip. Every one of them is database-bound or network-bound and is worth a trace.
The hot path gets nothing. [:aurora_meter, :track],
[:aurora_meter, :reserve], [:aurora_meter, :broadcast],
[:aurora_meter, :cluster, :apply] and every gauge are not instrumented,
and there is no friendly switch to turn them on. track/4 runs at the rate a
metering library is built for; one span per increment would dominate the hot
path and the host's trace budget alike. A caller who really wants one passes
the event name in :events and owns the consequence.
Attributes carry no identifier
Every attribute goes through AuroraMeter.Telemetry.redact/2, so a tenant
key, a reference, an object id, a provider reference and an exception's
message are all dropped before anything reaches a tracer. An error is reported
as error_class (the exception module or the outcome tag), never as its
message, which is where a query, a key or a customer's data ends up.
tenant: :digest puts a stable pseudonym on the span instead, and
tenant: :raw puts the key itself there. Both are spelled out at the call
site so that carrying an identifier into a tracing pipeline is a decision
somebody wrote down.
Idempotency
attach/2 detaches its own handler ids before attaching, so calling it five
times leaves exactly the same handler set as calling it once. Two different
:name values are independent by construction, because the name is part of
every handler id.
Summary
Types
One instrumented event: its base name and whether it is a span triple.
Functions
Attaches one :telemetry handler per instrumented event name.
The events instrumented by default, as {base_event, :span | :flat}.
Removes every handler attached under name, and nothing else.
The handler id this bridge uses for name and event.
Event names this bridge never instruments unless the caller lists them.
Types
@type instrumented() :: {[atom()], :span | :flat}
One instrumented event: its base name and whether it is a span triple.
Functions
@spec attach(keyword()) :: :ok
Attaches one :telemetry handler per instrumented event name.
Options are AuroraMeter.OpenTelemetry.attach/1's, plus :tracer, the module
implementing AuroraMeter.OpenTelemetry.Tracer.
@spec default_events(keyword()) :: [instrumented()]
The events instrumented by default, as {base_event, :span | :flat}.
:include selects halves of the catalogue: [:core, :pro] by default.
Examples
iex> AuroraMeter.OpenTelemetry.Bridge.default_events(include: [:core])
...> |> Enum.map(&elem(&1, 0))
...> |> Enum.member?([:aurora_meter, :flush])
true
iex> AuroraMeter.OpenTelemetry.Bridge.default_events(include: [:core])
...> |> Enum.map(&elem(&1, 0))
...> |> Enum.member?([:aurora_meter, :track])
false
@spec detach(atom()) :: :ok
Removes every handler attached under name, and nothing else.
The handler id this bridge uses for name and event.
@spec never_by_default() :: [[atom()]]
Event names this bridge never instruments unless the caller lists them.
Examples
iex> [:aurora_meter, :track] in AuroraMeter.OpenTelemetry.Bridge.never_by_default()
true