Skip to content

feat(core): Emit no_parent_span client outcomes for discarded spans requiring a parent - #20350

Merged
s1gr1d merged 7 commits into
developfrom
lms/feat-record-no_parent_span-client-outcome
Apr 20, 2026
Merged

feat(core): Emit no_parent_span client outcomes for discarded spans requiring a parent#20350
s1gr1d merged 7 commits into
developfrom
lms/feat-record-no_parent_span-client-outcome

Conversation

@Lms24

@Lms24Lms24 commented Apr 16, 2026

Copy link
Copy Markdown
Member

This PR adds reporting a client discard outcome for spans we skip because they require a parent span to be active. This happens when onlyIfParent: true is set when starting spans, or in custom logic for http.client spans. With this PR, we should now get a much clearer picture of how many spans users are missing out on.

In span streaming, we'll always emit them (see #17932) spans.

closes https://linear.app/getsentry/issue/SDK-1123/add-client-report-outcome-for-dropped-spans-because-of-missing-parent

@github-actions

github-actionsBot commented Apr 16, 2026

Copy link
Copy Markdown
Contributor

size-limit report 📦

PathSize% ChangeChange
@sentry/browser25.88 kB--
@sentry/browser - with treeshaking flags24.35 kB--
@sentry/browser (incl. Tracing)43.81 kB+0.1%+40 B 🔺
@sentry/browser (incl. Tracing + Span Streaming)45.5 kB+0.08%+35 B 🔺
@sentry/browser (incl. Tracing, Profiling)48.73 kB+0.08%+36 B 🔺
@sentry/browser (incl. Tracing, Replay)82.93 kB+0.05%+36 B 🔺
@sentry/browser (incl. Tracing, Replay) - with treeshaking flags72.43 kB+0.05%+34 B 🔺
@sentry/browser (incl. Tracing, Replay with Canvas)87.62 kB+0.04%+35 B 🔺
@sentry/browser (incl. Tracing, Replay, Feedback)99.87 kB+0.04%+38 B 🔺
@sentry/browser (incl. Feedback)42.7 kB--
@sentry/browser (incl. sendFeedback)30.55 kB--
@sentry/browser (incl. FeedbackAsync)35.55 kB--
@sentry/browser (incl. Metrics)27.16 kB--
@sentry/browser (incl. Logs)27.29 kB--
@sentry/browser (incl. Metrics & Logs)27.98 kB--
@sentry/react27.62 kB--
@sentry/react (incl. Tracing)46.05 kB+0.09%+41 B 🔺
@sentry/vue30.71 kB+0.05%+15 B 🔺
@sentry/vue (incl. Tracing)45.62 kB+0.09%+41 B 🔺
@sentry/svelte25.89 kB--
CDN Bundle28.55 kB--
CDN Bundle (incl. Tracing)44.94 kB+0.25%+112 B 🔺
CDN Bundle (incl. Logs, Metrics)29.93 kB--
CDN Bundle (incl. Tracing, Logs, Metrics)46.03 kB+0.26%+118 B 🔺
CDN Bundle (incl. Replay, Logs, Metrics)68.83 kB--
CDN Bundle (incl. Tracing, Replay)81.9 kB+0.15%+116 B 🔺
CDN Bundle (incl. Tracing, Replay, Logs, Metrics)82.97 kB+0.15%+121 B 🔺
CDN Bundle (incl. Tracing, Replay, Feedback)87.41 kB+0.15%+124 B 🔺
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics)88.49 kB+0.15%+125 B 🔺
CDN Bundle - uncompressed83.4 kB--
CDN Bundle (incl. Tracing) - uncompressed134.3 kB+0.21%+270 B 🔺
CDN Bundle (incl. Logs, Metrics) - uncompressed87.55 kB--
CDN Bundle (incl. Tracing, Logs, Metrics) - uncompressed137.72 kB+0.2%+270 B 🔺
CDN Bundle (incl. Replay, Logs, Metrics) - uncompressed210.91 kB--
CDN Bundle (incl. Tracing, Replay) - uncompressed251.53 kB+0.11%+270 B 🔺
CDN Bundle (incl. Tracing, Replay, Logs, Metrics) - uncompressed254.93 kB+0.11%+270 B 🔺
CDN Bundle (incl. Tracing, Replay, Feedback) - uncompressed264.45 kB+0.11%+270 B 🔺
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics) - uncompressed267.83 kB+0.11%+270 B 🔺
@sentry/nextjs (client)48.58 kB+0.08%+37 B 🔺
@sentry/sveltekit (client)44.22 kB+0.09%+39 B 🔺
@sentry/node-core58.02 kB+0.1%+55 B 🔺
@sentry/node174.89 kB+0.06%+90 B 🔺
@sentry/node - without tracing97.98 kB+0.07%+66 B 🔺
@sentry/aws-serverless115.21 kB+0.06%+58 B 🔺

View base workflow run

@linear-code

Copy link
Copy Markdown

@Lms24
Lms24 marked this pull request as ready for review April 16, 2026 15:28
@Lms24Lms24 self-assigned this Apr 16, 2026
@s1gr1ds1gr1d self-assigned this Apr 17, 2026
Comment threadpackages/opentelemetry/src/trace.ts Outdated
Comment on lines +51 to +56
const shouldSkipSpan = options.onlyIfParent && !trace.getSpan(activeCtx);
const ctx = shouldSkipSpan ? suppressTracing(activeCtx) : activeCtx;

if (shouldSkipSpan) {
getClient()?.recordDroppedEvent('no_parent_span', 'span');
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Maybe this could be made a bit more robust. Right now it's checking shouldSkipSpan but the value of the variable could depend on something else than onlyIfParent in the future. Then this would be wrong.

The test also only check for dropped events and not necessarily that this resulted because of a missing parent span.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Yeah I guess we could inline the variable or name it a bit more precise, unless you had something else in mind?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I added some additional tests and changed the variable name to a more descriptive one (missingRequiredParent) and not behaviorial one. shouldSkipSpan could include any condition why we skip spans.

It was not really possible to change the general structure here.

| 'ignored'
| 'invalid';
| 'invalid'
| 'no_parent_span';

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

do we need a change in relay for this?

Comment threadpackages/opentelemetry/src/trace.ts Outdated
Comment on lines +51 to +56
const shouldSkipSpan = options.onlyIfParent && !trace.getSpan(activeCtx);
const ctx = shouldSkipSpan ? suppressTracing(activeCtx) : activeCtx;

if (shouldSkipSpan) {
getClient()?.recordDroppedEvent('no_parent_span', 'span');
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Yeah I guess we could inline the variable or name it a bit more precise, unless you had something else in mind?

@s1gr1d
s1gr1d enabled auto-merge (squash) April 20, 2026 09:20
@s1gr1d
s1gr1d disabled auto-merge April 20, 2026 09:20
@s1gr1d
s1gr1d enabled auto-merge (squash) April 20, 2026 09:21

@cursorcursorBot 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 1 potential issue.

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 2b11222. Configure here.

Co-authored-by: Nicolas Hrubec <nicolas.hrubec@outlook.com>
Comment on lines +162 to 164
getClient()?.recordDroppedEvent('no_parent_span', 'span');
}

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.

Bug:http.client spans without a parent are counted as dropped twice: once in startInactiveSpan and again in the SentrySampler, leading to inflated metrics.
Severity: MEDIUM

Suggested Fix

Prevent the double-counting of dropped events. One approach is to remove the recordDroppedEvent('no_parent_span', 'span') call from startInactiveSpan for http.client spans, allowing the SentrySampler to handle this case exclusively as it did previously.

Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent. Verify if this is a real issue. If it is, propose a fix; if not, explain why it's
not valid.
Location: packages/opentelemetry/src/trace.ts#L162-L164
Potential issue: When an `http.client` span is created with `onlyIfParent: true` and no
active parent span exists, the new logic in `startInactiveSpan` records a
`'no_parent_span'` dropped event. However, the span creation process continues, and the
`SentrySampler` is also invoked. The sampler contains separate logic to detect and
record a dropped event for `http.client` spans without a local parent. This results in
the same dropped span being counted twice, which will inflate the `no_parent_span`
outcome metrics.

Did we get this right? 👍 / 👎 to inform future reviews.

@s1gr1d
s1gr1d merged commit be13537 into developApr 20, 2026
244 of 245 checks passed
@s1gr1d
s1gr1d deleted the lms/feat-record-no_parent_span-client-outcome branch April 20, 2026 11:43
Sign up for freeto 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.

3 participants

@Lms24@nicohrubec@s1gr1d