fix(cloudflare): Missing events inside waitUntil #18475
Draft
+61
−4
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This is a follow up to #16681.
Problem
The
waitUntilcould take longer than the actual request is taking, which is actually a good thing and wanted by Cloudflare. By definition of our implementation we are ending the root span at the end of the request, while the promise insidewaitUntilcould still generate events. These events are only send while the root span is still active ("Event 1" in the mermaid diagram), but are not send anymore when the root span ended ("Event 2") and are basically dropped.sequenceDiagram participant R as Request participant W as waitUntil participant S as Sentry Spans Note over R: Request starts activate R R->>S: Root span starts activate S Note over R,W: User calls ctx.waitUntil(promise) R->>W: Promise created activate W W->>S: Event 1 ✓ Note over S: Captured (span still active) Note over R: Request handler returns deactivate R R->>S: Root span ends deactivate S Note over W: waitUntil continues running... W->>S: Event 2 ✗ Note over S: LOST!<br/>Span already ended W->>W: waitUntil completes deactivate WSolution
While the solution is not perfect, it is mitigating the problem. To mitigate it we add a new transaction for the
waitUntil, which means it is free of the root span duration, but it still has the information of the trace and its span parent.sequenceDiagram participant R as Request participant W as waitUntil participant S1 as Root Span participant S2 as waitUntil Transaction Note over R: Request starts activate R R->>S1: Root span starts activate S1 Note over R,W: User calls ctx.waitUntil(promise) R->>W: Promise created activate W W->>S2: waitUntil transaction starts activate S2 W->>S2: Event 1 ✓ Note over R: Request handler returns deactivate R R->>S1: Root span ends deactivate S1 Note over W: waitUntil continues running... W->>S2: Event 2 ✓ Note over S2: Captured!<br/>waitUntil transaction still active W->>S2: waitUntil transaction ends deactivate S2 W->>W: waitUntil completes deactivate WSide effects
That actually causes one slight problem, where I don't have the solution for, except writing documentation.
When there is a manual sentry span added inside a
waitUntilit will have the wrong parent span, since the parent is the same as the one of the request. Since by the time of the execution ofasyncFn()the parent will be request, and notasyncFn. However, this can be solved when the user adds aforceTransaction: truemanually inside theSentry.startSpan, since then it will decouple again and will have the correct parent span.