Commit d7351ef
fix(llmobs): emit session_id as top-level field + propagate via context (#11371)
fix(llmobs): emit session_id as top-level field in LLMObs span event
dd-trace-java was placing session_id only inside the `tags[]` array of
each LLMObs span event on the wire, never as a top-level span field.
The LLM Trace Explorer's Sessions filter keys off the top-level
`session_id` field per the public HTTP intake API schema
(https://docs.datadoghq.com/llm_observability/instrumentation/api?tab=model#span),
so Java spans were invisible to that filter. dd-trace-py and
dd-trace-js have conformed to this schema since the LLMObs v2 API
launched (2024-06-21, MLOB-955).
In LLMObsSpanMapper.map(), read the _ml_obs_tag.session_id tag from
each span before opening the msgpack map; if present, extend the map
size from 11 to 12 entries and emit the value as a top-level field.
Mirrors the existing parent_id lift pattern, with one deliberate
difference: the tag is not removed so the `session_id:<value>` entry
remains in the tags[] array, matching dd-trace-py and dd-trace-js
behavior.
Originating issue: MLOS-646.
fix(llmobs): propagate session_id from parent context to child LLMObs spans
dd-trace-java's DDLLMObsSpan constructor only honored an explicitly
passed sessionId argument. When a caller used the SDK's documented
"set session_id on the root span only" pattern and started a child
LLMObs span with sessionId=null, the child carried no session_id.
dd-trace-py (ddtrace/llmobs/_llmobs.py:1911) and dd-trace-js
(packages/dd-trace/src/llmobs/tagger.js:105-106) both auto-propagate
session_id from parent context to descendant LLMObs spans.
Add a SESSION_ID ContextKey to LLMObsContext alongside the existing
span-context key, plus an attach(ctx, sessionId) overload and a
currentSessionId() accessor. In DDLLMObsSpan's constructor, fall back
to LLMObsContext.currentSessionId() when no explicit sessionId is
passed. The constructor now also propagates the effective sessionId
through the new context key so subsequent descendant spans can inherit
it.
Originating issue: MLOS-646.
test(llmobs): consolidate session_id mapper tests, add transitive inheritance test
fix(llmobs/openai-java): inherit session_id on auto-instrumented openai.request span
OpenAiDecorator.afterStart() already consulted LLMObsContext.current()
to set the LLMObs parent_id tag but never read session_id from the
context. Auto-instrumented openai.request spans therefore carried no
_ml_obs_tag.session_id even when a manual LLMObs workflow parent had
one. dd-trace-py and dd-trace-js both auto-propagate session_id to
auto-instrumented LLM spans via parent context.
Add a SESSION_ID constant to CommonTags. In OpenAiDecorator.afterStart(),
after the existing parent_id block, read LLMObsContext.currentSessionId()
and stamp it on the span as CommonTags.SESSION_ID when present. With
this change, auto-instrumented openai.request spans now appear under
their session in the LLM Trace Explorer's Sessions view, matching
Python and Node behavior.
Depends on the LLMObsContext.currentSessionId() API added in the
preceding fix(llmobs): propagate session_id from parent context commit.
Originating issue: MLOS-646.
test(llmobs/openai-java): migrate session_id propagation test to JUnit 5 + Java
refactor(llmobs): drop redundant hasSessionId ternary on LLMObsContext.attach
Merge remote-tracking branch 'origin/master' into jessica.gamio/llmobs-session-id-mlos-646
style(llmobs/openai-java): apply spotless formatting to SessionIdPropagationForkedTest
fix(llmobs): address Codex review — safe session_id cast, gate inheritance on trace match
- LLMObsSpanMapper: read session_id tag as Object and instanceof-check before casting,
so a non-string value can't ClassCastException and drop the entire LLMObs payload.
- DDLLMObsSpan: move session_id inheritance from the constructor preamble to inside
the existing trace-id consistency check that already gates parent_id. Prevents a
stale LLMObsContext from leaking session attribution across traces.
- DDLLMObsSpanTest: existing 2-level + 3-level inheritance tests now activate the
parent's AgentScope so they truly share a trace. New test asserts session_id is
NOT inherited when the LLMObsContext belongs to a different trace.
test(llmobs): rename cross-trace test to mention async-boundary leak as the canonical scenario
Merge branch 'master' into jessica.gamio/llmobs-session-id-mlos-646
Co-authored-by: yury.gribkov <yury.gribkov@datadoghq.com>1 parent cfb9996 commit d7351ef
8 files changed
Lines changed: 356 additions & 9 deletions
File tree
- dd-java-agent
- agent-llmobs/src
- main/java/datadog/trace/llmobs/domain
- test/groovy/datadog/trace/llmobs/domain
- instrumentation/openai-java/openai-java-3.0/src
- main/java/datadog/trace/instrumentation/openai_java
- test/java/datadog/trace/instrumentation/openai_java
- dd-trace-core/src
- main/java/datadog/trace/llmobs/writer/ddintake
- test/groovy/datadog/trace/llmobs/writer/ddintake
- internal-api/src/main/java/datadog/trace/api/llmobs
Lines changed: 19 additions & 6 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
89 | 89 | | |
90 | 90 | | |
91 | 91 | | |
92 | | - | |
93 | | - | |
94 | | - | |
95 | | - | |
96 | | - | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
97 | 95 | | |
98 | 96 | | |
99 | 97 | | |
| |||
106 | 104 | | |
107 | 105 | | |
108 | 106 | | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
109 | 116 | | |
110 | 117 | | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
111 | 123 | | |
112 | | - | |
| 124 | + | |
| 125 | + | |
113 | 126 | | |
114 | 127 | | |
115 | 128 | | |
| |||
Lines changed: 90 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
411 | 411 | | |
412 | 412 | | |
413 | 413 | | |
| 414 | + | |
| 415 | + | |
| 416 | + | |
| 417 | + | |
| 418 | + | |
| 419 | + | |
| 420 | + | |
| 421 | + | |
| 422 | + | |
| 423 | + | |
| 424 | + | |
| 425 | + | |
| 426 | + | |
| 427 | + | |
| 428 | + | |
| 429 | + | |
| 430 | + | |
| 431 | + | |
| 432 | + | |
| 433 | + | |
| 434 | + | |
| 435 | + | |
| 436 | + | |
| 437 | + | |
| 438 | + | |
| 439 | + | |
| 440 | + | |
| 441 | + | |
| 442 | + | |
| 443 | + | |
| 444 | + | |
| 445 | + | |
| 446 | + | |
| 447 | + | |
| 448 | + | |
| 449 | + | |
| 450 | + | |
| 451 | + | |
| 452 | + | |
| 453 | + | |
| 454 | + | |
| 455 | + | |
| 456 | + | |
| 457 | + | |
| 458 | + | |
| 459 | + | |
| 460 | + | |
| 461 | + | |
| 462 | + | |
| 463 | + | |
| 464 | + | |
| 465 | + | |
| 466 | + | |
| 467 | + | |
| 468 | + | |
| 469 | + | |
| 470 | + | |
| 471 | + | |
| 472 | + | |
| 473 | + | |
| 474 | + | |
| 475 | + | |
| 476 | + | |
| 477 | + | |
| 478 | + | |
| 479 | + | |
| 480 | + | |
| 481 | + | |
| 482 | + | |
| 483 | + | |
| 484 | + | |
| 485 | + | |
| 486 | + | |
| 487 | + | |
| 488 | + | |
| 489 | + | |
| 490 | + | |
| 491 | + | |
| 492 | + | |
| 493 | + | |
| 494 | + | |
| 495 | + | |
| 496 | + | |
| 497 | + | |
| 498 | + | |
| 499 | + | |
| 500 | + | |
| 501 | + | |
| 502 | + | |
| 503 | + | |
414 | 504 | | |
415 | 505 | | |
416 | 506 | | |
| |||
Lines changed: 1 addition & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
30 | 30 | | |
31 | 31 | | |
32 | 32 | | |
| 33 | + | |
33 | 34 | | |
34 | 35 | | |
35 | 36 | | |
| |||
Lines changed: 10 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
115 | 115 | | |
116 | 116 | | |
117 | 117 | | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
118 | 128 | | |
119 | 129 | | |
120 | 130 | | |
| |||
Lines changed: 129 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
Lines changed: 22 additions & 2 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
55 | 55 | | |
56 | 56 | | |
57 | 57 | | |
| 58 | + | |
58 | 59 | | |
59 | 60 | | |
60 | 61 | | |
| |||
88 | 89 | | |
89 | 90 | | |
90 | 91 | | |
| 92 | + | |
| 93 | + | |
91 | 94 | | |
92 | 95 | | |
93 | 96 | | |
| |||
126 | 129 | | |
127 | 130 | | |
128 | 131 | | |
129 | | - | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
130 | 143 | | |
131 | 144 | | |
132 | 145 | | |
| |||
166 | 179 | | |
167 | 180 | | |
168 | 181 | | |
169 | | - | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
170 | 190 | | |
171 | 191 | | |
172 | 192 | | |
| |||
0 commit comments