fix(otel): restore OpenInference cache and reasoning token details in v2 mapper

This commit is contained in:
Yash Singh 2026-11-01 10:18:35 +05:30
parent 60fc121ce8
commit 0413b42347
No known key found for this signature in database
2 changed files with 47 additions and 0 deletions

View file

@ -190,6 +190,8 @@ class OpenInferenceMapper:
- ``llm.output_messages.{i}.message.role`` / ``...content``
- ``llm.output_messages.{i}.message.tool_calls.{j}.tool_call.*``
- ``llm.token_count.prompt`` / ``...completion`` / ``...total``
- ``llm.token_count.prompt_details.cache_read`` / ``...cache_write``
- ``llm.token_count.completion_details.reasoning``
- ``metadata`` — JSON object of allowlisted promoted request metadata
- ``input.value`` / ``output.value`` — JSON-serialized request / response
"""
@ -201,6 +203,9 @@ class OpenInferenceMapper:
"llm.token_count.prompt": lambda d: d.usage.input_tokens,
"llm.token_count.completion": lambda d: d.usage.output_tokens,
"llm.token_count.total": lambda d: d.usage.total_tokens,
"llm.token_count.prompt_details.cache_read": lambda d: d.usage.cache_read_input_tokens or None,
"llm.token_count.prompt_details.cache_write": lambda d: d.usage.cache_creation_input_tokens or None,
"llm.token_count.completion_details.reasoning": lambda d: d.usage.reasoning_tokens or None,
}
# Folded into the ``llm.invocation_parameters`` JSON blob.

View file

@ -100,6 +100,48 @@ def test_openinference_mapper_input_output_messages():
assert params["max_tokens"] == 128
_OPENINFERENCE_TOKEN_DETAIL_KEYS: Final = (
"llm.token_count.prompt_details.cache_read",
"llm.token_count.prompt_details.cache_write",
"llm.token_count.completion_details.reasoning",
)
def test_openinference_mapper_emits_cache_and_reasoning_token_details():
usage: Final = LLMUsage(
input_tokens=120,
output_tokens=40,
total_tokens=160,
cache_read_input_tokens=80,
cache_creation_input_tokens=30,
reasoning_tokens=25,
)
attrs: Final = OpenInferenceMapper().map(_llm_call(usage=usage))
assert attrs["llm.token_count.prompt_details.cache_read"] == 80
assert attrs["llm.token_count.prompt_details.cache_write"] == 30
assert attrs["llm.token_count.completion_details.reasoning"] == 25
@pytest.mark.parametrize(
"usage",
[
LLMUsage(input_tokens=12, output_tokens=8, total_tokens=20),
LLMUsage(
input_tokens=12,
output_tokens=8,
total_tokens=20,
cache_read_input_tokens=0,
cache_creation_input_tokens=0,
reasoning_tokens=0,
),
],
ids=["absent", "zero"],
)
def test_openinference_mapper_omits_missing_token_details(usage: LLMUsage):
attrs: Final = OpenInferenceMapper().map(_llm_call(usage=usage))
assert not set(_OPENINFERENCE_TOKEN_DETAIL_KEYS) & set(attrs)
def test_openinference_mapper_skips_non_llm_roles():
from litellm.integrations.otel.model.payloads import GuardrailSpanData