-
-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Expand file tree
/
Copy pathsvelteKitSpans.ts
More file actions
97 lines (88 loc) · 3.54 KB
/
svelteKitSpans.ts
File metadata and controls
97 lines (88 loc) · 3.54 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
import type { Integration, SpanJSON, SpanOrigin, StreamedSpanJSON } from '@sentry/core';
import {
safeSetSpanJSONAttributes,
SEMANTIC_ATTRIBUTE_SENTRY_OP,
SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,
} from '@sentry/core';
/**
* A small integration that preprocesses spans so that SvelteKit-generated spans
* (via Kit's tracing feature since 2.31.0) get the correct Sentry attributes
* and data.
*/
export function svelteKitSpansIntegration(): Integration {
return {
name: 'SvelteKitSpansEnhancement',
// Using preprocessEvent to ensure the processing happens before user-configured
// event processors are executed
preprocessEvent(event) {
// only iterate over the spans if the root span was emitted by SvelteKit
// TODO: Right now, we can't optimize this to only check traces with a kit-emitted root span
// this is because in Cloudflare, the kit-emitted root span is missing but our cloudflare
// SDK emits the http.server span.
if (event.type === 'transaction') {
event.spans?.forEach(_enhanceKitSpan);
}
},
processSpan(span) {
_enhanceKitSpanStreamed(span);
},
};
}
/**
* Adds sentry-specific attributes and data to a span emitted by SvelteKit's native tracing (since 2.31.0)
* @exported for testing
*/
export function _enhanceKitSpan(span: SpanJSON): void {
const { op, origin } = _getKitSpanEnhancement(span.description);
const previousOp = span.op || span.data[SEMANTIC_ATTRIBUTE_SENTRY_OP];
const previousOrigin = span.origin || span.data[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN];
if (!previousOp && op) {
span.op = op;
span.data[SEMANTIC_ATTRIBUTE_SENTRY_OP] = op;
}
if ((!previousOrigin || previousOrigin === 'manual') && origin) {
span.origin = origin;
span.data[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN] = origin;
}
}
/**
* Streaming-mode counterpart of {@link _enhanceKitSpan} operating on {@link StreamedSpanJSON}.
* @exported for testing
*/
export function _enhanceKitSpanStreamed(span: StreamedSpanJSON): void {
const { op, origin } = _getKitSpanEnhancement(span.name);
const previousOrigin = span.attributes?.[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN] as SpanOrigin | undefined;
if (op) {
safeSetSpanJSONAttributes(span, { [SEMANTIC_ATTRIBUTE_SENTRY_OP]: op });
}
if (previousOrigin === 'manual' && origin) {
// `safeSetSpanJSONAttributes` skips existing keys, so overwrite the 'manual' sentinel directly.
span.attributes![SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN] = origin;
} else {
safeSetSpanJSONAttributes(span, { [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: origin });
}
}
function _getKitSpanEnhancement(spanName: string | undefined): {
op?: string;
origin?: SpanOrigin;
} {
switch (spanName) {
case 'sveltekit.resolve':
return { op: 'function.sveltekit.resolve', origin: 'auto.http.sveltekit' };
case 'sveltekit.load':
return { op: 'function.sveltekit.load', origin: 'auto.function.sveltekit.load' };
case 'sveltekit.form_action':
return { op: 'function.sveltekit.form_action', origin: 'auto.function.sveltekit.action' };
case 'sveltekit.remote.call':
return { op: 'function.sveltekit.remote', origin: 'auto.rpc.sveltekit.remote' };
case 'sveltekit.handle.root':
// We don't want to overwrite the root handle span at this point since
// we already enhance the root span in our `sentryHandle` hook.
return {};
default:
if (spanName?.startsWith('sveltekit.handle.sequenced.')) {
return { op: 'function.sveltekit.handle', origin: 'auto.function.sveltekit.handle' };
}
return {};
}
}