|
1 | 1 | /* eslint-disable @sentry-internal/sdk/no-optional-chaining */
|
2 | 2 | import type { Span } from '@sentry/core';
|
3 |
| -import { getActiveTransaction, trace } from '@sentry/core'; |
| 3 | +import { getActiveTransaction, getCurrentHub, trace } from '@sentry/core'; |
4 | 4 | import { captureException } from '@sentry/node';
|
5 | 5 | import {
|
6 | 6 | addExceptionMechanism,
|
@@ -64,32 +64,42 @@ export const transformPageChunk: NonNullable<ResolveOptions['transformPageChunk'
|
64 | 64 | * // export const handle = sequence(sentryHandle, yourCustomHandle);
|
65 | 65 | * ```
|
66 | 66 | */
|
67 |
| -export const sentryHandle: Handle = ({ event, resolve }) => { |
| 67 | +export const sentryHandle: Handle = 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); |
| 73 | + } |
68 | 74 | return domain.create().bind(() => {
|
69 |
| - const sentryTraceHeader = event.request.headers.get('sentry-trace'); |
70 |
| - const baggageHeader = event.request.headers.get('baggage'); |
71 |
| - const traceparentData = sentryTraceHeader ? extractTraceparentData(sentryTraceHeader) : undefined; |
72 |
| - const dynamicSamplingContext = baggageHeaderToDynamicSamplingContext(baggageHeader); |
73 |
| - |
74 |
| - return trace( |
75 |
| - { |
76 |
| - op: 'http.server', |
77 |
| - name: `${event.request.method} ${event.route.id}`, |
78 |
| - status: 'ok', |
79 |
| - ...traceparentData, |
80 |
| - metadata: { |
81 |
| - source: 'route', |
82 |
| - dynamicSamplingContext: traceparentData && !dynamicSamplingContext ? {} : dynamicSamplingContext, |
83 |
| - }, |
84 |
| - }, |
85 |
| - async (span?: Span) => { |
86 |
| - const res = await resolve(event, { transformPageChunk }); |
87 |
| - if (span) { |
88 |
| - span.setHttpStatus(res.status); |
89 |
| - } |
90 |
| - return res; |
91 |
| - }, |
92 |
| - sendErrorToSentry, |
93 |
| - ); |
| 75 | + return instrumentHandle(input); |
94 | 76 | })();
|
95 | 77 | };
|
| 78 | + |
| 79 | +function instrumentHandle({ event, resolve }: Parameters<Handle>[0]): ReturnType<Handle> { |
| 80 | + const sentryTraceHeader = event.request.headers.get('sentry-trace'); |
| 81 | + const baggageHeader = event.request.headers.get('baggage'); |
| 82 | + const traceparentData = sentryTraceHeader ? extractTraceparentData(sentryTraceHeader) : undefined; |
| 83 | + const dynamicSamplingContext = baggageHeaderToDynamicSamplingContext(baggageHeader); |
| 84 | + |
| 85 | + return trace( |
| 86 | + { |
| 87 | + op: 'http.server', |
| 88 | + name: `${event.request.method} ${event.route.id}`, |
| 89 | + status: 'ok', |
| 90 | + ...traceparentData, |
| 91 | + metadata: { |
| 92 | + source: 'route', |
| 93 | + dynamicSamplingContext: traceparentData && !dynamicSamplingContext ? {} : dynamicSamplingContext, |
| 94 | + }, |
| 95 | + }, |
| 96 | + async (span?: Span) => { |
| 97 | + const res = await resolve(event, { transformPageChunk }); |
| 98 | + if (span) { |
| 99 | + span.setHttpStatus(res.status); |
| 100 | + } |
| 101 | + return res; |
| 102 | + }, |
| 103 | + sendErrorToSentry, |
| 104 | + ); |
| 105 | +} |
0 commit comments