Skip to content

fix(opentelemetry): Ensure only orphaned spans of sent spans are sent #16590

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jun 16, 2025

Conversation

mydea
Copy link
Member

@mydea mydea commented Jun 16, 2025

Noticed this small but potentially impactful typo: We used to mark all finished spans as sent, not just the ones that are actually sent :O (Also we iterated twice over the same array, streamlined this by just doing this once).

@mydea mydea requested review from BYK, Lms24 and andreiborza June 16, 2025 12:28
@mydea mydea self-assigned this Jun 16, 2025
Copy link
Member

@andreiborza andreiborza left a comment

Choose a reason for hiding this comment

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

Nice find!

Should we reflect this in a test somewhere?

@@ -192,6 +189,7 @@ export class SentrySpanExporter {
);

for (const span of sentSpans) {
this._sentSpans.set(span.spanContext().spanId, Date.now() + DEFAULT_TIMEOUT * 1000);
Copy link
Member

Choose a reason for hiding this comment

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

Just noticed, we should probably move out the Date.now() + DEFAULT_TIMEOUT * 1000 part to avoid recalculating it over the loop.

Copy link
Member Author

Choose a reason for hiding this comment

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

ah, great catch too! 👍 will do!

Copy link
Member

@BYK BYK left a comment

Choose a reason for hiding this comment

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

Good catch! That said I think this was intentional as sometimes we never send spans so they don't end up in sentSpans. We may rename this._sentSpans to this._finishedSpans to avoid the confusion. To avoid going over this list a second time, we may try to bake the logic into this._maybeSend I guess. Not sure how impactful that would be tho.

@mydea
Copy link
Member Author

mydea commented Jun 16, 2025

so we def. cannot do this based on finished spans, as that breaks the product quite drastically - as generally, it is really bad if we send spans with the wrong transaction (as the product still relies on this a lot), so this should only be last resort. This is leading to bugs today (where e.g. db spans show up as transactions instead of as spans of their http.server transaction how they should be) 😬
we could think about, in a follow up, handling stuff we would otherwise discard somehow differently, so they are eventually sent.

@mydea
Copy link
Member Author

mydea commented Jun 16, 2025

I also added a test that previously failed - which shows that if the actual root span is not sent yet, we should never send the child span on it's own, as that breaks the product.

@mydea mydea changed the title fix(opentelemetry): Ensure unsent spans are ignored in span exporter fix(opentelemetry): Ensure only orphaned spans of sent spans are sent Jun 16, 2025
@mydea mydea force-pushed the fn/fix-spanexporter-bug branch from a65df3d to 024562c Compare June 16, 2025 14:00
@mydea
Copy link
Member Author

mydea commented Jun 16, 2025

sometimes we never send spans

if that happens IMHO this is a major problem that should be fixed at its root rather than working around it like this 🤔

@@ -3,16 +3,15 @@ import { waitForTransaction } from '@sentry-internal/test-utils';

test('should create AI spans with correct attributes', async ({ page }) => {
const aiTransactionPromise = waitForTransaction('nextjs-15', async transactionEvent => {
return transactionEvent?.transaction === 'ai-test';
return transactionEvent.transaction === 'GET /ai-test';
Copy link
Member Author

Choose a reason for hiding this comment

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

this actually also shows the incorrect behavior we had before - the ai-test span was sent as a transaction instead of as part of the GET /ai-test span, which is what it should have been.

@mydea mydea enabled auto-merge (squash) June 16, 2025 14:14
@mydea mydea merged commit a744088 into develop Jun 16, 2025
143 of 145 checks passed
@mydea mydea deleted the fn/fix-spanexporter-bug branch June 16, 2025 14:24
@BYK
Copy link
Member

BYK commented Jun 17, 2025

@mydea

sometimes we never send spans

if that happens IMHO this is a major problem that should be fixed at its root rather than working around it like this 🤔

Following up on this to prevent FUD: I think this was due to those spans belonging to root spans that were already sent (so the very thing the patch was aiming to fix). That means the current behavior (the one with your fix in) is 100% correct and there shouldn't be any spans not being sent or not being considered to be sent.

TL;DR -- My earlier comment was not fully accurate and I don't think we need anything more to investigate regarding that. Sorry for the confusion.

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.

3 participants