ReqLLM. Telemetry
(ReqLLM v1.13.0)
View Source
Native :telemetry emitter for ReqLLM request and reasoning lifecycle.
Every event for a logical request shares the same request_id, so request
lifecycle, reasoning lifecycle, and token usage can be correlated without
provider-specific parsing. The OpenTelemetry bridge (ReqLLM.OpenTelemetry)
is built on top of these events — attach handlers here for billing, tenant
attribution, or any integration that should not depend on an OpenTelemetry
SDK.
Event families
| Event | Measurements |
|---|---|
[:req_llm, :request, :start] | system_time |
[:req_llm, :request, :stop] | duration, system_time |
[:req_llm, :request, :exception] | duration, system_time |
[:req_llm, :reasoning, :start] | system_time |
[:req_llm, :reasoning, :update] | system_time |
[:req_llm, :reasoning, :stop] | duration, system_time |
[:req_llm, :token_usage] | token + cost counters |
duration is in native monotonic time units — convert with
System.convert_time_unit/3 if you want milliseconds.
Request metadata
All request lifecycle events carry the same metadata map: request_id,
operation, mode, provider, model, transport, reasoning,
request_summary, response_summary, http_status, finish_reason,
usage, request_options, server, streaming. The full shape and a
worked example live in the Telemetry guide.
Reasoning events never include raw thinking text — they are metadata-only even with payload capture enabled.
Payload modes
Default is metadata-only. Opt into raw payloads globally or per call:
config :req_llm, telemetry: [payloads: :raw]
ReqLLM.generate_text(model, prompt, telemetry: [payloads: :raw])Raw payloads are still sanitized — reasoning text is redacted, binary parts are summarized by byte size and media type, embeddings report vector counts rather than vectors. Use with care in multi-tenant systems.
Token usage compatibility
[:req_llm, :token_usage] remains available for existing consumers and now
fires for streaming as well as non-streaming requests. For new integrations,
prefer [:req_llm, :request, :stop] — it includes duration, finish reason,
summaries, and normalized reasoning metadata alongside usage.
See also
- Telemetry guide — full event shapes, reasoning normalization, payload capture, attach examples
ReqLLM.OpenTelemetry— the auto-attached GenAI client span bridgeReqLLM.Telemetry.OpenTelemetry— dependency-free OTel mapper
Summary
Functions
Emits the compatibility token usage event.
Emits request exception telemetry and returns the updated context.
Builds a telemetry context for a request lifecycle.
Observes a terminal response and updates response and reasoning state.
Folds a streaming chunk into the telemetry context and emits milestone reasoning events when applicable.
Stores telemetry context in a Req request.
Stores telemetry context in a Req response private map.
Pre-populates context.server from a request source that start_request
cannot read directly (e.g. an HTTPContext for streaming flows). Has no
effect if the source yields no server info.
Returns the normalized metadata map for reasoning lifecycle events.
Reads telemetry context from a Req request.
Returns the private key used to store telemetry context on Req requests.
Returns the normalized request metadata map for request lifecycle events.
Emits request start telemetry and returns the updated context.
Emits request stop telemetry and returns the updated context.
Extracts token usage metadata from a Req response private map.
Types
@type context() :: %{ request_id: String.t(), model: LLMDB.Model.t(), operation: atom(), mode: lifecycle_mode(), transport: transport(), payload_mode: payload_mode(), reasoning_contract: reasoning_contract(), original_opts: keyword(), request_options: map(), server: map(), request_summary: map(), request_payload: any(), request_started?: boolean(), request_stopped?: boolean(), started_at: integer() | nil, request_started_system_time: integer() | nil, first_chunk_at: integer() | nil, requested_reasoning: map(), effective_reasoning: map(), reasoning_started?: boolean(), reasoning_started_at: integer() | nil, reasoning_observation: map(), response_summary_state: map() }
@type lifecycle_mode() :: :sync | :stream
@type payload_mode() :: :none | :raw
@type reasoning_contract() ::
:openai_effort
| :openai_or_thinking
| :anthropic_thinking
| :platform_anthropic
| :google_budget
| :alibaba_thinking
| :thinking_toggle
| :zenmux_reasoning
| :unsupported
@type transport() :: :req | :finch
Functions
@spec emit_token_usage(LLMDB.Model.t(), map() | nil, keyword()) :: :ok
Emits the compatibility token usage event.
@spec exception_request(context(), Exception.t() | term(), keyword()) :: context()
Emits request exception telemetry and returns the updated context.
@spec new_context(LLMDB.Model.t(), keyword(), keyword()) :: context()
Builds a telemetry context for a request lifecycle.
Observes a terminal response and updates response and reasoning state.
@spec observe_stream_chunk(context(), ReqLLM.StreamChunk.t()) :: context()
Folds a streaming chunk into the telemetry context and emits milestone reasoning events when applicable.
Called by ReqLLM's streaming pipeline (ReqLLM.StreamServer) for every
chunk produced during a streaming request. Returns an updated context
with:
first_chunk_atset toSystem.monotonic_time/0on the first non-empty content chunk or first tool call — this feedsstreaming.time_to_first_chunkon the request lifecycle metadata andgen_ai.client.operation.time_to_first_chunkon the OpenTelemetry bridge.response_summarycounters incremented for text bytes, thinking bytes, tool calls, etc.- A
[:req_llm, :reasoning, :update]event emitted withmilestone: :content_startedthe first time a reasoning chunk is observed.
Hosts integrating against the low-level streaming API (ReqLLM.Streaming)
do not normally call this directly — ReqLLM threads it through the
streaming pipeline. The high-level stream_text/3 / stream_object/4
APIs use it transparently.
@spec put_request_context(Req.Request.t(), context()) :: Req.Request.t()
Stores telemetry context in a Req request.
@spec put_response_context(Req.Response.t(), context()) :: Req.Response.t()
Stores telemetry context in a Req response private map.
Pre-populates context.server from a request source that start_request
cannot read directly (e.g. an HTTPContext for streaming flows). Has no
effect if the source yields no server info.
Returns the normalized metadata map for reasoning lifecycle events.
@spec request_context(Req.Request.t()) :: context() | nil
Reads telemetry context from a Req request.
@spec request_context_key() :: atom()
Returns the private key used to store telemetry context on Req requests.
Returns the normalized request metadata map for request lifecycle events.
Emits request start telemetry and returns the updated context.
Emits request stop telemetry and returns the updated context.
Extracts token usage metadata from a Req response private map.