Skip to content

Conversation

@logaretm
Copy link
Collaborator

@logaretm logaretm commented Dec 3, 2025

This is a big PR because of the tests added, the logic changes themselves are pretty minimal, so make sure to filter out the files when reviewing.

Actual Changes

Removed traces from wrapApiHandlerWithSentry for both the server runtime and the edge runtime

Tests Added

Since we are dropping explicit trace wrapping logic from the pages router templates, we needed to have tests on Next 16 to make sure the page router there still works in both Turbopack and Webpack with minimal differences in the quality of the traces.

We have around 36 test case to check, but only 20 can pass at this time due to the wrapping logic still present, ideally as we move towards removing templates entirely, we can then unskip those tests and tighten many of the assertions we have to accommodate for it.

I added TODOs and a TEST_STATUS.md document to detail what we should update once the SDK drops more of the wrapping logic it currently has.

Closes #18450 (added automatically)

@linear
Copy link

linear bot commented Dec 3, 2025

@logaretm logaretm force-pushed the awad/js-1209-remove-tracing-from-pages-router-api-2 branch 2 times, most recently from 2af20e5 to 2516846 Compare December 3, 2025 10:49
@github-actions
Copy link
Contributor

github-actions bot commented Dec 3, 2025

node-overhead report 🧳

Note: This is a synthetic benchmark with a minimal express app and does not necessarily reflect the real-world performance impact in an application.

Scenario Requests/s % of Baseline Prev. Requests/s Change %
GET Baseline 9,406 - 9,185 +2%
GET With Sentry 1,794 19% 1,801 -0%
GET With Sentry (error only) 6,293 67% 6,271 +0%
POST Baseline 1,200 - 1,203 -0%
POST With Sentry 604 50% 604 -
POST With Sentry (error only) 1,075 90% 1,074 +0%
MYSQL Baseline 3,427 - 3,372 +2%
MYSQL With Sentry 509 15% 465 +9%
MYSQL With Sentry (error only) 2,771 81% 2,751 +1%

View base workflow run

@logaretm logaretm force-pushed the awad/js-1209-remove-tracing-from-pages-router-api-2 branch 2 times, most recently from 9cf8b89 to 27e02e0 Compare December 8, 2025 15:50
@logaretm logaretm force-pushed the awad/js-1209-remove-tracing-from-pages-router-api-2 branch from c055f2d to 8102dd9 Compare December 9, 2025 14:43
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR removes explicit tracing instrumentation from Pages Router API route wrappers (wrapApiHandlerWithSentry) for both Node.js server and Edge runtimes, relying instead on Next.js's built-in OpenTelemetry instrumentation to create transaction spans. The wrappers now only handle error capture, transaction name setting on isolation scope, and route backfilling.

Key Changes:

  • Removed manual span creation (startSpanManual, startSpan) from API route wrappers
  • Wrappers now set transaction names on isolation scope and use route backfill attributes for parameterized route names
  • Updated test expectations to reflect origin change from 'auto.http.nextjs' to 'auto' (from Next.js OTEL)
  • Added comprehensive Next.js 16 Pages Router test application with 36+ test cases

Reviewed changes

Copilot reviewed 74 out of 76 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
packages/nextjs/src/common/pages-router-instrumentation/wrapApiHandlerWithSentry.ts Removed tracing logic; now only captures errors and sets transaction metadata via isolation scope and route backfill
packages/nextjs/src/edge/wrapApiHandlerWithSentry.ts Removed tracing logic from edge runtime wrapper; simplified to error monitoring only
packages/nextjs/src/server/index.ts Added SEMANTIC_ATTRIBUTE_SENTRY_SOURCE to route backfill logic to ensure proper transaction source attribution
packages/nextjs/test/config/withSentry.test.ts Deleted unit test that verified explicit span creation (no longer applicable)
dev-packages/e2e-tests/test-applications/nextjs-13/tests/**/*.test.ts Updated assertions to expect 'auto' origin instead of 'auto.http.nextjs'
dev-packages/e2e-tests/test-applications/create-next-app/tests/**/*.test.ts Updated assertions for new tracing behavior with flexible parent span matching
dev-packages/e2e-tests/test-applications/nextjs-pages-dir/tests/edge-route.test.ts Removed runtime context assertions and skipped scope isolation test
dev-packages/e2e-tests/test-applications/nextjs-16-pages-dir/**/* New comprehensive test application with 36 test cases for Next.js 16 Pages Router covering both webpack and turbopack
dev-packages/e2e-tests/test-applications/nextjs-16-pages-dir/TEST_STATUS.md Detailed documentation of test status, known issues, and future work items

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +93 to 103
// as the runtime freezes as soon as the error is thrown below
await flushSafelyWithTimeout();

// We rethrow here so that nextjs can do with the error whatever it would normally do. (Sometimes "whatever it
// would normally do" is to allow the error to bubble up to the global handlers - another reason we need to mark
// the error as already having been captured.)
throw objectifiedErr;
}
},
});
}
Copy link

Choose a reason for hiding this comment

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

Bug: The removal of waitUntil(flushSafelyWithTimeout()) for successful requests in serverless environments will cause Sentry events to be lost, as the runtime can terminate before flushing is complete.
Severity: CRITICAL | Confidence: High

🔍 Detailed Analysis

For successful requests in both server and edge runtimes, Sentry events are no longer guaranteed to be flushed. The previous implementation used waitUntil(flushSafelyWithTimeout()) to ensure background event transmission completed in serverless environments (like Vercel or Cloudflare) without blocking the response. The new code removes this mechanism for the success path. As a result, the serverless runtime can terminate immediately after the request handler finishes, but before Sentry has finished sending the event, leading to data loss.

💡 Suggested Fix

Reinstate the non-blocking flush mechanism for successful requests. In the finally block of the wrapper, call waitUntil(flushSafelyWithTimeout()) to ensure events are sent without delaying the HTTP response. This was the behavior in the previous implementation and is critical for serverless platforms.

🤖 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/nextjs/src/common/pages-router-instrumentation/wrapApiHandlerWithSentry.ts#L49-L103

Potential issue: For successful requests in both server and edge runtimes, Sentry events
are no longer guaranteed to be flushed. The previous implementation used
`waitUntil(flushSafelyWithTimeout())` to ensure background event transmission completed
in serverless environments (like Vercel or Cloudflare) without blocking the response.
The new code removes this mechanism for the success path. As a result, the serverless
runtime can terminate immediately after the request handler finishes, but before Sentry
has finished sending the event, leading to data loss.

Did we get this right? 👍 / 👎 to inform future reviews.
Reference ID: 6728031

Copy link
Collaborator Author

@logaretm logaretm Dec 10, 2025

Choose a reason for hiding this comment

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

I switched to a blocking await here before throwing which should work better than calling waitUntil then throwing as the runtime can shutdown as soon as an unhandled error like these are thrown.

This matches the logic we have in the other API handler wrapper.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants