ReqLLM. Telemetry. OpenTelemetry
(ReqLLM v1.12.0)
View Source
Dependency-free helpers for mapping ReqLLM telemetry metadata to OpenTelemetry GenAI span data.
This module does not depend on an OpenTelemetry SDK and does not start or stop
spans on your behalf. Instead, it translates ReqLLM's native :telemetry
metadata into:
- GenAI span names
- GenAI span attributes
- span status hints
- span events (
exception, optionalgen_ai.client.inference.operation.details)
Content capture is opt-in through the :content option:
:none(default) — no message, instructions, or tool definitions are emitted.:attributes—gen_ai.input.messages,gen_ai.system_instructions,gen_ai.tool.definitions, andgen_ai.output.messagesare attached as span attributes.:event— the same payload is attached to a singlegen_ai.client.inference.operation.detailsspan event instead of the span attributes.
When content capture is on, ReqLLM request telemetry must also enable payload
capture with telemetry: [payloads: :raw], otherwise the request payload is
not available to map.
Reasoning text remains redacted in every content mode — reasoning parts are
intentionally omitted from gen_ai.input.messages / gen_ai.output.messages.
Summary
Functions
Builds terminal span data for a [:req_llm, :request, :exception] event.
Builds span creation data for a [:req_llm, :request, :start] event.
Builds terminal span data for a [:req_llm, :request, :stop] event.
Builds gen_ai.execute_tool sub-span stubs for server-side builtin
tool calls present on the response message.
Types
@type content_mode() :: :none | :attributes | :event
@type metric_record() :: map()
@type request_start_stub() :: %{ name: String.t(), kind: :client, attributes: map(), events: [otel_event()] }
@type request_terminal_stub() :: %{ attributes: map(), status: span_status(), events: [otel_event()], metrics: [metric_record()], tool_spans: [tool_span_stub()] }
@type span_status() :: :ok | {:error, String.t()}
@type tool_span_stub() :: %{ name: String.t(), kind: :internal, attributes: map(), status: span_status(), start_time: integer() | nil, end_time: integer() | nil }
Functions
@spec request_exception( map(), keyword() ) :: request_terminal_stub()
Builds terminal span data for a [:req_llm, :request, :exception] event.
@spec request_start( map(), keyword() ) :: request_start_stub()
Builds span creation data for a [:req_llm, :request, :start] event.
In content: :event mode the inference event payload is intentionally
deferred to the terminal stub (request_stop/2 / request_exception/2)
so the host emits exactly one gen_ai.client.inference.operation.details
event per span, carrying both request and response content. Start-side
request content is still attached as span attributes when
content: :attributes.
@spec request_stop( map(), keyword() ) :: request_terminal_stub()
Builds terminal span data for a [:req_llm, :request, :stop] event.
Pass measurements: %{duration: native} to populate metrics and the
gen_ai.response.time_to_first_chunk span attribute on streaming requests.
Pass langfuse: true to add langfuse.observation.cost_details (JSON-encoded)
whenever ReqLLM has computed a cost breakdown.
@spec tool_spans( map(), keyword() ) :: [tool_span_stub()]
Builds gen_ai.execute_tool sub-span stubs for server-side builtin
tool calls present on the response message.
Only entries flagged via ReqLLM.ToolCall.builtin?/1 are surfaced —
user-defined function tool execution happens in the caller's process
and must be instrumented there.
When metadata.builtin_tool_timing carries wall-clock nanoseconds for
a given call id (streaming path), the stub propagates start_time /
end_time so the translator can emit a span with the measured
duration. Otherwise the fields are nil, and the translator falls
back to "start span / end span" back-to-back — effectively a
zero-width marker recording that the invocation occurred inside the
parent's lifetime.