diff --git a/packages/browser/src/transports/base.ts b/packages/browser/src/transports/base.ts index 8fd960593ac5..1f02f3f32996 100644 --- a/packages/browser/src/transports/base.ts +++ b/packages/browser/src/transports/base.ts @@ -24,14 +24,10 @@ import { import { sendReport } from './utils'; -const CATEGORY_MAPPING: { - [key in SentryRequestType]: string; -} = { - event: 'error', - transaction: 'transaction', - session: 'session', - attachment: 'attachment', -}; +function requestTypeToCategory(ty: SentryRequestType): string { + const tyStr = ty as string; + return tyStr === 'event' ? 'error' : tyStr; +} const global = getGlobalObject(); @@ -93,7 +89,7 @@ export abstract class BaseTransport implements Transport { // We could use nested maps, but it's much easier to read and type this way. // A correct type for map-based implementation if we want to go that route // would be `Partial>>>` - const key = `${CATEGORY_MAPPING[category]}:${reason}`; + const key = `${requestTypeToCategory(category)}:${reason}`; logger.log(`Adding outcome: ${key}`); this._outcomes[key] = (this._outcomes[key] ?? 0) + 1; } @@ -180,7 +176,7 @@ export abstract class BaseTransport implements Transport { * Gets the time that given category is disabled until for rate limiting */ protected _disabledUntil(requestType: SentryRequestType): Date { - const category = CATEGORY_MAPPING[requestType]; + const category = requestTypeToCategory(requestType); return this._rateLimits[category] || this._rateLimits.all; } diff --git a/packages/hub/src/session.ts b/packages/hub/src/session.ts index 654754d2aee7..1bca2377cdd5 100644 --- a/packages/hub/src/session.ts +++ b/packages/hub/src/session.ts @@ -125,12 +125,12 @@ export class Session implements SessionInterface { errors: this.errors, did: typeof this.did === 'number' || typeof this.did === 'string' ? `${this.did}` : undefined, duration: this.duration, - attrs: dropUndefinedKeys({ + attrs: { release: this.release, environment: this.environment, ip_address: this.ipAddress, user_agent: this.userAgent, - }), + }, }); } } diff --git a/packages/utils/src/dsn.ts b/packages/utils/src/dsn.ts index 011472e35234..89752e6ccfdf 100644 --- a/packages/utils/src/dsn.ts +++ b/packages/utils/src/dsn.ts @@ -1,5 +1,6 @@ import { DsnComponents, DsnLike, DsnProtocol } from '@sentry/types'; +import { isDebugBuild } from './env'; import { SentryError } from './error'; /** Regular expression used to parse a Dsn. */ @@ -102,22 +103,25 @@ export class Dsn implements DsnComponents { /** Validates this Dsn and throws on error. */ private _validate(): void { - ['protocol', 'publicKey', 'host', 'projectId'].forEach(component => { - if (!this[component as keyof DsnComponents]) { - throw new SentryError(`${ERROR_MESSAGE}: ${component} missing`); + // we only validate in debug mode. This will fail later anyways. + if (isDebugBuild()) { + ['protocol', 'publicKey', 'host', 'projectId'].forEach(component => { + if (!this[component as keyof DsnComponents]) { + throw new SentryError(`${ERROR_MESSAGE}: ${component} missing`); + } + }); + + if (!this.projectId.match(/^\d+$/)) { + throw new SentryError(`${ERROR_MESSAGE}: Invalid projectId ${this.projectId}`); } - }); - if (!this.projectId.match(/^\d+$/)) { - throw new SentryError(`${ERROR_MESSAGE}: Invalid projectId ${this.projectId}`); - } - - if (this.protocol !== 'http' && this.protocol !== 'https') { - throw new SentryError(`${ERROR_MESSAGE}: Invalid protocol ${this.protocol}`); - } + if (this.protocol !== 'http' && this.protocol !== 'https') { + throw new SentryError(`${ERROR_MESSAGE}: Invalid protocol ${this.protocol}`); + } - if (this.port && isNaN(parseInt(this.port, 10))) { - throw new SentryError(`${ERROR_MESSAGE}: Invalid port ${this.port}`); + if (this.port && isNaN(parseInt(this.port, 10))) { + throw new SentryError(`${ERROR_MESSAGE}: Invalid port ${this.port}`); + } } } } diff --git a/packages/utils/test/dsn.test.ts b/packages/utils/test/dsn.test.ts index 534346cf0067..804fbe41536c 100644 --- a/packages/utils/test/dsn.test.ts +++ b/packages/utils/test/dsn.test.ts @@ -1,6 +1,12 @@ +import { isDebugBuild } from '@sentry/utils'; + import { Dsn } from '../src/dsn'; import { SentryError } from '../src/error'; +function testIf(condition: boolean): jest.It { + return condition ? test : test.skip; +} + describe('Dsn', () => { describe('fromComponents', () => { test('applies all components', () => { @@ -37,7 +43,7 @@ describe('Dsn', () => { expect(dsn.projectId).toBe('123'); }); - test('throws for missing components', () => { + testIf(isDebugBuild())('throws for missing components', () => { expect( () => new Dsn({ @@ -76,7 +82,7 @@ describe('Dsn', () => { ).toThrow(SentryError); }); - test('throws for invalid components', () => { + testIf(isDebugBuild())('throws for invalid components', () => { expect( () => new Dsn({ @@ -144,18 +150,18 @@ describe('Dsn', () => { expect(dsn.projectId).toBe('321'); }); - test('throws when provided invalid Dsn', () => { + testIf(isDebugBuild())('throws when provided invalid Dsn', () => { expect(() => new Dsn('some@random.dsn')).toThrow(SentryError); }); - test('throws without mandatory fields', () => { + testIf(isDebugBuild())('throws without mandatory fields', () => { expect(() => new Dsn('://abc@sentry.io/123')).toThrow(SentryError); expect(() => new Dsn('https://@sentry.io/123')).toThrow(SentryError); expect(() => new Dsn('https://abc@123')).toThrow(SentryError); expect(() => new Dsn('https://abc@sentry.io/')).toThrow(SentryError); }); - test('throws for invalid fields', () => { + testIf(isDebugBuild())('throws for invalid fields', () => { expect(() => new Dsn('httpx://abc@sentry.io/123')).toThrow(SentryError); expect(() => new Dsn('httpx://abc@sentry.io:xxx/123')).toThrow(SentryError); expect(() => new Dsn('http://abc@sentry.io/abc')).toThrow(SentryError);