ReqLLM.OpenTelemetry.Attributes (ReqLLM v1.12.0)

View Source

Builds the scalar gen_ai.* / server.* / error.* attribute maps emitted on GenAI client spans, from ReqLLM request lifecycle metadata.

Shared between the live bridge (ReqLLM.OpenTelemetry) and the dependency-free mapper (ReqLLM.Telemetry.OpenTelemetry) so both emit identical payloads. See ReqLLM.OpenTelemetry for the end-to-end flow.

start/1 runs on [:req_llm, :request, :start] and returns roughly:

%{
  "gen_ai.provider.name" => "openai",
  "gen_ai.operation.name" => "chat",
  "gen_ai.request.model" => "gpt-5",
  "gen_ai.request.temperature" => 0.7,
  "server.address" => "api.openai.com",
  "server.port" => 443,
  "req_llm.request_id" => "2184"
}

terminal/1 is merged on top at :stop (response id, finish reasons, usage, embedding dims, OpenAI extension fields, streaming TTFC). exception/1 and exception_event/1 cover the error path.

Keys are binary spec names; the live bridge atomizes them at the adapter boundary. nil and empty-list values are dropped so OTel backends never see blank-but-present attributes.

Summary

Functions

Returns the normalized cost breakdown map for langfuse.observation.cost_details, or nil when no cost info is present. Result is suitable for Jason.encode!/1.

Returns the span error-status hint for stop events. nil for success.

Resolves a error.type string from request metadata. Falls back to "_OTHER" when nothing is recognizable.

Builds attributes added on :exception events. Includes error.type.

Returns the exception event payload (exception.type, exception.message).

Returns nil for empty strings and nil, otherwise returns the value. Used by metric and attribute builders to drop blank-but-present fields.

Resolves the GenAI provider name from request metadata, falling back to the model's provider when metadata.provider is absent.

Returns the requested model id, e.g. "gpt-5".

Builds GenAI span start attributes from request lifecycle metadata.

Returns gen_ai.response.time_to_first_chunk as seconds, or nil for non-streaming requests or streams that never observed a content chunk.

Builds the additional attributes that become available at request stop.

Functions

cost_breakdown(metadata)

@spec cost_breakdown(map()) :: %{optional(String.t()) => number()} | nil

Returns the normalized cost breakdown map for langfuse.observation.cost_details, or nil when no cost info is present. Result is suitable for Jason.encode!/1.

error_status(metadata)

@spec error_status(map()) :: nil | {String.t(), String.t()}

Returns the span error-status hint for stop events. nil for success.

error_type(metadata)

@spec error_type(map()) :: String.t()

Resolves a error.type string from request metadata. Falls back to "_OTHER" when nothing is recognizable.

exception(metadata)

@spec exception(map()) :: %{optional(String.t()) => term()}

Builds attributes added on :exception events. Includes error.type.

exception_event(metadata)

@spec exception_event(map()) :: %{optional(String.t()) => term()}

Returns the exception event payload (exception.type, exception.message).

present(value)

@spec present(any()) :: any()

Returns nil for empty strings and nil, otherwise returns the value. Used by metric and attribute builders to drop blank-but-present fields.

provider_name(metadata)

@spec provider_name(map()) :: String.t() | nil

Resolves the GenAI provider name from request metadata, falling back to the model's provider when metadata.provider is absent.

request_model(metadata)

@spec request_model(map()) :: String.t() | nil

Returns the requested model id, e.g. "gpt-5".

start(metadata)

@spec start(map()) :: %{optional(String.t()) => term()}

Builds GenAI span start attributes from request lifecycle metadata.

The returned map uses binary attribute names as defined by the OpenTelemetry GenAI semantic conventions. Callers that need atom-keyed maps (e.g. the live bridge) atomize at the adapter boundary.

streaming_ttfc_seconds(metadata)

@spec streaming_ttfc_seconds(map()) :: float() | nil

Returns gen_ai.response.time_to_first_chunk as seconds, or nil for non-streaming requests or streams that never observed a content chunk.

terminal(metadata)

@spec terminal(map()) :: %{optional(String.t()) => term()}

Builds the additional attributes that become available at request stop.

These are merged on top of the start attributes already on the span.