diff --git a/.size-limit.js b/.size-limit.js index 761905a49ef3..7feee4373586 100644 --- a/.size-limit.js +++ b/.size-limit.js @@ -82,7 +82,7 @@ module.exports = [ path: 'packages/browser/build/npm/esm/prod/index.js', import: createImport('init', 'browserTracingIntegration', 'replayIntegration', 'replayCanvasIntegration'), gzip: true, - limit: '85.55 KB', + limit: '86 KB', }, { name: '@sentry/browser (incl. Tracing, Replay, Feedback)', @@ -184,7 +184,7 @@ module.exports = [ name: 'CDN Bundle (incl. Tracing)', path: createCDNPath('bundle.tracing.min.js'), gzip: true, - limit: '43 KB', + limit: '44 KB', }, { name: 'CDN Bundle (incl. Logs, Metrics)', diff --git a/dev-packages/browser-integration-tests/suites/public-api/sendDefaultPii/overrideIp/init.js b/dev-packages/browser-integration-tests/suites/public-api/sendDefaultPii/overrideIp/init.js new file mode 100644 index 000000000000..957b42442255 --- /dev/null +++ b/dev-packages/browser-integration-tests/suites/public-api/sendDefaultPii/overrideIp/init.js @@ -0,0 +1,16 @@ +import * as Sentry from '@sentry/browser'; + +window.Sentry = Sentry; + +Sentry.init({ + dsn: 'https://public@dsn.ingest.sentry.io/1337', + tracesSampleRate: 1, + sendDefaultPii: false, + _metadata: { + sdk: { + settings: { + infer_ip: 'auto', + }, + }, + }, +}); diff --git a/dev-packages/browser-integration-tests/suites/public-api/sendDefaultPii/overrideIp/subject.js b/dev-packages/browser-integration-tests/suites/public-api/sendDefaultPii/overrideIp/subject.js new file mode 100644 index 000000000000..1b632e0a9289 --- /dev/null +++ b/dev-packages/browser-integration-tests/suites/public-api/sendDefaultPii/overrideIp/subject.js @@ -0,0 +1 @@ +Sentry.captureException(new Error('woot')); diff --git a/dev-packages/browser-integration-tests/suites/public-api/sendDefaultPii/overrideIp/test.ts b/dev-packages/browser-integration-tests/suites/public-api/sendDefaultPii/overrideIp/test.ts new file mode 100644 index 000000000000..2b55c098bbb4 --- /dev/null +++ b/dev-packages/browser-integration-tests/suites/public-api/sendDefaultPii/overrideIp/test.ts @@ -0,0 +1,12 @@ +import { expect } from '@playwright/test'; +import { sentryTest } from '../../../../utils/fixtures'; +import { envelopeRequestParser, waitForErrorRequestOnUrl } from '../../../../utils/helpers'; + +sentryTest( + 'overrides IP inference by explicitly passing sdk.settings.infer_ip to "auto"', + async ({ getLocalTestUrl, page }) => { + const url = await getLocalTestUrl({ testDir: __dirname }); + const eventData = await envelopeRequestParser(await waitForErrorRequestOnUrl(page, url)); + expect(eventData.sdk?.settings?.infer_ip).toBe('auto'); + }, +); diff --git a/packages/browser/test/client.test.ts b/packages/browser/test/client.test.ts index d99e45984f0a..27135b4fc9a9 100644 --- a/packages/browser/test/client.test.ts +++ b/packages/browser/test/client.test.ts @@ -148,7 +148,7 @@ describe('applyDefaultOptions', () => { describe('SDK metadata', () => { describe('sdk.settings', () => { - it('sets infer_ipto "never" by default', () => { + it('sets infer_ip to "never" by default', () => { const options = getDefaultBrowserClientOptions({}); const client = new BrowserClient(options); @@ -233,5 +233,30 @@ describe('SDK metadata', () => { expect(client.getOptions()._metadata?.sdk?.name).toBe('sentry.javascript.angular'); }); + + it('preserves passed-in partial SDK metadata', () => { + const options = getDefaultBrowserClientOptions({ + _metadata: { + sdk: { + settings: { + infer_ip: 'auto', + }, + }, + }, + // Usually, this would cause infer_ip to be set to 'never' + // but we're passing it in explicitly, so it should be preserved + sendDefaultPii: false, + }); + const client = new BrowserClient(options); + + expect(client.getOptions()._metadata?.sdk).toEqual({ + name: 'sentry.javascript.browser', + version: expect.any(String), + packages: [{ name: 'npm:@sentry/browser', version: expect.any(String) }], + settings: { + infer_ip: 'auto', + }, + }); + }); }); }); diff --git a/packages/core/src/utils/sdkMetadata.ts b/packages/core/src/utils/sdkMetadata.ts index 714a022689e3..e7755537551a 100644 --- a/packages/core/src/utils/sdkMetadata.ts +++ b/packages/core/src/utils/sdkMetadata.ts @@ -15,18 +15,14 @@ import { SDK_VERSION } from '../utils/version'; * @param names list of package names */ export function applySdkMetadata(options: CoreOptions, name: string, names = [name], source = 'npm'): void { - const metadata = options._metadata || {}; + const sdk = ((options._metadata = options._metadata || {}).sdk = options._metadata.sdk || {}); - if (!metadata.sdk) { - metadata.sdk = { - name: `sentry.javascript.${name}`, - packages: names.map(name => ({ - name: `${source}:@sentry/${name}`, - version: SDK_VERSION, - })), + if (!sdk.name) { + sdk.name = `sentry.javascript.${name}`; + sdk.packages = names.map(name => ({ + name: `${source}:@sentry/${name}`, version: SDK_VERSION, - }; + })); + sdk.version = SDK_VERSION; } - - options._metadata = metadata; } diff --git a/packages/core/test/lib/utils/sdkMetadata.test.ts b/packages/core/test/lib/utils/sdkMetadata.test.ts new file mode 100644 index 000000000000..ee502267e673 --- /dev/null +++ b/packages/core/test/lib/utils/sdkMetadata.test.ts @@ -0,0 +1,143 @@ +import { describe, expect, it } from 'vitest'; +import { applySdkMetadata } from '../../../src'; + +describe('applySdkMetadata', () => { + it('applies a custom SDK name', () => { + const options = { + dsn: '123', + }; + + applySdkMetadata(options, 'angular'); + + expect(options).toEqual({ + _metadata: { + sdk: { + name: 'sentry.javascript.angular', + packages: [ + { + name: 'npm:@sentry/angular', + version: expect.any(String), + }, + ], + version: expect.any(String), + }, + }, + dsn: '123', + }); + }); + + it('attaches multiple packages if names is passed in', () => { + const options = { + dsn: '123', + }; + + applySdkMetadata(options, 'angular', ['angular', 'browser']); + + expect(options).toEqual({ + _metadata: { + sdk: { + name: 'sentry.javascript.angular', + packages: [ + { name: 'npm:@sentry/angular', version: expect.any(String) }, + { name: 'npm:@sentry/browser', version: expect.any(String) }, + ], + version: expect.any(String), + }, + }, + dsn: '123', + }); + }); + + it('sets the source if source is passed in', () => { + const options = { + dsn: '123', + }; + + applySdkMetadata(options, 'angular', ['angular', 'browser'], 'cdn'); + + expect(options).toEqual({ + _metadata: { + sdk: { + name: 'sentry.javascript.angular', + packages: [ + { name: 'cdn:@sentry/angular', version: expect.any(String) }, + { name: 'cdn:@sentry/browser', version: expect.any(String) }, + ], + version: expect.any(String), + }, + }, + dsn: '123', + }); + }); + + it('preserves existing SDK metadata if already set', () => { + const options = { + dsn: '123', + _metadata: { + sdk: { + name: 'sentry.javascript.react', + }, + }, + }; + + applySdkMetadata(options, 'angular', ['angular', 'browser'], 'cdn'); + + expect(options).toEqual({ + _metadata: { + sdk: { + name: 'sentry.javascript.react', + }, + }, + dsn: '123', + }); + }); + + it('merges existing SDK metadata with default values', () => { + const options = { + dsn: '123', + _metadata: { + sdk: { + settings: { + infer_ip: 'auto' as const, + }, + }, + }, + }; + + applySdkMetadata(options, 'angular'); + + expect(options).toEqual({ + _metadata: { + sdk: { + name: 'sentry.javascript.angular', + packages: [{ name: 'npm:@sentry/angular', version: expect.any(String) }], + version: expect.any(String), + settings: { + infer_ip: 'auto' as const, + }, + }, + }, + dsn: '123', + }); + }); + + it('handles empty metadata object', () => { + const options = { + dsn: '123', + _metadata: {}, + }; + + applySdkMetadata(options, 'angular'); + + expect(options).toEqual({ + _metadata: { + sdk: { + name: 'sentry.javascript.angular', + packages: [{ name: 'npm:@sentry/angular', version: expect.any(String) }], + version: expect.any(String), + }, + }, + dsn: '123', + }); + }); +});