Skip to content

Python: emit all usage details on OTEL spans (fixes #5511)#6197

Open
hanhan761 wants to merge 2 commits into
microsoft:mainfrom
hanhan761:fix-5511-cached-tokens-otel
Open

Python: emit all usage details on OTEL spans (fixes #5511)#6197
hanhan761 wants to merge 2 commits into
microsoft:mainfrom
hanhan761:fix-5511-cached-tokens-otel

Conversation

@hanhan761
Copy link
Copy Markdown

Summary

Emit all usage details from UsageDetails as OTEL span attributes, not just input_token_count and output_token_count.

Issue

Fixes #5511

Changes

  • Added TOTAL_TOKENS constant for gen_ai.usage.total_tokens
  • Added _apply_usage_details() helper that emits all usage fields:
    • Maps standard keys (input_token_count, output_token_count, total_token_count) to standard OTEL attribute names
    • Passes through additional keys (e.g., cached_tokens, reasoning_tokens) as gen_ai.usage.{key}
  • Updated all 3 usage extraction sites to use the helper:
    • _get_response_attributes()
    • _apply_accumulated_usage()
    • EmbeddingTelemetryLayer

Verification

attrs = {}
_apply_usage_details(attrs, {
    input_token_count: 10,
    output_token_count: 20,
    cached_tokens: 5,
})
assert attrs[gen_ai.usage.input_tokens] == 10
assert attrs[gen_ai.usage.output_tokens] == 20
assert attrs[gen_ai.usage.cached_tokens] == 5

Copilot AI review requested due to automatic review settings May 30, 2026 07:17
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

This PR expands observability token-usage reporting by adding a total token attribute and centralizing usage-attribute extraction, and it exposes a new public alias for the history provider type.

Changes:

  • Added gen_ai.usage.total_tokens (OtelAttr.TOTAL_TOKENS) and mapped token usage keys to Otel attributes.
  • Introduced _apply_usage_details() to consistently apply usage fields across response/accumulated usage paths.
  • Exported ChatMessageStore as an alias of HistoryProvider from the package __init__.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.

File Description
python/packages/core/agent_framework/observability.py Adds TOTAL_TOKENS and a shared helper to apply token usage and extra usage keys onto span attributes.
python/packages/core/agent_framework/init.py Exposes ChatMessageStore as a public alias and adds it to __all__.

Comment on lines +2262 to +2266
_USAGE_ATTR_MAP: dict[str, str] = {
"input_token_count": OtelAttr.INPUT_TOKENS,
"output_token_count": OtelAttr.OUTPUT_TOKENS,
"total_token_count": OtelAttr.TOTAL_TOKENS,
}
Comment on lines +2269 to +2276
def _apply_usage_details(attributes: dict[str, Any], usage: Mapping[str, Any]) -> None:
for usage_key, otel_attr in _USAGE_ATTR_MAP.items():
value = usage.get(usage_key)
if value is not None:
attributes[otel_attr] = value
for usage_key, value in usage.items():
if usage_key not in _USAGE_ATTR_MAP and value is not None:
attributes[f"gen_ai.usage.{usage_key}"] = value
Comment on lines +2272 to +2273
if value is not None:
attributes[otel_attr] = value
SessionContext,
register_state_type,
)
ChatMessageStore = HistoryProvider
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Python: [Bug]: missing cached tokens on OTEL spans

3 participants