fix(node): Ensure startNewTrace propagates traceId in OTel environments#19963
fix(node): Ensure startNewTrace propagates traceId in OTel environments#19963
Conversation
Semver Impact of This PR🟢 Patch (bug fixes) 📋 Changelog PreviewThis is how your changes will appear in the changelog. New Features ✨
Bug Fixes 🐛
Documentation 📚
Internal Changes 🔧
🤖 This preview updates automatically when you update the PR. |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
There was a problem hiding this comment.
Pull request overview
Adds an OpenTelemetry-aware startNewTrace pathway so that, in OTEL-powered environments, spans created within the callback consistently inherit the newly generated traceId (matching the behavior of continueTrace).
Changes:
- Implement OTEL-specific
startNewTracethat injects a remoteSpanContextinto the active OTEL context. - Extend
AsyncContextStrategyto allow OTEL to override corestartNewTracebehavior, and register the override in the OTEL strategy. - Add regression tests covering
startNewTracetraceId propagation in OTEL environments.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/opentelemetry/src/trace.ts | Adds OTEL-specific startNewTrace which sets a new trace context via OTEL context propagation. |
| packages/opentelemetry/src/asyncContextStrategy.ts | Registers startNewTrace on the OTEL async context strategy so core can delegate to it. |
| packages/core/src/tracing/trace.ts | Delegates startNewTrace to the active async context strategy when available. |
| packages/core/src/asyncContext/types.ts | Extends AsyncContextStrategy interface with optional startNewTrace. |
| packages/opentelemetry/test/trace.test.ts | Adds regression tests to validate traceId behavior within startNewTrace. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
size-limit report 📦
|
node-overhead report 🧳Note: This is a synthetic benchmark with a minimal express app and does not necessarily reflect the real-world performance impact in an application.
|
9572217 to
bf0ba37
Compare
nicohrubec
left a comment
There was a problem hiding this comment.
thanks looks all good to me. just one question did you verify that this also fixes #18401? seems like it might be a different issue
…ents `startNewTrace` only set the traceId on the Sentry scope's propagation context but did not inject it into the OTel context. This caused each `startInactiveSpan` call within the callback to get a fresh random traceId from OTel's tracer instead of sharing the one from `startNewTrace`. Add an OTel-aware `startNewTrace` implementation that injects the new traceId as a remote span context, following the same pattern as `continueTrace`. Closes #19952 Closes #18401 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…scope leakage Address review feedback: calling setPropagationContext before context.with mutated the outer scope, leaking the new traceId after the callback returned. Move it inside the context.with callback so it only affects the cloned scope. Also add a regression test asserting the outer scope is not modified. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Ensures TraceFlags.NONE on the remote span context does not cause the sampler to inherit a false sampling decision from the parent. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Use an explicit traceId in the inner scope instead of relying on generateTraceId producing different values, which can be deterministic in CI with mocked random. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
c57247f to
132b408
Compare
|
@nicohrubec @s1gr1d You are both correct, doesn't seem related not sure how it made it into the description. |

Summary
startNewTraceimplementation that injects the new traceId as a remote span context into the OTel contextstartNewTraceto theAsyncContextStrategyinterface so OTel can override the default behaviorRoot Cause
startNewTraceset a newtraceIdon the Sentry scope's propagation context but only calledwithActiveSpan(null, callback), which in OTel translates totrace.deleteSpan(context.active()). This removed the active span but did not inject the new traceId into the OTel context. Each subsequentstartInactiveSpancall created a root span with a fresh random traceId from OTel's tracer.The fix follows the same pattern as
continueTrace— injecting the traceId as a remote span context viatrace.setSpanContext()so all spans in the callback inherit it.Closes #19952