Skip to content

fix(llmobs/openai-java): inherit session_id on auto-instrumented openai.request span#11372

Draft
jessicagamio wants to merge 1 commit into
jessica.gamio/llmobs-session-id-mlos-646from
jessica.gamio/llmobs-openai-java-session-id-mlos-646
Draft

fix(llmobs/openai-java): inherit session_id on auto-instrumented openai.request span#11372
jessicagamio wants to merge 1 commit into
jessica.gamio/llmobs-session-id-mlos-646from
jessica.gamio/llmobs-openai-java-session-id-mlos-646

Conversation

@jessicagamio
Copy link
Copy Markdown

@jessicagamio jessicagamio commented May 14, 2026

Summary

dd-trace-java's openai-java auto-instrumentation (OpenAiDecorator) doesn't inherit session_id from the active LLMObs parent context. Auto-instrumented openai.request spans carry no _ml_obs_tag.session_id even when a manual workflow parent has one set.

This PR brings the openai-java integration to parity with dd-trace-py (ddtrace/llmobs/_llmobs.py:_on_span_start) and dd-trace-js (packages/dd-trace/src/llmobs/tagger.js:105-106), both of which auto-propagate session_id from parent context to auto-instrumented LLM spans.

MLOB tracking: MLOB-7480

Stacked on #11371

This PR is stacked on #11371 (MLOB-7479 — emit session_id as top-level field + propagate via context). It uses LLMObsContext.currentSessionId(), an API added in that PR.

Once #11371 merges, the base branch of this PR will be re-pointed to master.

Changes

  • dd-java-agent/instrumentation/openai-java/.../CommonTags.java — add SESSION_ID = TAG_PREFIX + LLMObsTags.SESSION_ID constant, mirroring the existing PARENT_ID pattern.
  • dd-java-agent/instrumentation/openai-java/.../OpenAiDecorator.java — in afterStart(), after the existing parent_id block, read LLMObsContext.currentSessionId() and stamp it on the span as CommonTags.SESSION_ID when present.
  • dd-java-agent/instrumentation/openai-java/.../SessionIdPropagationTest.groovynew file, 2 tests: (1) auto-instrumented openai.request span inherits session_id from active LLMObs context; (2) no session_id tag when no LLMObs context is active.

Test plan

  • ./gradlew :dd-java-agent:instrumentation:openai-java:openai-java-3.0:test — 97 tests pass (2 new + 95 existing, 0 regressions)
  • ./gradlew :dd-java-agent:instrumentation:openai-java:openai-java-3.0:spotlessCheck clean
  • End-to-end verified: auto-instrumented openai.request now appears under the same Session as its workflow parent in the LLM Trace Explorer

Future considerations

The openai-java module is currently the only LLMObs auto-instrumentation in dd-trace-java. When additional ones are added (Anthropic, Vertex, Bedrock, etc.), each will need the same LLMObsContext.currentSessionId() lookup. A shared helper could consolidate this in a future refactor — out of scope for this PR.

…ai.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.
* OpenAiDecorator's session_id inheritance behavior, which only depends on
* LLMObsContext.currentSessionId() being set.
*/
class SessionIdPropagationTest extends OpenAiTest {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

It's now a requirement to use Java/JUnit instead of Groovy/Spock for all new tests the repo wide.

Copy link
Copy Markdown
Contributor

@ygree ygree left a comment

Choose a reason for hiding this comment

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

Looks good! One suggestion is to use JUnit for testing. Also, perhaps we should keep this change in the parent PR since they're closely related.

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.

2 participants