Skip to content

Commit 8c0762e

Browse files
committed
check for active txn instead of active domain
1 parent 6bac31b commit 8c0762e

File tree

2 files changed

+53
-7
lines changed

2 files changed

+53
-7
lines changed

packages/sveltekit/src/server/handle.ts

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/* eslint-disable @sentry-internal/sdk/no-optional-chaining */
2-
import type { Span } from '@sentry/core';
2+
import { getCurrentHub, Span } from '@sentry/core';
33
import { getActiveTransaction, trace } from '@sentry/core';
44
import { captureException } from '@sentry/node';
55
import {
@@ -65,16 +65,18 @@ export const transformPageChunk: NonNullable<ResolveOptions['transformPageChunk'
6565
* ```
6666
*/
6767
export const sentryHandle: Handle = input => {
68-
// @ts-ignore domain.active exists if there is an active domain, TS just doesn't know
69-
if (domain.active) {
70-
return handleInDomain(input);
68+
// if there is an active transaction, we know that this handle call is nested and hence
69+
// we don't create a new domain for it. If we created one, nested server calls would
70+
// create new transactions instead of adding a child span to the currently active span.
71+
if (getCurrentHub().getScope().getSpan()) {
72+
return instrumentHandle(input);
7173
}
7274
return domain.create().bind(() => {
73-
return handleInDomain(input);
75+
return instrumentHandle(input);
7476
})();
7577
};
7678

77-
function handleInDomain({ event, resolve }: Parameters<Handle>[0]): ReturnType<Handle> {
79+
function instrumentHandle({ event, resolve }: Parameters<Handle>[0]): ReturnType<Handle> {
7880
const sentryTraceHeader = event.request.headers.get('sentry-trace');
7981
const baggageHeader = event.request.headers.get('baggage');
8082
const traceparentData = sentryTraceHeader ? extractTraceparentData(sentryTraceHeader) : undefined;

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

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ describe('handleSentry', () => {
129129
expect(response).toEqual(mockResponse);
130130
});
131131

132-
it('creates a transaction', async () => {
132+
it("creates a transaction if there's no active span", async () => {
133133
let ref: any = undefined;
134134
client.on('finishTransaction', (transaction: Transaction) => {
135135
ref = transaction;
@@ -149,6 +149,50 @@ describe('handleSentry', () => {
149149
expect(ref.metadata.source).toEqual('route');
150150

151151
expect(ref.endTimestamp).toBeDefined();
152+
expect(ref.spanRecorder.spans).toHaveLength(1);
153+
});
154+
155+
it('creates a child span for nested server calls (i.e. if there is an active span)', async () => {
156+
let ref: any = undefined;
157+
let txnCount = 0;
158+
client.on('finishTransaction', (transaction: Transaction) => {
159+
ref = transaction;
160+
++txnCount;
161+
});
162+
163+
try {
164+
await sentryHandle({
165+
event: mockEvent(),
166+
resolve: async _ => {
167+
// simulateing a nested load call:
168+
await sentryHandle({
169+
event: mockEvent({ route: { id: 'api/users/details/[id]' } }),
170+
resolve: resolve(type, isError),
171+
});
172+
return mockResponse;
173+
},
174+
});
175+
} catch (e) {
176+
//
177+
}
178+
179+
expect(txnCount).toEqual(1);
180+
expect(ref).toBeDefined();
181+
182+
expect(ref.name).toEqual('GET /users/[id]');
183+
expect(ref.op).toEqual('http.server');
184+
expect(ref.status).toEqual(isError ? 'internal_error' : 'ok');
185+
expect(ref.metadata.source).toEqual('route');
186+
187+
expect(ref.endTimestamp).toBeDefined();
188+
189+
expect(ref.spanRecorder.spans).toHaveLength(2);
190+
expect(ref.spanRecorder.spans).toEqual(
191+
expect.arrayContaining([
192+
expect.objectContaining({ op: 'http.server', description: 'GET /users/[id]' }),
193+
expect.objectContaining({ op: 'http.server', description: 'GET api/users/details/[id]' }),
194+
]),
195+
);
152196
});
153197

154198
it('creates a transaction from sentry-trace header', async () => {

0 commit comments

Comments
 (0)