Skip to content

Commit 02290d1

Browse files
author
Luca Forstner
authored
feat(nextjs): Improve Next.js serverside span data quality (#13652)
Sometimes we were sending faulty `default` ops for Next.js transactions. This seemed to happen when the HTTP integration couldn't get a handle of the incoming requests (yet to figure out why). This PR: - Backfills the op for faulty transactions - Sets the origin of spans generated by Next.js to `auto` (I couldn't come up with a more specific origin because the second part of it is an op and none are satisfactory) - Remove the `sentry.skip_span_data_inference` which is only used internally. This change is hard to test because it seems to happen flakily that the http integration isn't working. Fixes #13598
1 parent ae4451d commit 02290d1

File tree

3 files changed

+27
-2
lines changed

3 files changed

+27
-2
lines changed

dev-packages/e2e-tests/test-applications/nextjs-14/tests/generation-functions.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ test('Should emit a span for a generateMetadata() function invokation', async ({
1717
expect(transaction.spans).toContainEqual(
1818
expect.objectContaining({
1919
description: 'generateMetadata /generation-functions/page',
20-
origin: 'manual',
20+
origin: 'auto',
2121
parent_span_id: expect.any(String),
2222
span_id: expect.any(String),
2323
status: 'ok',
@@ -74,7 +74,7 @@ test('Should send a transaction event for a generateViewport() function invokati
7474
expect((await transactionPromise).spans).toContainEqual(
7575
expect.objectContaining({
7676
description: 'generateViewport /generation-functions/page',
77-
origin: 'manual',
77+
origin: 'auto',
7878
parent_span_id: expect.any(String),
7979
span_id: expect.any(String),
8080
status: 'ok',

packages/nextjs/src/server/index.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import {
2+
SEMANTIC_ATTRIBUTE_SENTRY_OP,
23
SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,
34
applySdkMetadata,
45
getClient,
@@ -189,6 +190,7 @@ export function init(options: NodeOptions): NodeClient | undefined {
189190
// with patterns (e.g. http.server spans) that will produce confusing data.
190191
if (spanAttributes?.['next.span_type'] !== undefined) {
191192
span.setAttribute('sentry.skip_span_data_inference', true);
193+
span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, 'auto');
192194
}
193195

194196
// We want to rename these spans because they look like "GET /path/to/route" and we already emit spans that look
@@ -286,6 +288,28 @@ export function init(options: NodeOptions): NodeClient | undefined {
286288
),
287289
);
288290

291+
getGlobalScope().addEventProcessor(
292+
Object.assign(
293+
(event => {
294+
// Sometimes, the HTTP integration will not work, causing us not to properly set an op for spans generated by
295+
// Next.js that are actually more or less correct server HTTP spans, so we are backfilling the op here.
296+
if (
297+
event.type === 'transaction' &&
298+
event.transaction?.match(/^(RSC )?GET /) &&
299+
event.contexts?.trace?.data?.['sentry.rsc'] === true &&
300+
!event.contexts.trace.op
301+
) {
302+
event.contexts.trace.data = event.contexts.trace.data || {};
303+
event.contexts.trace.data[SEMANTIC_ATTRIBUTE_SENTRY_OP] = 'http.server';
304+
event.contexts.trace.op = 'http.server';
305+
}
306+
307+
return event;
308+
}) satisfies EventProcessor,
309+
{ id: 'NextjsTransactionEnhancer' },
310+
),
311+
);
312+
289313
if (process.env.NODE_ENV === 'development') {
290314
getGlobalScope().addEventProcessor(devErrorSymbolicationEventProcessor);
291315
}

packages/opentelemetry/src/spanExporter.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,7 @@ function removeSentryAttributes(data: Record<string, unknown>): Record<string, u
345345
/* eslint-disable @typescript-eslint/no-dynamic-delete */
346346
delete cleanedData[SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE];
347347
delete cleanedData[SEMANTIC_ATTRIBUTE_SENTRY_PARENT_IS_REMOTE];
348+
delete cleanedData['sentry.skip_span_data_inference'];
348349
/* eslint-enable @typescript-eslint/no-dynamic-delete */
349350

350351
return cleanedData;

0 commit comments

Comments
 (0)