v5.118.0 proposal#9519
Conversation
* test: stop peer service checks racing operation spans The shared helper started the operation before registering its trace expectation and only inspected the first span of each payload. MongoDB connection traffic could therefore consume the payload containing the expected operation span, leaving the test to time out. * test: bind peer service checks to their operation spans Delayed setup traces can carry the same peer-service tags as the operation under test, allowing the shared matcher to pass without observing that operation. Run each generator under a unique parent and match its child span instead. Generator throws and invalid return values can bypass assertion cleanup. Keep the whole operation inside the cleanup boundary so the original failure is not replaced by a leaked-expectation teardown error. * test: match peer service spans by trace Peer-service spans can be nested below integration spans, so requiring a direct parent excluded valid operations. Match the generated trace to keep setup traffic isolated without constraining span depth. * test: stop correlation spans delaying trace export Keeping the correlation parent open until the operation settled delayed trace export. Integrations that publish duplicate finish notifications could then recompute `_dd.peer.service.source` before the trace was sent. * fix(tracing): make peer service finalization idempotent Repeated finish notifications can reach an outbound span before an ancestor lets the trace flush. The second pass treats the computed peer service as preconfigured and rewrites its source to `peer.service`; an existing source now marks finalization. The peer-service assertion keeps its correlation parent open through completion and matches the integration component, so delayed setup traces and spans from another integration cannot satisfy it. * test(mongodb): target bulkWrite peer service parent
…with 5 updates (#9478) * chore(deps): bump the gh-actions-packages group across 6 directories with 5 updates Bumps the gh-actions-packages group with 4 updates in the / directory: [actions/checkout](https://github.com/actions/checkout), [github/codeql-action/init](https://github.com/github/codeql-action), [github/codeql-action/analyze](https://github.com/github/codeql-action) and [slackapi/slack-github-action](https://github.com/slackapi/slack-github-action). Bumps the gh-actions-packages group with 1 update in the /.github/actions/datadog-ci directory: [actions/setup-node](https://github.com/actions/setup-node). Bumps the gh-actions-packages group with 1 update in the /.github/actions/node/setup directory: [actions/setup-node](https://github.com/actions/setup-node). Bumps the gh-actions-packages group with 1 update in the /.github/actions/testagent/logs directory: [actions/checkout](https://github.com/actions/checkout). Bumps the gh-actions-packages group with 1 update in the /.github/actions/testagent/start directory: [actions/checkout](https://github.com/actions/checkout). Bumps the gh-actions-packages group with 4 updates in the /.github/workflows directory: [actions/checkout](https://github.com/actions/checkout), [github/codeql-action/init](https://github.com/github/codeql-action), [github/codeql-action/analyze](https://github.com/github/codeql-action) and [slackapi/slack-github-action](https://github.com/slackapi/slack-github-action). Updates `actions/checkout` from 7.0.0 to 7.0.1 - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](actions/checkout@9c091bb...3d3c42e) Updates `github/codeql-action/init` from 4.37.0 to 4.37.1 - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](github/codeql-action@99df26d...7188fc3) Updates `github/codeql-action/analyze` from 4.37.0 to 4.37.1 - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](github/codeql-action@99df26d...7188fc3) Updates `slackapi/slack-github-action` from 3.0.4 to 4.0.0 - [Release notes](https://github.com/slackapi/slack-github-action/releases) - [Changelog](https://github.com/slackapi/slack-github-action/blob/main/CHANGELOG.md) - [Commits](slackapi/slack-github-action@fc46ded...dcb1066) Updates `actions/setup-node` from 6.4.0 to 7.0.0 - [Release notes](https://github.com/actions/setup-node/releases) - [Commits](actions/setup-node@48b55a0...8207627) Updates `actions/setup-node` from 6.4.0 to 7.0.0 - [Release notes](https://github.com/actions/setup-node/releases) - [Commits](actions/setup-node@48b55a0...8207627) Updates `actions/checkout` from 7.0.0 to 7.0.1 - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](actions/checkout@9c091bb...3d3c42e) Updates `actions/checkout` from 7.0.0 to 7.0.1 - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](actions/checkout@9c091bb...3d3c42e) Updates `actions/checkout` from 7.0.0 to 7.0.1 - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](actions/checkout@9c091bb...3d3c42e) Updates `github/codeql-action/init` from 4.37.0 to 4.37.1 - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](github/codeql-action@99df26d...7188fc3) Updates `github/codeql-action/analyze` from 4.37.0 to 4.37.1 - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](github/codeql-action@99df26d...7188fc3) Updates `slackapi/slack-github-action` from 3.0.4 to 4.0.0 - [Release notes](https://github.com/slackapi/slack-github-action/releases) - [Changelog](https://github.com/slackapi/slack-github-action/blob/main/CHANGELOG.md) - [Commits](slackapi/slack-github-action@fc46ded...dcb1066) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: 7.0.1 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: gh-actions-packages - dependency-name: github/codeql-action/init dependency-version: 4.37.1 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: gh-actions-packages - dependency-name: github/codeql-action/analyze dependency-version: 4.37.1 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: gh-actions-packages - dependency-name: slackapi/slack-github-action dependency-version: 4.0.0 dependency-type: direct:production update-type: version-update:semver-major dependency-group: gh-actions-packages - dependency-name: actions/setup-node dependency-version: 7.0.0 dependency-type: direct:production update-type: version-update:semver-major dependency-group: gh-actions-packages - dependency-name: actions/setup-node dependency-version: 7.0.0 dependency-type: direct:production update-type: version-update:semver-major dependency-group: gh-actions-packages - dependency-name: actions/checkout dependency-version: 7.0.1 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: gh-actions-packages - dependency-name: actions/checkout dependency-version: 7.0.1 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: gh-actions-packages - dependency-name: actions/checkout dependency-version: 7.0.1 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: gh-actions-packages - dependency-name: github/codeql-action/init dependency-version: 4.37.1 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: gh-actions-packages - dependency-name: github/codeql-action/analyze dependency-version: 4.37.1 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: gh-actions-packages - dependency-name: slackapi/slack-github-action dependency-version: 4.0.0 dependency-type: direct:production update-type: version-update:semver-major dependency-group: gh-actions-packages ... Signed-off-by: dependabot[bot] <support@github.com> * attempt to fix jobs --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Thomas Hunter II <tlhunter@datadog.com>
* feat(llmobs): add OpenAI Agents trace-processor integration * ci(llmobs): test OpenAI Agents integration
* separate llmobs trace ids * update exportSpan * tests * add tagger test * additional fixups * update tests from rebase
* fix(openfeature): support custom agentless endpoints * fix(openfeature): never send API keys to custom endpoints * fix(openfeature): clarify default endpoint error
Overall package sizeSelf size: 7.52 MB Dependency sizes| name | version | self size | total size | |------|---------|-----------|------------| | import-in-the-middle | 3.3.2 | 124.41 kB | 440.65 kB | | opentracing | 0.14.7 | 194.81 kB | 194.81 kB | | dc-polyfill | 0.1.11 | 25.74 kB | 25.74 kB |🤖 This report was automatically generated by heaviest-objects-in-the-universe |
🎉 All green!🧪 All tests passed 🎯 Code Coverage (details) 🔗 Commit SHA: 376fc9b | Docs | Datadog PR Page | Give us feedback! |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## v5.x #9519 +/- ##
===========================================
+ Coverage 83.19% 98.48% +15.29%
===========================================
Files 476 947 +471
Lines 20153 128035 +107882
Branches 0 10906 +10906
===========================================
+ Hits 16766 126096 +109330
+ Misses 3387 1939 -1448 Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
More details
The changed LLMObs propagation, OpenFeature endpoint, peer-service finalization, and OpenAI Agents helper paths behaved correctly across targeted normal, boundary, malformed, and propagation scenarios. The full OpenAI Agents versioned integration suite could not run because its local version fixtures are not materialized, so that path remains the main validation gap.
📊 Validated against 10 scenarios · Open Bits AI session
🤖 Datadog Autotest · Commit 9b61525 · What is Autotest? · @DataDog review to ask questions · Any feedback? Reach out in #autotest
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 9b61525319
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| if (!traceId) return | ||
|
|
||
| const name = oaiTrace.name || 'Agent workflow' | ||
| const ddSpan = this.#tracer.startSpan(name, { |
There was a problem hiding this comment.
Preserve active parent for agent workflows
When an agent run is started inside an existing Datadog span, such as an HTTP request handler, this direct startSpan() call creates the workflow as a new root because dd-trace only uses a parent when childOf/references are provided. The child agent and openai.request spans then form a separate trace, so the agent work no longer appears under the request that triggered it; pass the currently active span as the workflow parent.
Useful? React with 👍 / 👎.
| handoff: 'tool', | ||
| guardrail: 'task', | ||
| custom: 'task', | ||
| response: 'llm', |
There was a problem hiding this comment.
Trace generation spans from chat-completions agents
When users configure the Agents SDK to use Chat Completions (setOpenAIAPI('chat_completions') or OpenAIChatCompletionsModel), the SDK reports the LLM call as a generation span rather than a response span. Since this mapping only treats response as an LLM span, onSpanStart() drops those model calls, so chat-completions agents lose their LLM/APM span and LLMObs input/output tagging even though the integration advertises @openai/agents support.
Useful? React with 👍 / 👎.
| let content = '' | ||
| if (Array.isArray(item.content)) { | ||
| const textParts = item.content | ||
| .filter(c => c.type === 'input_text' || c.type === 'text') |
There was a problem hiding this comment.
Preserve non-text agent input parts
When an Agents run sends Responses API message content with images or files, this filter keeps only text parts and drops every non-text part before tagging the LLM span and workflow input. A multimodal prompt can therefore be recorded as incomplete or even as an empty user message, so LLMObs no longer reflects the actual model input; include placeholders or structured handling for image/file parts instead of filtering them out.
Useful? React with 👍 / 👎.
|
|
||
| constructor ({ tracer, config } = {}) { | ||
| this.#tracer = tracer | ||
| this.#tagger = config?.llmobs?.DD_LLMOBS_ENABLED ? new LLMObsTagger(config, true) : undefined |
There was a problem hiding this comment.
Create LLMObs tagger for late enablement
When @openai/agents is loaded before tracer.llmobs.enable(), this one-time check leaves #tagger undefined because DD_LLMOBS_ENABLED is still false at plugin construction. A later programmatic enable flips the shared config and starts the writers, but every openai-agents LLMObs path is guarded by this.#tagger, so this integration keeps emitting only APM spans; create the tagger unconditionally or lazily when LLMObs becomes enabled.
Useful? React with 👍 / 👎.
| const parentSpan = this.#resolveParent(oaiSpan) | ||
| const spanName = deriveSpanName(oaiSpan) | ||
|
|
||
| const ddSpan = this.#tracer.startSpan(spanName, { |
There was a problem hiding this comment.
Activate tool spans while user tools run
When a function tool does instrumented work such as HTTP or database calls, this startSpan() only creates the tool span with childOf; it never makes that span active for the duration of the agents-core span. Since the plugin only binds scope around model response calls, downstream spans emitted from user tool execution inherit the prior active span instead of the function tool span, breaking the trace hierarchy for tool internals.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 9b61525319
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| if (!traceId) return | ||
|
|
||
| const name = oaiTrace.name || 'Agent workflow' | ||
| const ddSpan = this.#tracer.startSpan(name, { |
There was a problem hiding this comment.
Preserve active parent for agent workflows
When an agent run is started inside an existing Datadog span, such as an HTTP request handler, this direct startSpan() call creates the workflow as a new root because dd-trace only uses a parent when childOf/references are provided. The child agent and openai.request spans then form a separate trace, so the agent work no longer appears under the request that triggered it; pass the currently active span as the workflow parent.
Useful? React with 👍 / 👎.
| handoff: 'tool', | ||
| guardrail: 'task', | ||
| custom: 'task', | ||
| response: 'llm', |
There was a problem hiding this comment.
Trace generation spans from chat-completions agents
When users configure the Agents SDK to use Chat Completions (setOpenAIAPI('chat_completions') or OpenAIChatCompletionsModel), the SDK reports the LLM call as a generation span rather than a response span. Since this mapping only treats response as an LLM span, onSpanStart() drops those model calls, so chat-completions agents lose their LLM/APM span and LLMObs input/output tagging even though the integration advertises @openai/agents support.
Useful? React with 👍 / 👎.
| let content = '' | ||
| if (Array.isArray(item.content)) { | ||
| const textParts = item.content | ||
| .filter(c => c.type === 'input_text' || c.type === 'text') |
There was a problem hiding this comment.
Preserve non-text agent input parts
When an Agents run sends Responses API message content with images or files, this filter keeps only text parts and drops every non-text part before tagging the LLM span and workflow input. A multimodal prompt can therefore be recorded as incomplete or even as an empty user message, so LLMObs no longer reflects the actual model input; include placeholders or structured handling for image/file parts instead of filtering them out.
Useful? React with 👍 / 👎.
|
|
||
| constructor ({ tracer, config } = {}) { | ||
| this.#tracer = tracer | ||
| this.#tagger = config?.llmobs?.DD_LLMOBS_ENABLED ? new LLMObsTagger(config, true) : undefined |
There was a problem hiding this comment.
Create LLMObs tagger for late enablement
When @openai/agents is loaded before tracer.llmobs.enable(), this one-time check leaves #tagger undefined because DD_LLMOBS_ENABLED is still false at plugin construction. A later programmatic enable flips the shared config and starts the writers, but every openai-agents LLMObs path is guarded by this.#tagger, so this integration keeps emitting only APM spans; create the tagger unconditionally or lazily when LLMObs becomes enabled.
Useful? React with 👍 / 👎.
| const parentSpan = this.#resolveParent(oaiSpan) | ||
| const spanName = deriveSpanName(oaiSpan) | ||
|
|
||
| const ddSpan = this.#tracer.startSpan(spanName, { |
There was a problem hiding this comment.
Activate tool spans while user tools run
When a function tool does instrumented work such as HTTP or database calls, this startSpan() only creates the tool span with childOf; it never makes that span active for the duration of the agents-core span. Since the plugin only binds scope around model response calls, downstream spans emitted from user tool execution inherit the prior active span instead of the function tool span, breaking the trace hierarchy for tool internals.
Useful? React with 👍 / 👎.
9b61525 to
376fc9b
Compare
BenchmarksBenchmark execution time: 2026-07-24 16:46:37 Comparing candidate commit 376fc9b in PR branch Found 3 performance improvements and 0 performance regressions! Performance is the same for 2313 metrics, 42 unstable metrics.
|
Features
Fixes