Skip to content

Commit dff83da

Browse files
committed
feat(sveltekit): Add option to control handling of unknown server routes
1 parent acfd50c commit dff83da

File tree

2 files changed

+56
-14
lines changed

2 files changed

+56
-14
lines changed

packages/sveltekit/src/server/handle.ts

Lines changed: 41 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,24 @@ import type { Handle, ResolveOptions } from '@sveltejs/kit';
77

88
import { getTracePropagationData } from './utils';
99

10+
export type SentryHandleOptions = {
11+
/**
12+
* Controls whether the SDK should capture errors and traces in requests that don't belong to a
13+
* route defined in your SvelteKit application.
14+
*
15+
* By default, this option is set to `false` to reduce noise (e.g. bots sending random requests to your server).
16+
*
17+
* Set this option to `true` if you want to monitor requests events without a route. This might be useful in certain
18+
* scenarios, for instance if you registered other handlers that handle these requests.
19+
* If you set this option, you might want adjust the the transaction name in the `beforeSendTransaction`
20+
* callback of your server-side `Sentry.init` options. You can also use `beforeSendTransaction` to filter out
21+
* transactions that you still don't want to be sent to Sentry.
22+
*
23+
* @default false
24+
*/
25+
handleUnknownRoutes?: boolean;
26+
};
27+
1028
function sendErrorToSentry(e: unknown): unknown {
1129
// In case we have a primitive, wrap it in the equivalent wrapper class (string -> String, etc.) so that we can
1230
// store a seen flag on it.
@@ -59,33 +77,42 @@ export const transformPageChunk: NonNullable<ResolveOptions['transformPageChunk'
5977
* // export const handle = sequence(sentryHandle(), yourCustomHandler);
6078
* ```
6179
*/
62-
export function sentryHandle(): Handle {
80+
export function sentryHandle(handlerOptions?: SentryHandleOptions): Handle {
81+
const options = {
82+
handleUnknownRoutes: false,
83+
...handlerOptions,
84+
};
85+
86+
const sentryRequestHandler: Handle = input => {
87+
// if there is an active transaction, we know that this handle call is nested and hence
88+
// we don't create a new domain for it. If we created one, nested server calls would
89+
// create new transactions instead of adding a child span to the currently active span.
90+
if (getCurrentHub().getScope().getSpan()) {
91+
return instrumentHandle(input, options);
92+
}
93+
return runWithAsyncContext(() => {
94+
return instrumentHandle(input, options);
95+
});
96+
};
97+
6398
return sentryRequestHandler;
6499
}
65100

66-
const sentryRequestHandler: Handle = input => {
67-
// if there is an active transaction, we know that this handle call is nested and hence
68-
// we don't create a new domain for it. If we created one, nested server calls would
69-
// create new transactions instead of adding a child span to the currently active span.
70-
if (getCurrentHub().getScope().getSpan()) {
71-
return instrumentHandle(input);
101+
function instrumentHandle({ event, resolve }: Parameters<Handle>[0], options: SentryHandleOptions): ReturnType<Handle> {
102+
if (!event.route?.id && !options.handleUnknownRoutes) {
103+
return resolve(event);
72104
}
73-
return runWithAsyncContext(() => {
74-
return instrumentHandle(input);
75-
});
76-
};
77105

78-
function instrumentHandle({ event, resolve }: Parameters<Handle>[0]): ReturnType<Handle> {
79106
const { traceparentData, dynamicSamplingContext } = getTracePropagationData(event);
80107

81108
return trace(
82109
{
83110
op: 'http.server',
84-
name: `${event.request.method} ${event.route.id}`,
111+
name: `${event.request.method} ${event.route?.id || event.url.pathname}`,
85112
status: 'ok',
86113
...traceparentData,
87114
metadata: {
88-
source: 'route',
115+
source: event.route.id ? 'route' : 'url',
89116
dynamicSamplingContext: traceparentData && !dynamicSamplingContext ? {} : dynamicSamplingContext,
90117
},
91118
},

packages/sveltekit/test/server/handle.test.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,21 @@ describe('handleSentry', () => {
305305
expect(mockResolve).toHaveBeenCalledTimes(1);
306306
expect(mockResolve).toHaveBeenCalledWith(event, { transformPageChunk: expect.any(Function) });
307307
});
308+
309+
it("doesn't create a transaction if there's no route", async () => {
310+
let ref: any = undefined;
311+
client.on('finishTransaction', (transaction: Transaction) => {
312+
ref = transaction;
313+
});
314+
315+
try {
316+
await sentryHandle()({ event: mockEvent({ route: undefined }), resolve: resolve(type, isError) });
317+
} catch {
318+
//
319+
}
320+
321+
expect(ref).toBeUndefined();
322+
});
308323
});
309324
});
310325

0 commit comments

Comments
 (0)