You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
When using Next.js with Turbopack and the Sentry tunnel route feature (tunnelRoute: true), several issues prevented events from being sent properly:
1. Tunnel Route Consistency (Turbopack)
Problem: Random tunnel routes were generated separately for client and server builds in Turbopack.
Solution: Implemented processs-level caching in withSentryConfig.ts:
Extract tunnel route resolution into resolveTunnelRoute() function
Use process.env to store the random tunnel value across server/client builds.
2. Filter Tunnel Request Spans
Problem: Requests to the tunnel route (before rewrite) and to Sentry ingest URLs (after rewrite) were creating spans that polluted Sentry with internal instrumentation noise, spans were being created by the middleware and OTEL node.js fetch instrumentation.
Solution: Implemented server-side span filtering:
Created dropMiddlewareTunnelRequests() utility to detect and drop tunnel-related spans
Filter spans originating from Middleware.execute (Next.js middleware)
Filter spans originating from auto.http.otel.node_fetch (Node.js fetch instrumentation)
Check both local tunnel paths and Sentry ingest URLs (using isSentryRequestSpan from @sentry/opentelemetry)
Mark matching spans with TRANSACTION_ATTR_SHOULD_DROP_TRANSACTION to prevent them from being sent
I tried beforeSampling hook but it didn't work for some reason, so I stuck with the drop attribute.
The final issue was excluding the tunnel requests from the middleware/proxy, but there are many blockers for a solution:
The config must be statically analyzable, so we cannot expose withSentryMiddlewareConfig wrapper of any kind.
Warning the user doesn't help much because they can't do anything about it since the tunnel route is random.
Tested out writing a loader for turbopack/webpack to inject the tunnel into the matcher as an array but user existing matcher can match still.
Only way is to inject an exclusion match into the user existing matcher, if it is an array then we need to inject it into each single entry.
I may explore this further later with a loader for both webpack/turbopack, and figure out a reliable way to inject the negative matchers into the user expressions.
The event processor on the edge runtime only filters transactions based on the TRANSACTION_ATTR_SHOULD_DROP_TRANSACTION attribute, but lacks the explicit tunnel route transaction name check present in the server-side event processor. This asymmetry creates a defensive gap: if span marking fails for any reason, server-side transactions are still filtered by name, but edge-side transactions would slip through. For consistency and robustness, the edge-side event processor should include the same explicit tunnel route check that filters POST requests to the tunnel path.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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.
When using Next.js with Turbopack and the Sentry tunnel route feature (
tunnelRoute: true), several issues prevented events from being sent properly:1. Tunnel Route Consistency (Turbopack)
Problem: Random tunnel routes were generated separately for client and server builds in Turbopack.
Solution: Implemented processs-level caching in
withSentryConfig.ts:resolveTunnelRoute()functionprocess.envto store the random tunnel value across server/client builds.2. Filter Tunnel Request Spans
Problem: Requests to the tunnel route (before rewrite) and to Sentry ingest URLs (after rewrite) were creating spans that polluted Sentry with internal instrumentation noise, spans were being created by the middleware and OTEL node.js fetch instrumentation.
Solution: Implemented server-side span filtering:
dropMiddlewareTunnelRequests()utility to detect and drop tunnel-related spansMiddleware.execute(Next.js middleware)auto.http.otel.node_fetch(Node.js fetch instrumentation)isSentryRequestSpanfrom@sentry/opentelemetry)TRANSACTION_ATTR_SHOULD_DROP_TRANSACTIONto prevent them from being sentbeforeSamplinghook but it didn't work for some reason, so I stuck with the drop attribute.The final issue was excluding the tunnel requests from the middleware/proxy, but there are many blockers for a solution:
configmust be statically analyzable, so we cannot exposewithSentryMiddlewareConfigwrapper of any kind.I may explore this further later with a loader for both webpack/turbopack, and figure out a reliable way to inject the negative matchers into the user expressions.