Skip to content

Commit f865ebd

Browse files
committed
fix(v8/svelte): Guard component tracking beforeUpdate call
start ci
1 parent b6a4a4a commit f865ebd

File tree

5 files changed

+26
-34
lines changed

5 files changed

+26
-34
lines changed

packages/svelte/src/config.ts

+11-18
Original file line numberDiff line numberDiff line change
@@ -22,30 +22,23 @@ export function withSentryConfig(
2222
const mergedOptions = {
2323
...DEFAULT_SENTRY_OPTIONS,
2424
...sentryOptions,
25+
componentTracking: {
26+
...DEFAULT_SENTRY_OPTIONS.componentTracking,
27+
...(sentryOptions && sentryOptions.componentTracking),
28+
},
2529
};
2630

2731
const originalPreprocessors = getOriginalPreprocessorArray(originalConfig);
2832

29-
// Map is insertion-order-preserving. It's important to add preprocessors
30-
// to this map in the right order we want to see them being executed.
31-
// see: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map
32-
const sentryPreprocessors = new Map<string, SentryPreprocessorGroup>();
33-
34-
const shouldTrackComponents = mergedOptions.componentTracking && mergedOptions.componentTracking.trackComponents;
35-
if (shouldTrackComponents) {
36-
const firstPassPreproc: SentryPreprocessorGroup = componentTrackingPreprocessor(mergedOptions.componentTracking);
37-
sentryPreprocessors.set(firstPassPreproc.sentryId || '', firstPassPreproc);
33+
// Bail if users already added the preprocessor
34+
if (originalPreprocessors.find((p: PreprocessorGroup) => !!(p as SentryPreprocessorGroup).sentryId)) {
35+
return originalConfig;
3836
}
3937

40-
// We prioritize user-added preprocessors, so we don't insert sentry processors if they
41-
// have already been added by users.
42-
originalPreprocessors.forEach((p: SentryPreprocessorGroup) => {
43-
if (p.sentryId) {
44-
sentryPreprocessors.delete(p.sentryId);
45-
}
46-
});
47-
48-
const mergedPreprocessors = [...sentryPreprocessors.values(), ...originalPreprocessors];
38+
const mergedPreprocessors = [...originalPreprocessors];
39+
if (mergedOptions.componentTracking.trackComponents) {
40+
mergedPreprocessors.unshift(componentTrackingPreprocessor(mergedOptions.componentTracking));
41+
}
4942

5043
return {
5144
...originalConfig,

packages/svelte/src/constants.ts

-5
This file was deleted.

packages/svelte/src/performance.ts

+11-6
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,7 @@ import { SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '@sentry/browser';
22
import type { Span } from '@sentry/core';
33
import { afterUpdate, beforeUpdate, onMount } from 'svelte';
44

5-
import { startInactiveSpan } from '@sentry/core';
6-
import { DEFAULT_COMPONENT_NAME, UI_SVELTE_INIT, UI_SVELTE_UPDATE } from './constants';
5+
import { logger, startInactiveSpan } from '@sentry/core';
76
import type { TrackComponentOptions } from './types';
87

98
const defaultTrackComponentOptions: {
@@ -29,21 +28,27 @@ export function trackComponent(options?: TrackComponentOptions): void {
2928

3029
const customComponentName = mergedOptions.componentName;
3130

32-
const componentName = `<${customComponentName || DEFAULT_COMPONENT_NAME}>`;
31+
const componentName = `<${customComponentName || 'Svelte Component'}>`;
3332

3433
if (mergedOptions.trackInit) {
3534
recordInitSpan(componentName);
3635
}
3736

3837
if (mergedOptions.trackUpdates) {
39-
recordUpdateSpans(componentName);
38+
try {
39+
recordUpdateSpans(componentName);
40+
} catch {
41+
logger.warn(
42+
"Cannot track component updates. This is likely because you're using Svelte 5 in Runes mode. Set `trackUpdates: false` in `withSentryConfig` or `trackComponent` to disable this warning.",
43+
);
44+
}
4045
}
4146
}
4247

4348
function recordInitSpan(componentName: string): void {
4449
const initSpan = startInactiveSpan({
4550
onlyIfParent: true,
46-
op: UI_SVELTE_INIT,
51+
op: 'ui.svelte.init',
4752
name: componentName,
4853
attributes: { [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ui.svelte' },
4954
});
@@ -58,7 +63,7 @@ function recordUpdateSpans(componentName: string): void {
5863
beforeUpdate(() => {
5964
updateSpan = startInactiveSpan({
6065
onlyIfParent: true,
61-
op: UI_SVELTE_UPDATE,
66+
op: 'ui.svelte.update',
6267
name: componentName,
6368
attributes: { [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ui.svelte' },
6469
});

packages/svelte/test/config.test.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ describe('withSentryConfig', () => {
6060

6161
const wrappedConfig = withSentryConfig(originalConfig);
6262

63-
expect(wrappedConfig).toEqual({ ...originalConfig, preprocess: [sentryPreproc] });
63+
expect(wrappedConfig).toEqual({ ...originalConfig });
6464
});
6565

6666
it('handles multiple wraps correctly by only adding our preprocessors once', () => {

packages/svelte/test/performance.test.ts

+3-4
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import { getClient, getCurrentScope, getIsolationScope, init, startSpan } from '
99

1010
import type { TransactionEvent } from '@sentry/core';
1111

12-
// @ts-expect-error svelte import
1312
import DummyComponent from './components/Dummy.svelte';
1413

1514
const PUBLIC_DSN = 'https://username@domain/123';
@@ -32,7 +31,7 @@ describe('Sentry.trackComponent()', () => {
3231

3332
init({
3433
dsn: PUBLIC_DSN,
35-
enableTracing: true,
34+
tracesSampleRate: 1.0,
3635
beforeSendTransaction,
3736
});
3837
});
@@ -220,7 +219,7 @@ describe('Sentry.trackComponent()', () => {
220219
expect(transaction.spans![1]?.description).toEqual('<CustomComponentName>');
221220
});
222221

223-
it("doesn't do anything, if there's no ongoing transaction", async () => {
222+
it("doesn't do anything, if there's no ongoing parent span", async () => {
224223
render(DummyComponent, {
225224
props: { options: { componentName: 'CustomComponentName' } },
226225
});
@@ -230,7 +229,7 @@ describe('Sentry.trackComponent()', () => {
230229
expect(transactions).toHaveLength(0);
231230
});
232231

233-
it("doesn't record update spans, if there's no ongoing root span at that time", async () => {
232+
it("doesn't record update spans, if there's no ongoing parent span at that time", async () => {
234233
const component = startSpan({ name: 'outer' }, span => {
235234
expect(span).toBeDefined();
236235

0 commit comments

Comments
 (0)