Skip to content

Commit f7c033a

Browse files
authored
feat(nextjs): Give app router prefetch requests a http.server.prefetch op (#13600)
Ref (not complete fix) #13596 This gives Next.js prefetch requests a `http.server.prefetch` op, when a `Next-Router-Prefetch: 1` header is present. In some situations Next.js doesn't seem to attach the header for prefetch requests. Seems like it is only attached when the current route is a dynamic route.
1 parent 02290d1 commit f7c033a

File tree

3 files changed

+18
-1
lines changed

3 files changed

+18
-1
lines changed

dev-packages/e2e-tests/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
"test:prepare": "ts-node prepare.ts",
1515
"test:validate": "run-s test:validate-configuration test:validate-test-app-setups",
1616
"clean": "rimraf tmp node_modules pnpm-lock.yaml && yarn clean:test-applications",
17-
"clean:test-applications": "rimraf test-applications/**/{node_modules,dist,build,.next,.sveltekit,pnpm-lock.yaml} .last-run.json && pnpm store prune"
17+
"clean:test-applications": "rimraf --glob test-applications/**/{node_modules,dist,build,.next,.sveltekit,pnpm-lock.yaml} .last-run.json && pnpm store prune"
1818
},
1919
"devDependencies": {
2020
"@types/glob": "8.0.0",

packages/node/src/integrations/http.ts

+12
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,10 @@ export const instrumentHttp = Object.assign(
165165

166166
isolationScope.setTransactionName(bestEffortTransactionName);
167167

168+
if (isKnownPrefetchRequest(req)) {
169+
span.setAttribute('sentry.http.prefetch', true);
170+
}
171+
168172
_httpOptions.instrumentation?.requestHook?.(span, req);
169173
},
170174
responseHook: (span, res) => {
@@ -275,3 +279,11 @@ function getBreadcrumbData(request: ClientRequest): Partial<SanitizedRequestData
275279
function _isClientRequest(req: ClientRequest | HTTPModuleRequestIncomingMessage): req is ClientRequest {
276280
return 'outputData' in req && 'outputSize' in req && !('client' in req) && !('statusCode' in req);
277281
}
282+
283+
/**
284+
* Detects if an incoming request is a prefetch request.
285+
*/
286+
function isKnownPrefetchRequest(req: HTTPModuleRequestIncomingMessage): boolean {
287+
// Currently only handles Next.js prefetch requests but may check other frameworks in the future.
288+
return req.headers['next-router-prefetch'] === '1';
289+
}

packages/opentelemetry/src/utils/parseSpanDescription.ts

+5
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,11 @@ export function descriptionForHttpMethod(
136136
break;
137137
}
138138

139+
// Spans for HTTP requests we have determined to be prefetch requests will have a `.prefetch` postfix in the op
140+
if (attributes['sentry.http.prefetch']) {
141+
opParts.push('prefetch');
142+
}
143+
139144
const { urlPath, url, query, fragment, hasRoute } = getSanitizedUrl(attributes, kind);
140145

141146
if (!urlPath) {

0 commit comments

Comments
 (0)