Skip to content

feat(langchain): report cached and reasoning token usage in Langchain/Langgraph#6800

Open
joaquinhuigomez wants to merge 1 commit into
getsentry:masterfrom
joaquinhuigomez:feat/langchain-langgraph-cached-reasoning-tokens
Open

feat(langchain): report cached and reasoning token usage in Langchain/Langgraph#6800
joaquinhuigomez wants to merge 1 commit into
getsentry:masterfrom
joaquinhuigomez:feat/langchain-langgraph-cached-reasoning-tokens

Conversation

@joaquinhuigomez

Copy link
Copy Markdown

Description

The Langchain and Langgraph integrations only recorded input/output/total token counts, dropping cached input tokens and reasoning output tokens — even though SPANDATA defines both and the OpenAI, OpenAI Agents, and Google GenAI integrations already report them. This makes cache-discount and reasoning-token cost calculations inaccurate for Langchain/Langgraph apps.

This extracts cache_read/cached_tokens and reasoning/reasoning_tokens from both the LangChain usage_metadata detail shape (input_token_details/output_token_details) and OpenAI-style details dicts (prompt_tokens_details/completion_tokens_details), and sets gen_ai.usage.input_tokens.cached / gen_ai.usage.output_tokens.reasoning in both integrations. Tests cover both detail shapes, span data emission, and the Langgraph accumulation loop (all three fail on master and pass with this change); ruff clean.

Issues

The Langchain and Langgraph integrations only recorded input, output,
and total token counts, dropping cached input tokens and reasoning
output tokens even though SPANDATA defines both and the OpenAI, OpenAI
Agents, and Google GenAI integrations already report them.

Extract cache_read/cached_tokens and reasoning/reasoning_tokens from
both the LangChain usage_metadata detail shape and OpenAI-style
details dicts, and set gen_ai.usage.input_tokens.cached and
gen_ai.usage.output_tokens.reasoning on spans in both integrations.

Fixes getsentryGH-6799
@joaquinhuigomez joaquinhuigomez requested a review from a team as a code owner July 11, 2026 13:18
Comment on lines +752 to +754
cached_tokens = _get_value(input_details, "cache_read") or _get_value(
input_details, "cached_tokens"
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Bug: The use of the or operator incorrectly handles legitimate 0 values for token counts, causing them to be evaluated as None and dropped from span data.
Severity: MEDIUM

Suggested Fix

Refactor the logic to avoid using the or operator for fallback when 0 is a valid value. Instead, explicitly check if the first value is None before attempting to retrieve the second value. This ensures that a 0 from the primary key is preserved.

Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent. Verify if this is a real issue. If it is, propose a fix; if not, explain why it's
not valid.

Location: sentry_sdk/integrations/langchain.py#L752-L754

Potential issue: In the `_extract_tokens` function, the use of the `or` operator to
select between two potential keys for token counts (e.g., `cache_read` or
`cached_tokens`) leads to incorrect behavior when a valid token count is `0`. Because
`0` is a falsy value in Python, the expression proceeds to evaluate the right-hand side.
If the alternative key does not exist, the result becomes `None`. This causes legitimate
zero-token counts for cached or reasoning tokens to be silently dropped instead of being
reported in span data. While this has minimal impact on cost calculations, it is a
correctness issue that prevents accurate reporting of API responses.

Also affects:

  • sentry_sdk/integrations/langchain.py:761~763
  • sentry_sdk/integrations/langchain.py:737~738
  • sentry_sdk/integrations/langchain.py:742~743

Did we get this right? 👍 / 👎 to inform future reviews.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Want reviews to match your repository better? Bugbot Learning can learn team-specific rules from PR activity. A team admin can enable Learning in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit cb26c51. Configure here.

cached_tokens += int(input_details.get("cached_tokens") or 0)

output_details = token_usage.get("completion_tokens_details") or {}
reasoning_tokens += int(output_details.get("reasoning_tokens") or 0)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Langgraph misses LangChain token shapes

Medium Severity

_set_usage_data only reads cached_tokens and reasoning_tokens from OpenAI-style prompt_tokens_details / completion_tokens_details. It never checks LangChain’s input_token_details / output_token_details or the cache_read / reasoning keys that _extract_tokens handles in the Langchain integration, so cached and reasoning usage can be omitted on Langgraph spans.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit cb26c51. Configure here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Langchain and Langgraph don't report cached/reasoning token usage

2 participants