fix(azure-functions): fix span links and missing telemetry for non-HTTP triggers#9278
Conversation
Overall package sizeSelf size: 6.71 MB Dependency sizes| name | version | self size | total size | |------|---------|-----------|------------| | import-in-the-middle | 3.3.1 | 122.62 kB | 438.86 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: 3fa504f | Docs | Datadog PR Page | Give us feedback! |
There was a problem hiding this comment.
Pull request overview
Fixes two tracing gaps in the Azure Functions plugin so non-HTTP triggers reliably produce telemetry and preserve upstream context via span links.
Changes:
- Force non-HTTP trigger invocations to start a root span (
childOf: null) to avoid inheriting a stale ambient span. - Default Service Bus/Event Hubs trigger
cardinalityto'one'when unset so span links are still created. - Add/extend integration tests and emulator fixtures to cover “unset cardinality” scenarios for Service Bus and Event Hubs.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| packages/datadog-plugin-azure-functions/src/index.js | Ensures non-HTTP invocations create root spans and span links work when cardinality is omitted. |
| packages/datadog-plugin-azure-functions/test/integration-test/servicebus-test/servicebus.spec.js | Adds an integration test asserting span links are present when Service Bus cardinality is unset. |
| packages/datadog-plugin-azure-functions/test/integration-test/servicebus-test/server.mjs | Adds a new queue sender/HTTP endpoint and a Service Bus queue trigger without cardinality. |
| packages/datadog-plugin-azure-functions/test/integration-test/eventhubs-test/eventhubs.spec.js | Adds an integration test asserting span links are present when Event Hubs cardinality is unset. |
| packages/datadog-plugin-azure-functions/test/integration-test/eventhubs-test/server.mjs | Adds a new HTTP producer endpoint and Event Hubs trigger without cardinality. |
| packages/datadog-plugin-azure-functions/test/fixtures/servicebus-emulator-config.json | Adds queue.3 to the Service Bus emulator fixture for the new test. |
| packages/datadog-plugin-azure-functions/test/fixtures/eventhub-emulator-config.json | Adds eh3 (+ consumer group) to the Event Hubs emulator fixture for the new test. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #9278 +/- ##
==========================================
+ Coverage 96.52% 96.56% +0.04%
==========================================
Files 905 918 +13
Lines 119287 121522 +2235
Branches 20647 20959 +312
==========================================
+ Hits 115138 117352 +2214
- Misses 4149 4170 +21 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:
|
|
@codex review |
|
Codex Review: Didn't find any major issues. Keep it up! Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
|
I think we should break this PR into two separate fixes. Fix 2 looks great, but fix 1 is confusing to me. There are a significant amount of places that do not set |
@jcstorms1 I think Fix 1 is fine, since in the case of a serverless function invocation, if the request doesnt have any distributed parent, then the serverless span should be the root span. As opposed to other integrations, where the span is a legitimate child span if another active span exists. Will let @BridgeAR or @rochdev chime in on this. |
jcstorms1
left a comment
There was a problem hiding this comment.
After digging into this a bit more I found the following example which points to this exact fix. We probably need to go through all of our integrations and check we do this properly.
dd-trace-js/packages/dd-trace/src/plugins/tracing.js
Lines 179 to 189 in f0e4773
Looks good to me @kathiehuang thanks for handling these fixes.
|
@jcstorms1 @wconti27 Thank you for the review! I'll update the PR description with the reference to the example/comment from |
11a2a4f to
3fa504f
Compare
BenchmarksBenchmark execution time: 2026-07-13 18:06:22 Comparing candidate commit 3fa504f in PR branch Found 0 performance improvements and 0 performance regressions! Performance is the same for 2310 metrics, 48 unstable metrics.
|
What does this PR do?
Fixes two bugs in
packages/datadog-plugin-azure-functions/src/index.jsaffecting non-HTTP-triggered Azure Functions:childOf: nullon thestartSpancall inbindStart's non-HTTP branch, so each invocation gets its own root span instead of possibly inheriting a stale ambient span.cardinalityto'one'insetSpanLinkswhen the trigger doesn't explicitly set it.Motivation
Fix 1:
TracingPlugin.startSpanseems to inherit the ambient active span from async-local-storage wheneverchildOfisn't explicitly passed. WithoutchildOf: null, a non-HTTP trigger invocation in a warm Node.js process could silently become a child of whatever span was left over from unrelated earlier work — often an already-finished, already-ingested trace. A late-arriving child of a closed trace is effectively unreportable, so the invocation, its downstream calls, and its outbound sends produced zero telemetry even though they ran and completed correctly.tracing.jsnotes thatchildOf:nullshould be passed for serverless spans without a distributed parent:dd-trace-js/packages/dd-trace/src/plugins/tracing.js
Lines 179 to 189 in f0e4773
This bug was found when we noticed a service-bus-triggered Azure Function was not producing spans.
Fix 2:
cardinalityis an optional field on@azure/functionsService Bus and Event Hubs trigger options.setSpanLinksonly added a span link when it read exactly'one'or'many'fromctx.invocationContext.options.trigger.cardinality. If an app never setcardinality, the value wasundefined, matched neither branch, and the function returned having silently added no link — with no error or warning anywhere. This broke the connection back to the producing trace for any Service Bus/Event Hubs consumer that didn't explicitly configurecardinality.https://datadoghq.atlassian.net/browse/SVLS-9426
Additional Notes
?? 'one'default makes exactly the two new "unset cardinality" tests fail (0 !== 1span links) while every other test stays green, confirming the tests isolate this gap specifically.We also tested a dev version of the Node.js tracer with a sample distributed app and saw both issues resolve with this fix. This service-bus-trigged Azure Function processKitchenQueue did not have a span until the
childOffix.Note: There might be frontend effects as a result of this change - we noticed that a trace without the span link fix had the service bus icon in Datadog UI but was missing it with the fix.