style(langchain): format codebase and verify ToolNode agent creation …#4368
style(langchain): format codebase and verify ToolNode agent creation …#4368ManyaS-Git wants to merge 1 commit into
Conversation
📝 WalkthroughWalkthroughThis PR reformats LangChain instrumentation, LangGraph patching, span utilities, event emission, vendor rules, fixtures, and extensive tests. Existing wrapper targets, tracing behavior, metric expectations, event payloads, and test logic are preserved. ChangesLangChain instrumentation
Estimated code review effort: 2 (Simple) | ~15 minutes Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment Warning |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In
`@packages/opentelemetry-instrumentation-langchain/opentelemetry/instrumentation/langchain/callback_handler.py`:
- Around line 745-749: Update the token-count initialization in the callback
handling flow around total_tokens so missing prompt and completion values
default to 0 for arithmetic and comparisons, while preserving None when setting
semantic span attributes so absent token data remains omitted. Ensure the
total-token calculation and the later prompt_tokens/completion_tokens checks
cannot receive None.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 441ae3c1-2a99-480f-a99b-52e713957e06
⛔ Files ignored due to path filters (1)
packages/opentelemetry-instrumentation-langchain/uv.lockis excluded by!**/*.lock
📒 Files selected for processing (23)
packages/opentelemetry-instrumentation-langchain/opentelemetry/instrumentation/langchain/__init__.pypackages/opentelemetry-instrumentation-langchain/opentelemetry/instrumentation/langchain/callback_handler.pypackages/opentelemetry-instrumentation-langchain/opentelemetry/instrumentation/langchain/event_emitter.pypackages/opentelemetry-instrumentation-langchain/opentelemetry/instrumentation/langchain/patch.pypackages/opentelemetry-instrumentation-langchain/opentelemetry/instrumentation/langchain/span_utils.pypackages/opentelemetry-instrumentation-langchain/opentelemetry/instrumentation/langchain/utils.pypackages/opentelemetry-instrumentation-langchain/opentelemetry/instrumentation/langchain/vendor_detection.pypackages/opentelemetry-instrumentation-langchain/tests/conftest.pypackages/opentelemetry-instrumentation-langchain/tests/metrics/test_langchain_metrics.pypackages/opentelemetry-instrumentation-langchain/tests/test_agents.pypackages/opentelemetry-instrumentation-langchain/tests/test_batch_metadata.pypackages/opentelemetry-instrumentation-langchain/tests/test_chains.pypackages/opentelemetry-instrumentation-langchain/tests/test_context_token_lifecycle.pypackages/opentelemetry-instrumentation-langchain/tests/test_documents_chains.pypackages/opentelemetry-instrumentation-langchain/tests/test_finish_reasons.pypackages/opentelemetry-instrumentation-langchain/tests/test_generation_role_extraction.pypackages/opentelemetry-instrumentation-langchain/tests/test_langgraph.pypackages/opentelemetry-instrumentation-langchain/tests/test_lcel.pypackages/opentelemetry-instrumentation-langchain/tests/test_llms.pypackages/opentelemetry-instrumentation-langchain/tests/test_non_ascii_content.pypackages/opentelemetry-instrumentation-langchain/tests/test_structured_output.pypackages/opentelemetry-instrumentation-langchain/tests/test_tool_call_content.pypackages/opentelemetry-instrumentation-langchain/tests/test_tool_calls.py
| total_tokens = token_usage.get("total_tokens") or (prompt_tokens + completion_tokens) | ||
|
|
||
| _set_span_attribute( | ||
| span, GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS, prompt_tokens | ||
| ) | ||
| _set_span_attribute( | ||
| span, GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS, completion_tokens | ||
| ) | ||
| _set_span_attribute( | ||
| span, SpanAttributes.GEN_AI_USAGE_TOTAL_TOKENS, total_tokens | ||
| ) | ||
| _set_span_attribute(span, GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS, prompt_tokens) | ||
| _set_span_attribute(span, GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS, completion_tokens) | ||
| _set_span_attribute(span, SpanAttributes.GEN_AI_USAGE_TOTAL_TOKENS, total_tokens) |
There was a problem hiding this comment.
🩺 Stability & Availability | 🔴 Critical | ⚡ Quick win
Prevent TypeError when token counts are missing.
If the token_usage dictionary is empty or lacks explicit prompt/completion token keys, both prompt_tokens and completion_tokens will evaluate to None. This causes a TypeError when computing prompt_tokens + completion_tokens, and another TypeError later when evaluating if prompt_tokens > 0: (around line 753). Defaulting them to 0 prevents both crashes while retaining the exact semantic attribute omission via None.
🔧 Proposed fix
- total_tokens = token_usage.get("total_tokens") or (prompt_tokens + completion_tokens)
-
- _set_span_attribute(span, GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS, prompt_tokens)
- _set_span_attribute(span, GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS, completion_tokens)
- _set_span_attribute(span, SpanAttributes.GEN_AI_USAGE_TOTAL_TOKENS, total_tokens)
+ prompt_tokens = prompt_tokens or 0
+ completion_tokens = completion_tokens or 0
+ total_tokens = token_usage.get("total_tokens") or (prompt_tokens + completion_tokens)
+
+ _set_span_attribute(span, GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS, prompt_tokens if prompt_tokens > 0 else None)
+ _set_span_attribute(span, GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS, completion_tokens if completion_tokens > 0 else None)
+ _set_span_attribute(span, SpanAttributes.GEN_AI_USAGE_TOTAL_TOKENS, total_tokens if total_tokens > 0 else None)📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| total_tokens = token_usage.get("total_tokens") or (prompt_tokens + completion_tokens) | |
| _set_span_attribute( | |
| span, GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS, prompt_tokens | |
| ) | |
| _set_span_attribute( | |
| span, GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS, completion_tokens | |
| ) | |
| _set_span_attribute( | |
| span, SpanAttributes.GEN_AI_USAGE_TOTAL_TOKENS, total_tokens | |
| ) | |
| _set_span_attribute(span, GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS, prompt_tokens) | |
| _set_span_attribute(span, GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS, completion_tokens) | |
| _set_span_attribute(span, SpanAttributes.GEN_AI_USAGE_TOTAL_TOKENS, total_tokens) | |
| prompt_tokens = prompt_tokens or 0 | |
| completion_tokens = completion_tokens or 0 | |
| total_tokens = token_usage.get("total_tokens") or (prompt_tokens + completion_tokens) | |
| _set_span_attribute(span, GenAIAttributes.GEN_AI_USAGE_INPUT_TOKENS, prompt_tokens if prompt_tokens > 0 else None) | |
| _set_span_attribute(span, GenAIAttributes.GEN_AI_USAGE_OUTPUT_TOKENS, completion_tokens if completion_tokens > 0 else None) | |
| _set_span_attribute(span, SpanAttributes.GEN_AI_USAGE_TOTAL_TOKENS, total_tokens if total_tokens > 0 else None) |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In
`@packages/opentelemetry-instrumentation-langchain/opentelemetry/instrumentation/langchain/callback_handler.py`
around lines 745 - 749, Update the token-count initialization in the callback
handling flow around total_tokens so missing prompt and completion values
default to 0 for arithmetic and comparisons, while preserving None when setting
semantic span attributes so absent token data remains omitted. Ensure the
total-token calculation and the later prompt_tokens/completion_tokens checks
cannot receive None.
…patch
feat(instrumentation): ...orfix(instrumentation): ....Summary by CodeRabbit