From da2487eec0466b8db5cada2575e6f53297a7dcf6 Mon Sep 17 00:00:00 2001 From: Ryan Albrecht Date: Wed, 21 Jun 2023 11:44:52 -0700 Subject: [PATCH 1/3] fix(replay): Mark ui.slowClickDetected `clickCount` as optional (#8376) This field was added as part of v7.56.0, but `SlowClickFrameData` was created before that. Having `clickCount` be required breaks backwards compatibility, it should be optional. --- packages/replay/src/types/replayFrame.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/replay/src/types/replayFrame.ts b/packages/replay/src/types/replayFrame.ts index 379dbab91605..f3fb594829d3 100644 --- a/packages/replay/src/types/replayFrame.ts +++ b/packages/replay/src/types/replayFrame.ts @@ -91,7 +91,7 @@ interface SlowClickFrameData extends ClickFrameData { route?: string; timeAfterClickMs: number; endReason: string; - clickCount: number; + clickCount?: number; } export interface SlowClickFrame extends BaseBreadcrumbFrame { category: 'ui.slowClickDetected'; From ee4e37ef4dc2549daa8accfcd4a4a00221f8f4ea Mon Sep 17 00:00:00 2001 From: Lukas Stracke Date: Thu, 22 Jun 2023 13:30:48 +0200 Subject: [PATCH 2/3] fix(sveltekit): Only instrument SvelteKit `fetch` if the SDK client is valid (#8381) In the client-side SvelteKit fetch instrumentation, our previous type cast when retrieving the SDK client was wrong, causing us to not guard the fetch instrumentation correctly if the client was undefined. This fix adds an undefined check. fixes #8290 --- packages/sveltekit/src/client/load.ts | 25 +++++++++++---- packages/sveltekit/test/client/load.test.ts | 34 ++++++++++++++++++--- 2 files changed, 48 insertions(+), 11 deletions(-) diff --git a/packages/sveltekit/src/client/load.ts b/packages/sveltekit/src/client/load.ts index 1996523346e2..bbc184b6d3a0 100644 --- a/packages/sveltekit/src/client/load.ts +++ b/packages/sveltekit/src/client/load.ts @@ -3,7 +3,7 @@ import type { BaseClient } from '@sentry/core'; import { getCurrentHub, trace } from '@sentry/core'; import type { Breadcrumbs, BrowserTracing } from '@sentry/svelte'; import { captureException } from '@sentry/svelte'; -import type { ClientOptions, SanitizedRequestData } from '@sentry/types'; +import type { Client, ClientOptions, SanitizedRequestData } from '@sentry/types'; import { addExceptionMechanism, addNonEnumerableProperty, @@ -122,12 +122,14 @@ type SvelteKitFetch = LoadEvent['fetch']; * @returns a proxy of SvelteKit's fetch implementation */ function instrumentSvelteKitFetch(originalFetch: SvelteKitFetch): SvelteKitFetch { - const client = getCurrentHub().getClient() as BaseClient; + const client = getCurrentHub().getClient(); - const browserTracingIntegration = - client.getIntegrationById && (client.getIntegrationById('BrowserTracing') as BrowserTracing | undefined); - const breadcrumbsIntegration = - client.getIntegrationById && (client.getIntegrationById('Breadcrumbs') as Breadcrumbs | undefined); + if (!isValidClient(client)) { + return originalFetch; + } + + const browserTracingIntegration = client.getIntegrationById('BrowserTracing') as BrowserTracing | undefined; + const breadcrumbsIntegration = client.getIntegrationById('Breadcrumbs') as Breadcrumbs | undefined; const browserTracingOptions = browserTracingIntegration && browserTracingIntegration.options; @@ -270,3 +272,14 @@ function addFetchBreadcrumb( }, ); } + +type MaybeClientWithGetIntegrationsById = + | (Client & { getIntegrationById?: BaseClient['getIntegrationById'] }) + | undefined; + +type ClientWithGetIntegrationById = Required & + Exclude; + +function isValidClient(client: MaybeClientWithGetIntegrationsById): client is ClientWithGetIntegrationById { + return !!client && typeof client.getIntegrationById === 'function'; +} diff --git a/packages/sveltekit/test/client/load.test.ts b/packages/sveltekit/test/client/load.test.ts index b07e0c12108f..65b4cc1da3b1 100644 --- a/packages/sveltekit/test/client/load.test.ts +++ b/packages/sveltekit/test/client/load.test.ts @@ -52,6 +52,12 @@ const mockedGetIntegrationById = vi.fn(id => { return undefined; }); +const mockedGetClient = vi.fn(() => { + return { + getIntegrationById: mockedGetIntegrationById, + }; +}); + vi.mock('@sentry/core', async () => { const original = (await vi.importActual('@sentry/core')) as any; return { @@ -62,11 +68,7 @@ vi.mock('@sentry/core', async () => { }, getCurrentHub: () => { return { - getClient: () => { - return { - getIntegrationById: mockedGetIntegrationById, - }; - }, + getClient: mockedGetClient, getScope: () => { return { getSpan: () => { @@ -427,6 +429,28 @@ describe('wrapLoadWithSentry', () => { }); }); + it.each([ + ['is undefined', undefined], + ["doesn't have a `getClientById` method", {}], + ])("doesn't instrument fetch if the client %s", async (_, client) => { + // @ts-expect-error: we're mocking the client + mockedGetClient.mockImplementationOnce(() => client); + + async function load(_event: Parameters[0]): Promise> { + return { + msg: 'hi', + }; + } + const wrappedLoad = wrapLoadWithSentry(load); + + const originalFetch = MOCK_LOAD_ARGS.fetch; + await wrappedLoad(MOCK_LOAD_ARGS); + + expect(MOCK_LOAD_ARGS.fetch).toStrictEqual(originalFetch); + + expect(mockTrace).toHaveBeenCalledTimes(1); + }); + it('adds an exception mechanism', async () => { const addEventProcessorSpy = vi.spyOn(mockScope, 'addEventProcessor').mockImplementationOnce(callback => { void callback({}, { event_id: 'fake-event-id' }); From 54e091e7004c6b79cd94acc2d8a32c65632dbbd6 Mon Sep 17 00:00:00 2001 From: Lukas Stracke Date: Thu, 22 Jun 2023 14:37:44 +0200 Subject: [PATCH 3/3] fix(serverless): Export `autoDiscoverNodePerformanceMonitoringIntegrations` from SDK (#8382) When refactoring our `@sentry/tracing` package and exporting tracing related integrations from SDK packages, we apparently forgot to export `autoDiscoverNodePerformanceMonitoringIntegrations` from the Serverless SDK. This fix re-adds the export. --- packages/serverless/src/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/serverless/src/index.ts b/packages/serverless/src/index.ts index 284aef1331af..f6ae3a2b9184 100644 --- a/packages/serverless/src/index.ts +++ b/packages/serverless/src/index.ts @@ -15,6 +15,7 @@ export { Scope, addBreadcrumb, addGlobalEventProcessor, + autoDiscoverNodePerformanceMonitoringIntegrations, captureEvent, captureException, captureMessage,