Repository navigation
fix(tracing): preserve message parts and embedded tool calls - #44078
Nikhi00718 wants to merge 4 commits into
Conversation
|
| role: str | None = None | ||
| type: str | None = None | ||
| content: JsonValue = None | ||
| parts: JsonValue = None |
There was a problem hiding this comment.
Oversized parts lose their content
When a GenAI message with parts exceeds the trace attribute limit, the truncation path shortens content rather than parts. It can store a role and a "null…" content marker instead of the message. By the time this viewer reads the trace, the conversation and embedded tool calls have been lost.
| text: str | None = None | ||
| content: JsonValue = None | ||
| result: JsonValue = None | ||
| name: str = "" |
There was a problem hiding this comment.
Optional name rejects valid blocks
A text block with name: null now fails validation because name must be a string. Validation rejects the entire block list, so a valid tool call beside that text block is no longer extracted and the viewer shows raw JSON instead. This limits the new extraction behavior for mixed block lists.
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
8478197 to
93af86c
Compare
|
Hi maintainers, could you review this trace-normalization fix when you have a chance? It preserves GenAI message parts, embedded tool calls, JSON tool results, and oversized conversation content, with regression coverage. Current head |
|
Closing: after #44363, the Python tracing formatter this PR changes no longer exists. Message normalization now lives in the Rust tracing stack, where parts and embedded tool calls are handled in |
TLDR
Problem this solves:
How it solves it:
User Flow
Before: a developer inspecting an agent run cannot follow its conversation or embedded tool calls
POST http://localhost:4000/v1/traceshttp://localhost:4000/ui/?page=logsand select its model spanAfter: the same run exposes its conversation, tool names, arguments, and results
POST http://localhost:4000/v1/traceshttp://localhost:4000/ui/?page=logsand select its model spanValidation
Base:
5ccb1a143b759a83752ccb350a7031c596b9dec4. Source tested atad7a142364; current headf06deca364adds only the two CI timeout adjustments described belowHosted CI on current head
f06deca364: 101 checks pass, one is skipped, none fail or remain pending. All ten GitHub-required checks pass, including the full canonical type-check gate. The production Rust wheel, compiled-extension tests, full workspace nextest step, Rust documentation tests, token-counter feature cases, and secret-manager feature cases passThe additional Python 3.14 dependency-resolution job hit its configured 15-minute timeout while installing lowest runtime dependencies: its locked runtime installation consumed about 13 minutes. The Rust test job hit its 20-minute timeout during secret-manager feature combinations, after the workspace, documentation, and token-counter tests passed. Rerun attempts did not schedule either job; the resolver rerun explicitly requires repository admin rights. These cancelled jobs are not counted as passes
f06deca364increases the resolver job allowance from 15 to 25 minutes and the Rust test allowance from 20 to 35 minutes to accommodate cold native builds and the complete feature matrix. All commands, assertions, feature cases, and quality budgets are retained. Both workflow files parse successfully. Python 3.14 resolution passes in 14m53s; the full Rust test job passes in 23m44s, exceeding the former 20-minute cap. Every Python version in the resolver matrix passesTests cover GenAI conversations, embedded calls, Rust LangSmith normalization, JSON scalar results, malformed arguments, incomplete blocks, optional names, content precedence, and duplicate prevention. Oversized-message cases cover Unicode, control characters, long roles, and calls that fit the byte budget. Exported argument strings remain unchanged rather than being repaired for inference
LITELLM_LOCAL_MODEL_COST_MAP=True python -m pytest \ tests/test_litellm/tracing/test_ui_format.py \ tests/test_litellm/tracing/test_decode.py \ tests/test_litellm/tracing/test_store.py \ --confcutdir=tests/test_litellm/tracing \ -k 'not decode or oversized or shortened' \ --cov=litellm/tracing --cov-branch -qLinux Python validation disables sockets and permits Unix sockets for asyncio wakeups. These scoped runs exclude parent proxy fixtures. The native decoder is exercised separately by the Rust OTLP tests. The full canonical type-check gate has not completed locally: the Linux runtime stopped during setup. CI found two tuple-narrowing diagnostics in the preceding commit; both are removed in this commit, and focused basedpyright confirms neither remains
Pre-Submission checklist
Screenshots / Proof of Fix
Live proxy and dashboard proof has not been captured. End-to-end verification remains pending.
Type
Bug Fix
Caveats
Medium
Low
Final Attestation