Repository navigation
fix(nextjs): Drop the request span that only runs the proxy #25386
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
base: develop
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| export const dynamic = 'force-dynamic'; | ||
|
|
||
| export default function Page() { | ||
| return <h1>Page behind proxy</h1>; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -48,6 +48,31 @@ test('Should create a span for middleware', async ({ request }) => { | |
| expect(routeSpan.attributes['isolation_scope.has_proxy_marker']).toEqual({ value: false, type: 'boolean' }); | ||
| }); | ||
|
|
||
| for (const path of ['/api/endpoint-behind-middleware', '/page-behind-proxy']) { | ||
| test(`Should create one http.server segment for a request to ${path} behind the proxy`, async ({ request }) => { | ||
| test.skip(getRuntime() === 'cloudflare', 'On Workers the middleware span is a child of the request span'); | ||
|
|
||
| // Next.js runs the proxy in a `BaseServer.handleRequest` span of its own, before the one that renders the route. | ||
| // That first span has neither a route nor the middleware span as a child, so it must not become a second | ||
| // `http.server` segment. | ||
| const spansPromise = collectStreamedSpans( | ||
| 'nextjs-16', | ||
| spans => | ||
| spans.some(span => span.is_segment && span.name === 'middleware GET') && | ||
| spans.some(span => span.is_segment && span.name === `GET ${path}`), | ||
| ); | ||
|
|
||
| const response = await request.get(path); | ||
| expect(response.status()).toBe(200); | ||
|
|
||
| const segmentSpans = (await spansPromise).filter(span => span.is_segment); | ||
| expect(segmentSpans.map(span => span.name).sort()).toEqual([`GET ${path}`, 'middleware GET']); | ||
| expect(segmentSpans.filter(span => getSpanOp(span) === 'http.server').map(span => span.name)).toEqual([ | ||
| `GET ${path}`, | ||
| ]); | ||
| }); | ||
| } | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Loop registers scenarios instead of test.eachLow Severity A Triggered by project rule: PR Review Guidelines for Cursor Bot Reviewed by Cursor Bugbot for commit bcb8427. Configure here. |
||
|
|
||
| // `withSentry` from `@sentry/nextjs/cloudflare` wraps the Worker entry, so middleware runs inside the request's | ||
| // `http.server` segment and its span is a child of it rather than a segment of its own. | ||
| test('Should create a span for middleware inside the request segment of the Worker', async ({ request }) => { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| import type { Scope } from '../scope'; | ||
| import { derefWeakRef, makeWeakRef, type MaybeWeakRef } from './weakRef'; | ||
|
|
||
| const SCOPE_INCOMING_REQUEST_FIELD = 'incomingRequest'; | ||
|
|
||
| /** | ||
| * Set the incoming request (e.g. Node's `IncomingMessage`) that a request's isolation scope belongs to. | ||
| * NOTE: This should NOT be used directly, but is only used internally by the server instrumentation. | ||
| */ | ||
| export function _setIncomingRequestForScope(scope: Scope, request: object): void { | ||
| // Use WeakRef so a scope that outlives the request (e.g. captured on a span) does not keep it alive | ||
| scope.refs[SCOPE_INCOMING_REQUEST_FIELD] = makeWeakRef(request); | ||
| } | ||
|
|
||
| /** | ||
| * Get the incoming request that a request's isolation scope belongs to. | ||
| * NOTE: This should NOT be used directly, but is only used internally by framework SDKs. | ||
| */ | ||
| export function _getIncomingRequestForScope(scope: Scope): object | undefined { | ||
| return derefWeakRef(scope.refs[SCOPE_INCOMING_REQUEST_FIELD] as MaybeWeakRef<object> | undefined); | ||
| } |


There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Span op asserted as string literal
Low Severity
The new segment assertion compares
getSpanOpto the string'http.server'. Testing conventions require span-op assertions to use the@sentry/conventionsconstant rather than a literal. Flagged because it is called out in the PR review rules.Triggered by project rule: PR Review Guidelines for Cursor Bot
Reviewed by Cursor Bugbot for commit bcb8427. Configure here.