Skip to content

Conversation

@nirga
Copy link
Member

@nirga nirga commented Aug 2, 2025

Fixed issue where metadata from Langchain batch() and abatch() method calls were not being populated as span attributes. The metadata was previously only stored in the OpenTelemetry context for propagation but never set as actual span attributes, making it difficult to correlate errors with specific data points.

Changes:

  • Modified _create_span method to set sanitized metadata as span attributes
  • Added tests for both sync batch and async abatch operations
  • Metadata is now accessible as traceloop.association.properties.* attributes

Fixes: #3213

🤖 Generated with Claude Code

  • I have added tests that cover my changes.
  • If adding a new instrumentation or changing an existing one, I've added screenshots from some observability platform showing the change.
  • PR name follows conventional commits format: feat(instrumentation): ... or fix(instrumentation): ....
  • (If applicable) I have updated the documentation accordingly.

Important

Fixes metadata not being set as span attributes in Langchain batch operations by modifying _create_span and adding tests.

  • Behavior:
    • Modified _create_span in callback_handler.py to set sanitized metadata as span attributes for batch operations.
    • Metadata is now accessible as traceloop.association.properties.* attributes.
  • Tests:
    • Added test_batch_metadata.py to verify metadata is recorded as span attributes in sync and async batch calls.
    • Introduced test cassettes test_async_batch_metadata_in_span_attributes.yaml and test_batch_metadata_in_span_attributes.yaml for reliable testing of metadata propagation.

This description was created by Ellipsis for b5f242a. You can customize this summary. It will automatically update as commits are pushed.


Summary by CodeRabbit

  • New Features
    • Span attributes now include metadata properties, enhancing traceability for batch operations.
  • Tests
    • Added tests verifying metadata is correctly recorded as span attributes in synchronous and asynchronous batch calls.
    • Introduced test cassettes to enable reliable and repeatable testing of metadata propagation in span attributes.

Fixed issue where metadata from Langchain batch() and abatch() method calls
were not being populated as span attributes. The metadata was previously only
stored in the OpenTelemetry context for propagation but never set as actual
span attributes, making it difficult to correlate errors with specific data points.

Changes:
- Modified _create_span method to set sanitized metadata as span attributes
- Added tests for both sync batch and async abatch operations
- Metadata is now accessible as traceloop.association.properties.* attributes

Fixes: #3213

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
@coderabbitai
Copy link

coderabbitai bot commented Aug 2, 2025

Walkthrough

The changes introduce logic to extract metadata from Langchain batch and abatch calls and set them as span attributes in OpenTelemetry tracing. New tests and VCR cassettes are added to verify that both synchronous and asynchronous batch metadata are correctly recorded as span attributes during instrumentation.

Changes

Cohort / File(s) Change Summary
Span Attribute Population Logic
packages/opentelemetry-instrumentation-langchain/opentelemetry/instrumentation/langchain/callback_handler.py
Enhanced _create_span to set span attributes from sanitized metadata, prefixing keys appropriately when metadata is provided.
Synchronous Batch Metadata Test & Cassette
packages/opentelemetry-instrumentation-langchain/tests/test_batch_metadata.py,
packages/opentelemetry-instrumentation-langchain/tests/cassettes/test_batch_metadata/test_batch_metadata_in_span_attributes.yaml
Added a new test and a VCR cassette to verify that metadata in synchronous batch calls is propagated to span attributes.
Asynchronous Batch Metadata Test & Cassette
packages/opentelemetry-instrumentation-langchain/tests/test_batch_metadata.py,
packages/opentelemetry-instrumentation-langchain/tests/cassettes/test_batch_metadata/test_async_batch_metadata_in_span_attributes.yaml
Added an async test and corresponding VCR cassette to validate metadata propagation in async batch (abatch) calls.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Langchain Instrumentation
    participant OpenTelemetry Span

    User->>Langchain Instrumentation: Call batch/abatch with metadata
    Langchain Instrumentation->>Langchain Instrumentation: Extract and sanitize metadata
    Langchain Instrumentation->>OpenTelemetry Span: Set span attributes from metadata
    OpenTelemetry Span-->>Langchain Instrumentation: Span with metadata attributes
    Langchain Instrumentation-->>User: Return batch/abatch results
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~15 minutes

Assessment against linked issues

Objective Addressed Explanation
Use metadata from invoke calls in Langchain to populate span attributes (#3213)
Support both synchronous and asynchronous batch calls for metadata propagation (#3213)
Ensure span attributes are correctly prefixed and sanitized (#3213)

Assessment against linked issues: Out-of-scope changes

No out-of-scope changes detected.

Poem

In the fields where traces loop and span,
Metadata hops in, as only code can.
Batch or abatch, sync or async delight,
Now every custom key is traced in flight!
With carrots and cassettes, we hop and cheer—
The span attributes are finally here!
🥕✨


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f0475f2 and b5f242a.

📒 Files selected for processing (1)
  • packages/opentelemetry-instrumentation-langchain/tests/test_batch_metadata.py (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/opentelemetry-instrumentation-langchain/tests/test_batch_metadata.py
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: Test Packages (3.11)
  • GitHub Check: Test Packages (3.10)
  • GitHub Check: Test Packages (3.12)
  • GitHub Check: Build Packages (3.11)
  • GitHub Check: Test Packages (3.9)
  • GitHub Check: Lint
✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch langchain-metadata-fix

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@ellipsis-dev ellipsis-dev bot left a comment

Choose a reason for hiding this comment

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

Important

Looks good to me! 👍

Reviewed everything up to f0475f2 in 1 minute and 23 seconds. Click for details.
  • Reviewed 572 lines of code in 4 files
  • Skipped 0 files when reviewing.
  • Skipped posting 2 draft comments. View those below.
  • Modify your settings and rules to customize what types of comments Ellipsis leaves. And don't forget to react with 👍 or 👎 to teach Ellipsis.
1. packages/opentelemetry-instrumentation-langchain/opentelemetry/instrumentation/langchain/callback_handler.py:237
  • Draft comment:
    Good enhancement: metadata is now correctly set as span attributes using sanitized values. Consider adding a short note that the attributes are prefixed with '{SpanAttributes.TRACELOOP_ASSOCIATION_PROPERTIES}' to clarify the naming convention for future maintainers.
  • Reason this comment was not posted:
    Decided after close inspection that this draft comment was likely wrong and/or not actionable: usefulness confidence = 10% vs. threshold = 50% The comment is suggesting a minor documentation improvement to clarify the prefix used. While technically correct, the prefix usage is already clear from the code itself. The comment is not pointing out a bug or suggesting a meaningful code improvement. It's just asking for slightly more verbose comments about something that's already evident in the code. The prefix pattern could be important for maintainers to understand. Having it documented explicitly could save time for future developers. While documentation can be helpful, in this case the code is self-documenting - the prefix usage is clear and explicit in the code. The suggested comment would just be repeating what's already obvious from reading the code. The comment should be deleted as it suggests adding redundant documentation for something that is already clear from the code itself.
2. packages/opentelemetry-instrumentation-langchain/tests/test_batch_metadata.py:29
  • Draft comment:
    The tests effectively check that batch and abatch calls propagate metadata as span attributes. Note that assertions allow for either a direct key or a dotted key (with the prefix) – consider standardizing the attribute naming format to simplify these checks.
  • Reason this comment was not posted:
    Decided after close inspection that this draft comment was likely wrong and/or not actionable: usefulness confidence = 20% vs. threshold = 50% The comment is making a suggestion about code quality and test structure. However, the dual format checks may be intentionally designed to handle both formats, rather than being an oversight. Without understanding the requirements of the telemetry system and whether both formats need to be supported, suggesting standardization could be premature or incorrect. I might be wrong about the dual format being intentional - perhaps it really is unnecessary complexity that should be standardized. The suggestion could lead to simpler, more maintainable tests. Even if standardization might be beneficial, we don't have enough context about the telemetry requirements to know if both formats need to be supported. Making assumptions about simplifying the format could break important functionality. While the comment raises an interesting point about test structure, we lack the context to know if the suggestion is valid. The dual format may be a requirement rather than an opportunity for improvement.

Workflow ID: wflow_DtDoxrRMEDJRbre1

You can customize Ellipsis by changing your verbosity settings, reacting with 👍 or 👎, replying to comments, or adding code review rules.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (2)
packages/opentelemetry-instrumentation-langchain/tests/test_batch_metadata.py (2)

6-44: Comprehensive test coverage with minor cleanup needed.

The test logic effectively validates sync batch metadata propagation with proper span filtering and attribute validation. The fallback checking for both direct and namespaced attributes is well-designed.

Apply this diff to remove the unused variable flagged by static analysis:

-    # Call batch with metadata
-    responses = llm.batch(messages_list, config={"metadata": test_metadata})
+    # Call batch with metadata
+    llm.batch(messages_list, config={"metadata": test_metadata})

46-84: Well-structured async test with minor cleanup needed.

The async test properly validates abatch metadata propagation with appropriate async patterns and comprehensive attribute checking. Good coverage of the async scenario.

Apply this diff to remove the unused variable flagged by static analysis:

-    # Call abatch with metadata
-    responses = await llm.abatch(messages_list, config={"metadata": test_metadata})
+    # Call abatch with metadata
+    await llm.abatch(messages_list, config={"metadata": test_metadata})
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2f718ec and f0475f2.

📒 Files selected for processing (4)
  • packages/opentelemetry-instrumentation-langchain/opentelemetry/instrumentation/langchain/callback_handler.py (1 hunks)
  • packages/opentelemetry-instrumentation-langchain/tests/cassettes/test_batch_metadata/test_async_batch_metadata_in_span_attributes.yaml (1 hunks)
  • packages/opentelemetry-instrumentation-langchain/tests/cassettes/test_batch_metadata/test_batch_metadata_in_span_attributes.yaml (1 hunks)
  • packages/opentelemetry-instrumentation-langchain/tests/test_batch_metadata.py (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
packages/opentelemetry-instrumentation-langchain/tests/test_batch_metadata.py (3)
packages/opentelemetry-semantic-conventions-ai/opentelemetry/semconv_ai/__init__.py (1)
  • SpanAttributes (64-257)
packages/opentelemetry-instrumentation-langchain/tests/metrics/test_langchain_metrics.py (1)
  • llm (18-19)
packages/traceloop-sdk/traceloop/sdk/utils/in_memory_span_exporter.py (1)
  • get_finished_spans (40-43)
🪛 Ruff (0.12.2)
packages/opentelemetry-instrumentation-langchain/tests/test_batch_metadata.py

19-19: Local variable responses is assigned to but never used

Remove assignment to unused variable responses

(F841)


60-60: Local variable responses is assigned to but never used

Remove assignment to unused variable responses

(F841)

🪛 Flake8 (7.2.0)
packages/opentelemetry-instrumentation-langchain/tests/test_batch_metadata.py

[error] 19-19: local variable 'responses' is assigned to but never used

(F841)


[error] 60-60: local variable 'responses' is assigned to but never used

(F841)

🔇 Additional comments (3)
packages/opentelemetry-instrumentation-langchain/opentelemetry/instrumentation/langchain/callback_handler.py (1)

237-241: LGTM! Clean implementation of metadata as span attributes.

This change effectively addresses the PR objective by setting sanitized metadata as span attributes using the proper namespace prefix. The implementation correctly leverages the existing sanitized metadata and follows established patterns in the codebase.

packages/opentelemetry-instrumentation-langchain/tests/cassettes/test_batch_metadata/test_async_batch_metadata_in_span_attributes.yaml (1)

1-233: LGTM! Well-structured VCR cassette for async batch testing.

This cassette properly records the HTTP interactions for the async batch metadata test, enabling deterministic test replay. The recorded requests match the expected test messages and include proper tracing headers.

packages/opentelemetry-instrumentation-langchain/tests/cassettes/test_batch_metadata/test_batch_metadata_in_span_attributes.yaml (1)

1-222: LGTM! Appropriate VCR cassette for synchronous batch testing.

This cassette correctly records the sync batch interactions with proper headers indicating synchronous operation (note the x-stainless-async: false header vs async:asyncio in the async version). Enables deterministic testing for the sync batch metadata scenario.

- Fixed line length violations by breaking long lines
- Removed unused variables
- Fixed whitespace issues
- Added proper newline at end of file
Copy link
Contributor

@ellipsis-dev ellipsis-dev bot left a comment

Choose a reason for hiding this comment

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

Important

Looks good to me! 👍

Reviewed b5f242a in 38 seconds. Click for details.
  • Reviewed 130 lines of code in 1 files
  • Skipped 0 files when reviewing.
  • Skipped posting 3 draft comments. View those below.
  • Modify your settings and rules to customize what types of comments Ellipsis leaves. And don't forget to react with 👍 or 👎 to teach Ellipsis.
1. packages/opentelemetry-instrumentation-langchain/tests/test_batch_metadata.py:23
  • Draft comment:
    Good cleanup: Removed the assignment to 'responses' from the batch() call since the return value wasn’t used.
  • Reason this comment was not posted:
    Confidence changes required: 0% <= threshold 50% None
2. packages/opentelemetry-instrumentation-langchain/tests/test_batch_metadata.py:72
  • Draft comment:
    Good cleanup: Removed the unused assignment from the await abatch() call, which simplifies the async test.
  • Reason this comment was not posted:
    Confidence changes required: 0% <= threshold 50% None
3. packages/opentelemetry-instrumentation-langchain/tests/test_batch_metadata.py:101
  • Draft comment:
    Minor style note: Add a newline at the end of the file to comply with style guidelines.
  • Reason this comment was not posted:
    Confidence changes required: 0% <= threshold 50% None

Workflow ID: wflow_pwYfnK3lPzhaulXr

You can customize Ellipsis by changing your verbosity settings, reacting with 👍 or 👎, replying to comments, or adding code review rules.

@nirga nirga merged commit 4410eef into main Aug 3, 2025
10 checks passed
@nirga nirga deleted the langchain-metadata-fix branch August 3, 2025 08:55
@zmievsa-semasoftware
Copy link

Please note that this now duplicates some of the properties such as:

  • gen_ai.request.temperature
  • traceloop.association.properties.ls_temperature

Not an issue with most OTEL providers though.

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.

🚀 Feature: use metadata from invoke calls in Langchain to populate span attributes

4 participants