Skip to content

fix(langchain): keep objects out of association properties - #4467

Open
IdoGol24 wants to merge 2 commits into
traceloop:mainfrom
IdoGol24:fix/langchain-metadata-content-gate
Open

fix(langchain): keep objects out of association properties#4467
IdoGol24 wants to merge 2 commits into
traceloop:mainfrom
IdoGol24:fix/langchain-metadata-content-gate

Conversation

@IdoGol24

@IdoGol24 IdoGol24 commented Sep 9, 2026

Copy link
Copy Markdown

Metadata values reached span attributes through str(): any non-primitive was stringified, so an object's repr became the attribute value. A model, client or config object renders its constructor state, which routinely includes an API key, and association properties are copied onto every descendant span, so one such value spread across the whole trace. This path is also not gated by TRACELOOP_TRACE_CONTENT, so turning content capture off did not suppress it.

Forward plain data only. Primitives are unchanged, lists keep their primitive elements, and a mapping is kept as JSON when every value in it is serializable (json.dumps with no default, so a mapping holding an object raises and the key is dropped). Anything else sanitizes to None and the key is dropped rather than recorded as a stringified object.

Documented usage is unaffected: string and numeric labels such as user_id and session_id are primitives and still populate association properties.

  • 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.

Summary by CodeRabbit

  • Bug Fixes

    • Improved metadata handling for LangChain telemetry.
    • Prevented arbitrary objects and unserializable values from being recorded in span attributes or association properties.
    • Preserved supported primitive values and valid structured metadata while reducing the risk of sensitive object details being exported.
    • Ensured unsupported metadata is omitted rather than converted into potentially misleading text.
  • Tests

    • Added coverage for metadata sanitization, including primitive, nested, invalid, and end-to-end cases.

Metadata values reached span attributes through str(): any non-primitive was
stringified, so an object's repr became the attribute value. A model, client
or config object renders its constructor state, which routinely includes an
API key, and association properties are copied onto every descendant span, so
one such value spread across the whole trace. This path is also not gated by
TRACELOOP_TRACE_CONTENT, so turning content capture off did not suppress it.

Forward plain data only. Primitives are unchanged, lists keep their primitive
elements, and a mapping is kept as JSON when every value in it is serializable
(json.dumps with no default, so a mapping holding an object raises and the key
is dropped). Anything else sanitizes to None and the key is dropped rather
than recorded as a stringified object.

Documented usage is unaffected: string and numeric labels such as user_id and
session_id are primitives and still populate association properties.
@coderabbitai

coderabbitai Bot commented Sep 9, 2026

Copy link
Copy Markdown

Review Change StackReview Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Advanced

Run ID: 2af3607b-1ac5-4910-afc5-9c31bbe9b441

📥 Commits

Reviewing files that changed from the base of the PR and between c47cec6 and c4801a6.

📒 Files selected for processing (2)
  • packages/opentelemetry-instrumentation-langchain/opentelemetry/instrumentation/langchain/callback_handler.py
  • packages/opentelemetry-instrumentation-langchain/tests/test_metadata_sanitization.py
🚧 Files skipped from review as they are similar to previous changes (2)
  • packages/opentelemetry-instrumentation-langchain/tests/test_metadata_sanitization.py
  • packages/opentelemetry-instrumentation-langchain/opentelemetry/instrumentation/langchain/callback_handler.py

Included review availability: Your plan provides up to 8 included reviews per hour; 4 remain after this review.


📝 Walkthrough

Walkthrough

LangChain metadata sanitization now preserves plain values, serializes plain mappings, drops arbitrary objects, and omits dropped values from span attributes and association properties. Tests cover unit cases and end-to-end span export.

Changes

LangChain metadata sanitization

Layer / File(s) Summary
Plain metadata sanitization
packages/opentelemetry-instrumentation-langchain/opentelemetry/instrumentation/langchain/callback_handler.py, packages/opentelemetry-instrumentation-langchain/tests/test_metadata_sanitization.py
Primitive values remain unchanged. Plain list and tuple elements remain. Plain dictionaries become JSON strings. Arbitrary objects and unserializable mappings are dropped.
Sanitized span metadata export
packages/opentelemetry-instrumentation-langchain/opentelemetry/instrumentation/langchain/callback_handler.py, packages/opentelemetry-instrumentation-langchain/tests/test_metadata_sanitization.py
The span creation path omits metadata entries that sanitize to None. End-to-end tests confirm that object representations do not reach span properties while primitive labels remain recorded.

Priority: ➖ Normal

Estimated code review effort: 3 (Moderate) | ~20 minutes

Severity of issue fixed: Medium

Merge Risk: ⚪ Minimal · up to c4801

This change sanitizes LangChain metadata before span export, retaining supported primitive data while omitting unsupported object values. No concrete merge-blocking risk is currently identified.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: preventing objects from reaching LangChain association properties.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 14 functions across 2 files.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

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.

1 participant