Skip to content

Conversation

@JPeer264
Copy link
Member

follow up to #16681

Problem

The waitUntil could 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 inside waitUntil could 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 W                          
Loading

Solution

There is a way to end the root span after everything has been finished, which allows us to send everything in one transaction. In order to still have a correct span for the request itself, I had to create a dedicated span just for the request (that can be seen in the "after" picture beneath).

Right now we only send one transaction after everything is finished, which could take up to "request time" + 30 seconds (that is the maximum wait time for a waitUntil). Which means Sentry gets that data after that time. Very soon there will be the concept of span streaming which would make these events available earlier.

sequenceDiagram
    participant R as Request
    participant W as waitUntil
    participant S as Root Span

    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 R: Request handler returns
    deactivate R
    
    Note over S: Root span stays open!<br/>Waiting for waitUntil...
    
    Note over W: waitUntil continues running...
    
    W->>S: Event 2 ✓
    Note over S: Captured!<br/>Same transaction
    
    W->>W: waitUntil completes
    deactivate W
    
    R->>S: Root span ends (after all waitUntil done)
    deactivate S
Loading

Special eyes

There is now an extra span for the fetch, which is basically the request itself. So this can be looked at with a critical eye

Comparison

before:

Screenshot 2025-12-12 at 15 02 10

after:

Screenshot 2025-12-12 at 15 00 19

@github-actions
Copy link
Contributor

size-limit report 📦

Path Size % Change Change
@sentry/browser 24.81 kB - -
@sentry/browser - with treeshaking flags 23.3 kB - -
@sentry/browser (incl. Tracing) 41.55 kB - -
@sentry/browser (incl. Tracing, Profiling) 46.14 kB - -
@sentry/browser (incl. Tracing, Replay) 79.97 kB - -
@sentry/browser (incl. Tracing, Replay) - with treeshaking flags 69.7 kB - -
@sentry/browser (incl. Tracing, Replay with Canvas) 84.64 kB - -
@sentry/browser (incl. Tracing, Replay, Feedback) 96.89 kB - -
@sentry/browser (incl. Feedback) 41.52 kB - -
@sentry/browser (incl. sendFeedback) 29.49 kB - -
@sentry/browser (incl. FeedbackAsync) 34.48 kB - -
@sentry/react 26.52 kB - -
@sentry/react (incl. Tracing) 43.75 kB - -
@sentry/vue 29.27 kB - -
@sentry/vue (incl. Tracing) 43.36 kB - -
@sentry/svelte 24.82 kB - -
CDN Bundle 27.24 kB - -
CDN Bundle (incl. Tracing) 42.23 kB - -
CDN Bundle (incl. Tracing, Replay) 78.75 kB - -
CDN Bundle (incl. Tracing, Replay, Feedback) 84.21 kB - -
CDN Bundle - uncompressed 80.04 kB - -
CDN Bundle (incl. Tracing) - uncompressed 125.39 kB - -
CDN Bundle (incl. Tracing, Replay) - uncompressed 241.42 kB - -
CDN Bundle (incl. Tracing, Replay, Feedback) - uncompressed 254.18 kB - -
@sentry/nextjs (client) 45.97 kB - -
@sentry/sveltekit (client) 41.92 kB - -
@sentry/node-core 51.5 kB - -
@sentry/node 159.94 kB - -
@sentry/node - without tracing 92.91 kB +0.02% +14 B 🔺
@sentry/aws-serverless 108.44 kB - -

View base workflow run

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.

2 participants