Skip to content

ref(node): Streamline undici (node-fetch) instrumentation#21650

Open
logaretm wants to merge 1 commit into
developfrom
awad/js-2395-streamline-opentelemetryinstrumentation-undici
Open

ref(node): Streamline undici (node-fetch) instrumentation#21650
logaretm wants to merge 1 commit into
developfrom
awad/js-2395-streamline-opentelemetryinstrumentation-undici

Conversation

@logaretm

@logaretm logaretm commented Jun 19, 2026

Copy link
Copy Markdown
Member

Streamlines the vendored UndiciInstrumentation (the span-emitting half of the NodeFetch integration) onto Sentry's span APIs.

closes #20743

Refactor the vendored `UndiciInstrumentation` (the span-emitting half of the
NodeFetch integration) to use Sentry's span APIs instead of OpenTelemetry's
tracing/propagation APIs.

- Span creation: `tracer.startSpan` -> `startInactiveSpan({ kind: CLIENT })`
  (the span is created on `undici:request:create` and ended later in
  `onDone`/`onError`, so it must be inactive).
- Status: `SpanStatusCode` -> `SPAN_STATUS_ERROR`; drop the no-op
  `recordException`.
- Trace propagation: replace `propagation.inject(trace.setSpan(...))` with
  `withActiveSpan(span, () => getTraceData(...))` gated by
  `shouldPropagateTraceForUrl`. This keeps the propagated `sentry-trace`
  referencing the http.client span (not the parent), matching prior output.
  Passing `{ span }` to `getTraceData` alone is insufficient: for an inactive
  span it resolves to the span's captured scope, whose active span is the
  parent.
- Drop the OTel metrics (no MeterProvider is wired up) and the dead
  `requireParentforSpans` code path (the SDK always passes `false`).
- Replace the diag logger with `debug` + `DEBUG_BUILD`, swap OTel type imports
  for `@sentry/core`, inline the semantic-convention constants into a local
  `semconv.ts`, and drop the blanket `eslint-disable`s.

The only remaining `@opentelemetry/api` usage is `SpanKind`; the
`@opentelemetry/instrumentation` patching base is kept.

Adds integration coverage for the error path (`internal_error` span) and for
`headersToSpanAttributes` (request + response header capture).
@linear-code

linear-code Bot commented Jun 19, 2026

Copy link
Copy Markdown

JS-2395

@github-actions

Copy link
Copy Markdown
Contributor

size-limit report 📦

Path Size % Change Change
@sentry/browser 27.45 kB - -
@sentry/browser - with treeshaking flags 25.88 kB - -
@sentry/browser (incl. Tracing) 45.91 kB - -
@sentry/browser (incl. Tracing + Span Streaming) 48.16 kB - -
@sentry/browser (incl. Tracing, Profiling) 50.69 kB - -
@sentry/browser (incl. Tracing, Replay) 85.1 kB - -
@sentry/browser (incl. Tracing, Replay) - with treeshaking flags 74.71 kB - -
@sentry/browser (incl. Tracing, Replay with Canvas) 89.8 kB - -
@sentry/browser (incl. Tracing, Replay, Feedback) 102.47 kB - -
@sentry/browser (incl. Feedback) 44.62 kB - -
@sentry/browser (incl. sendFeedback) 32.25 kB - -
@sentry/browser (incl. FeedbackAsync) 37.38 kB - -
@sentry/browser (incl. Metrics) 28.52 kB - -
@sentry/browser (incl. Logs) 28.76 kB - -
@sentry/browser (incl. Metrics & Logs) 29.45 kB - -
@sentry/react 29.25 kB - -
@sentry/react (incl. Tracing) 48.21 kB - -
@sentry/vue 32.58 kB - -
@sentry/vue (incl. Tracing) 47.78 kB - -
@sentry/svelte 27.48 kB - -
CDN Bundle 29.86 kB - -
CDN Bundle (incl. Tracing) 48.32 kB - -
CDN Bundle (incl. Logs, Metrics) 31.4 kB - -
CDN Bundle (incl. Tracing, Logs, Metrics) 49.62 kB - -
CDN Bundle (incl. Replay, Logs, Metrics) 70.71 kB - -
CDN Bundle (incl. Tracing, Replay) 85.64 kB - -
CDN Bundle (incl. Tracing, Replay, Logs, Metrics) 86.9 kB - -
CDN Bundle (incl. Tracing, Replay, Feedback) 91.49 kB - -
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics) 92.73 kB - -
CDN Bundle - uncompressed 88.8 kB - -
CDN Bundle (incl. Tracing) - uncompressed 146.13 kB - -
CDN Bundle (incl. Logs, Metrics) - uncompressed 93.5 kB - -
CDN Bundle (incl. Tracing, Logs, Metrics) - uncompressed 150.1 kB - -
CDN Bundle (incl. Replay, Logs, Metrics) - uncompressed 218.33 kB - -
CDN Bundle (incl. Tracing, Replay) - uncompressed 264.99 kB - -
CDN Bundle (incl. Tracing, Replay, Logs, Metrics) - uncompressed 268.95 kB - -
CDN Bundle (incl. Tracing, Replay, Feedback) - uncompressed 278.69 kB - -
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics) - uncompressed 282.64 kB - -
@sentry/nextjs (client) 50.61 kB - -
@sentry/sveltekit (client) 46.3 kB - -
@sentry/core/server 76.21 kB - -
@sentry/core/browser 63.34 kB - -
@sentry/node-core 61.9 kB +0.01% +1 B 🔺
@sentry/node 124.4 kB -0.24% -287 B 🔽
@sentry/node/import (ESM hook with diagnostics-channel injection) 70.05 kB - -
@sentry/node/light 50.98 kB - -
@sentry/node - without tracing 73.91 kB -0.49% -361 B 🔽
@sentry/aws-serverless 85.03 kB -0.4% -339 B 🔽
@sentry/cloudflare (withSentry) - minified 174.55 kB - -
@sentry/cloudflare (withSentry) 436.86 kB - -

View base workflow run

@logaretm logaretm marked this pull request as ready for review June 19, 2026 00:57
@logaretm logaretm requested a review from a team as a code owner June 19, 2026 00:57
@logaretm logaretm requested review from JPeer264, andreiborza, isaacs, mydea and nicohrubec and removed request for a team and mydea June 19, 2026 00:57

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 3 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 2b3dbd0. Configure here.

name: requestMethod === '_OTHER' ? 'HTTP' : requestMethod,
kind: SpanKind.CLIENT,
attributes,
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Missing http.client sentry.op

High Severity

startInactiveSpan is called without sentry.op (http.client) on the span or in merged attributes. The integration tests and prior OTel export path expect outgoing fetch spans to use op http.client, but native SentrySpan JSON only reads op from attributes and does not infer it from kind or http.request.method.

Fix in Cursor Fix in Web

Triggered by project rule: PR Review Guidelines for Cursor Bot

Reviewed by Cursor Bugbot for commit 2b3dbd0. Configure here.

name: requestMethod === '_OTHER' ? 'HTTP' : requestMethod,
kind: SpanKind.CLIENT,
attributes,
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Fetch span description missing URL

Medium Severity

Outgoing fetch spans are started with name set to the HTTP method only (e.g. GET), while integration tests expect descriptions like GET http://host/path. The OTel exporter used to derive that description from URL attributes and CLIENT kind; that inference no longer runs for these native spans.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 2b3dbd0. Configure here.

span.recordException(error);
span.setStatus({
code: SpanStatusCode.ERROR,
code: SPAN_STATUS_ERROR,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Error status not internal_error

Medium Severity

On undici:request:error, the span status message is set to the raw error.message, so serialized status is typically the system error string rather than internal_error. The new fetch-error integration test expects status: 'internal_error', consistent with @sentry/core fetch instrumentation.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 2b3dbd0. Configure here.

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.

Streamline @opentelemetry/instrumentation-undici

1 participant