Skip to content

Commit 10829d6

Browse files
author
Luca Forstner
committed
Actually factually don't drop Next.js OTEL spans anymore
1 parent 80745fc commit 10829d6

File tree

1 file changed

+5
-37
lines changed

1 file changed

+5
-37
lines changed

packages/nextjs/src/server/index.ts

Lines changed: 5 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -36,22 +36,6 @@ const globalWithInjectedValues = GLOBAL_OBJ as typeof GLOBAL_OBJ & {
3636
__sentryRewritesTunnelPath__?: string;
3737
};
3838

39-
// https://github.com/lforst/nextjs-fork/blob/9051bc44d969a6e0ab65a955a2fc0af522a83911/packages/next/src/server/lib/trace/constants.ts#L11
40-
const NEXTJS_SPAN_NAME_PREFIXES = [
41-
'BaseServer.',
42-
'LoadComponents.',
43-
'NextServer.',
44-
'createServer.',
45-
'startServer.',
46-
'NextNodeServer.',
47-
'Render.',
48-
'AppRender.',
49-
'Router.',
50-
'Node.',
51-
'AppRouteRouteHandlers.',
52-
'ResolveMetadata.',
53-
];
54-
5539
/**
5640
* A passthrough error boundary for the server that doesn't depend on any react. Error boundaries don't catch SSR errors
5741
* so they should simply be a passthrough.
@@ -135,25 +119,7 @@ export function init(options: NodeOptions): NodeClient | undefined {
135119
applySdkMetadata(opts, 'nextjs', ['nextjs', 'node']);
136120

137121
const client = nodeInit(opts);
138-
client?.on('beforeSampling', ({ spanAttributes, spanName, parentSampled, parentContext }, samplingDecision) => {
139-
// We allowlist the "BaseServer.handleRequest" span, since that one is responsible for App Router requests, which are actually useful for us.
140-
// HOWEVER, that span is not only responsible for App Router requests, which is why we additionally filter for certain transactions in an
141-
// event processor further below.
142-
if (spanAttributes['next.span_type'] === 'BaseServer.handleRequest') {
143-
return;
144-
}
145-
146-
// If we encounter a span emitted by Next.js, we do not want to sample it
147-
// The reason for this is that the data quality of the spans varies, it is different per version of Next,
148-
// and we need to keep our manual instrumentation around for the edge runtime anyhow.
149-
// BUT we only do this if we don't have a parent span with a sampling decision yet (or if the parent is remote)
150-
if (
151-
(spanAttributes['next.span_type'] || NEXTJS_SPAN_NAME_PREFIXES.some(prefix => spanName.startsWith(prefix))) &&
152-
(parentSampled === undefined || parentContext?.isRemote)
153-
) {
154-
samplingDecision.decision = false;
155-
}
156-
122+
client?.on('beforeSampling', ({ spanAttributes }, samplingDecision) => {
157123
// There are situations where the Next.js Node.js server forwards requests for the Edge Runtime server (e.g. in
158124
// middleware) and this causes spans for Sentry ingest requests to be created. These are not exempt from our tracing
159125
// because we didn't get the chance to do `suppressTracing`, since this happens outside of userland.
@@ -178,7 +144,7 @@ export function init(options: NodeOptions): NodeClient | undefined {
178144

179145
// What we do in this glorious piece of code, is hoist any information about parameterized routes from spans emitted
180146
// by Next.js via the `next.route` attribute, up to the transaction by setting the http.route attribute.
181-
if (spanAttributes?.['next.route']) {
147+
if (typeof spanAttributes?.['next.route'] === 'string') {
182148
const rootSpan = getRootSpan(span);
183149
const rootSpanAttributes = spanToJSON(rootSpan).data;
184150

@@ -188,7 +154,9 @@ export function init(options: NodeOptions): NodeClient | undefined {
188154
(rootSpanAttributes?.[ATTR_HTTP_REQUEST_METHOD] || rootSpanAttributes?.[SEMATTRS_HTTP_METHOD]) &&
189155
!rootSpanAttributes?.[ATTR_HTTP_ROUTE]
190156
) {
191-
rootSpan.setAttribute(ATTR_HTTP_ROUTE, spanAttributes['next.route']);
157+
const route = spanAttributes['next.route'].replace(/\/route$/, '');
158+
rootSpan.updateName(route);
159+
rootSpan.setAttribute(ATTR_HTTP_ROUTE, route);
192160
}
193161
}
194162

0 commit comments

Comments
 (0)