Skip to content

Commit d4f67a2

Browse files
authored
feat: Always assemble Envelopes (#9101)
1 parent d47eb1a commit d4f67a2

File tree

7 files changed

+37
-82
lines changed

7 files changed

+37
-82
lines changed

packages/browser/src/client.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ export class BrowserClient extends BaseClient<BrowserClientOptions> {
127127
return;
128128
}
129129

130+
// This is really the only place where we want to check for a DSN and only send outcomes then
130131
if (!this._dsn) {
131132
__DEBUG_BUILD__ && logger.log('No dsn provided, will not send outcomes');
132133
return;

packages/core/src/baseclient.ts

Lines changed: 23 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ export abstract class BaseClient<O extends ClientOptions> implements Client<O> {
127127
if (options.dsn) {
128128
this._dsn = makeDsn(options.dsn);
129129
} else {
130-
__DEBUG_BUILD__ && logger.warn('No DSN provided, client will not do anything.');
130+
__DEBUG_BUILD__ && logger.warn('No DSN provided, client will not send events.');
131131
}
132132

133133
if (this._dsn) {
@@ -216,11 +216,6 @@ export abstract class BaseClient<O extends ClientOptions> implements Client<O> {
216216
* @inheritDoc
217217
*/
218218
public captureSession(session: Session): void {
219-
if (!this._isEnabled()) {
220-
__DEBUG_BUILD__ && logger.warn('SDK not enabled, will not capture session.');
221-
return;
222-
}
223-
224219
if (!(typeof session.release === 'string')) {
225220
__DEBUG_BUILD__ && logger.warn('Discarded session because of missing or non-string release');
226221
} else {
@@ -297,8 +292,8 @@ export abstract class BaseClient<O extends ClientOptions> implements Client<O> {
297292
/**
298293
* Sets up the integrations
299294
*/
300-
public setupIntegrations(): void {
301-
if (this._isEnabled() && !this._integrationsInitialized) {
295+
public setupIntegrations(forceInitialize?: boolean): void {
296+
if ((forceInitialize && !this._integrationsInitialized) || (this._isEnabled() && !this._integrationsInitialized)) {
302297
this._integrations = setupIntegrations(this, this._options.integrations);
303298
this._integrationsInitialized = true;
304299
}
@@ -338,34 +333,30 @@ export abstract class BaseClient<O extends ClientOptions> implements Client<O> {
338333
public sendEvent(event: Event, hint: EventHint = {}): void {
339334
this.emit('beforeSendEvent', event, hint);
340335

341-
if (this._dsn) {
342-
let env = createEventEnvelope(event, this._dsn, this._options._metadata, this._options.tunnel);
343-
344-
for (const attachment of hint.attachments || []) {
345-
env = addItemToEnvelope(
346-
env,
347-
createAttachmentEnvelopeItem(
348-
attachment,
349-
this._options.transportOptions && this._options.transportOptions.textEncoder,
350-
),
351-
);
352-
}
336+
let env = createEventEnvelope(event, this._dsn, this._options._metadata, this._options.tunnel);
353337

354-
const promise = this._sendEnvelope(env);
355-
if (promise) {
356-
promise.then(sendResponse => this.emit('afterSendEvent', event, sendResponse), null);
357-
}
338+
for (const attachment of hint.attachments || []) {
339+
env = addItemToEnvelope(
340+
env,
341+
createAttachmentEnvelopeItem(
342+
attachment,
343+
this._options.transportOptions && this._options.transportOptions.textEncoder,
344+
),
345+
);
346+
}
347+
348+
const promise = this._sendEnvelope(env);
349+
if (promise) {
350+
promise.then(sendResponse => this.emit('afterSendEvent', event, sendResponse), null);
358351
}
359352
}
360353

361354
/**
362355
* @inheritDoc
363356
*/
364357
public sendSession(session: Session | SessionAggregates): void {
365-
if (this._dsn) {
366-
const env = createSessionEnvelope(session, this._dsn, this._options._metadata, this._options.tunnel);
367-
void this._sendEnvelope(env);
368-
}
358+
const env = createSessionEnvelope(session, this._dsn, this._options._metadata, this._options.tunnel);
359+
void this._sendEnvelope(env);
369360
}
370361

371362
/**
@@ -531,9 +522,9 @@ export abstract class BaseClient<O extends ClientOptions> implements Client<O> {
531522
});
532523
}
533524

534-
/** Determines whether this SDK is enabled and a valid Dsn is present. */
525+
/** Determines whether this SDK is enabled and a transport is present. */
535526
protected _isEnabled(): boolean {
536-
return this.getOptions().enabled !== false && this._dsn !== undefined;
527+
return this.getOptions().enabled !== false && this._transport !== undefined;
537528
}
538529

539530
/**
@@ -635,10 +626,6 @@ export abstract class BaseClient<O extends ClientOptions> implements Client<O> {
635626
const options = this.getOptions();
636627
const { sampleRate } = options;
637628

638-
if (!this._isEnabled()) {
639-
return rejectedSyncPromise(new SentryError('SDK not enabled, will not capture event.', 'log'));
640-
}
641-
642629
const isTransaction = isTransactionEvent(event);
643630
const isError = isErrorEvent(event);
644631
const eventType = event.type || 'error';
@@ -738,9 +725,9 @@ export abstract class BaseClient<O extends ClientOptions> implements Client<O> {
738725
* @inheritdoc
739726
*/
740727
protected _sendEnvelope(envelope: Envelope): PromiseLike<void | TransportMakeRequestResponse> | void {
741-
if (this._transport && this._dsn) {
742-
this.emit('beforeEnvelope', envelope);
728+
this.emit('beforeEnvelope', envelope);
743729

730+
if (this._isEnabled() && this._transport) {
744731
return this._transport.send(envelope).then(null, reason => {
745732
__DEBUG_BUILD__ && logger.error('Error while sending event:', reason);
746733
});

packages/core/src/envelope.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,15 +36,15 @@ function enhanceEventWithSdkInfo(event: Event, sdkInfo?: SdkInfo): Event {
3636
/** Creates an envelope from a Session */
3737
export function createSessionEnvelope(
3838
session: Session | SessionAggregates,
39-
dsn: DsnComponents,
39+
dsn?: DsnComponents,
4040
metadata?: SdkMetadata,
4141
tunnel?: string,
4242
): SessionEnvelope {
4343
const sdkInfo = getSdkMetadataForEnvelopeHeader(metadata);
4444
const envelopeHeaders = {
4545
sent_at: new Date().toISOString(),
4646
...(sdkInfo && { sdk: sdkInfo }),
47-
...(!!tunnel && { dsn: dsnToString(dsn) }),
47+
...(!!tunnel && dsn && { dsn: dsnToString(dsn) }),
4848
};
4949

5050
const envelopeItem: SessionItem =
@@ -58,7 +58,7 @@ export function createSessionEnvelope(
5858
*/
5959
export function createEventEnvelope(
6060
event: Event,
61-
dsn: DsnComponents,
61+
dsn?: DsnComponents,
6262
metadata?: SdkMetadata,
6363
tunnel?: string,
6464
): EventEnvelope {

packages/core/test/lib/base.test.ts

Lines changed: 6 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -398,30 +398,6 @@ describe('BaseClient', () => {
398398
});
399399

400400
describe('captureEvent() / prepareEvent()', () => {
401-
test('skips when disabled', () => {
402-
expect.assertions(1);
403-
404-
const options = getDefaultTestClientOptions({ enabled: false, dsn: PUBLIC_DSN });
405-
const client = new TestClient(options);
406-
const scope = new Scope();
407-
408-
client.captureEvent({}, undefined, scope);
409-
410-
expect(TestClient.instance!.event).toBeUndefined();
411-
});
412-
413-
test('skips without a Dsn', () => {
414-
expect.assertions(1);
415-
416-
const options = getDefaultTestClientOptions({});
417-
const client = new TestClient(options);
418-
const scope = new Scope();
419-
420-
client.captureEvent({}, undefined, scope);
421-
422-
expect(TestClient.instance!.event).toBeUndefined();
423-
});
424-
425401
test.each([
426402
['`Error` instance', new Error('Will I get caught twice?')],
427403
['plain object', { 'Will I': 'get caught twice?' }],
@@ -1616,9 +1592,9 @@ describe('BaseClient', () => {
16161592

16171593
test('close', async () => {
16181594
jest.useRealTimers();
1619-
expect.assertions(2);
1595+
expect.assertions(4);
16201596

1621-
const { makeTransport, delay } = makeFakeTransport(300);
1597+
const { makeTransport, delay, getSentCount } = makeFakeTransport(300);
16221598

16231599
const client = new TestClient(
16241600
getDefaultTestClientOptions({
@@ -1630,9 +1606,12 @@ describe('BaseClient', () => {
16301606
expect(client.captureMessage('test')).toBeTruthy();
16311607

16321608
await client.close(delay);
1609+
expect(getSentCount()).toBe(1);
16331610

1611+
expect(client.captureMessage('test')).toBeTruthy();
1612+
await client.close(delay);
16341613
// Sends after close shouldn't work anymore
1635-
expect(client.captureMessage('test')).toBeFalsy();
1614+
expect(getSentCount()).toBe(1);
16361615
});
16371616

16381617
test('multiple concurrent flush calls should just work', async () => {
@@ -1798,18 +1777,6 @@ describe('BaseClient', () => {
17981777

17991778
expect(TestClient.instance!.session).toEqual(session);
18001779
});
1801-
1802-
test('skips when disabled', () => {
1803-
expect.assertions(1);
1804-
1805-
const options = getDefaultTestClientOptions({ enabled: false, dsn: PUBLIC_DSN });
1806-
const client = new TestClient(options);
1807-
const session = makeSession({ release: 'test' });
1808-
1809-
client.captureSession(session);
1810-
1811-
expect(TestClient.instance!.session).toBeUndefined();
1812-
});
18131780
});
18141781

18151782
describe('recordDroppedEvent()/_clearOutcomes()', () => {

packages/sveltekit/test/server/handle.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,7 @@ describe('handleSentry', () => {
296296
} catch (e) {
297297
expect(mockCaptureException).toBeCalledTimes(1);
298298
expect(addEventProcessorSpy).toBeCalledTimes(1);
299-
expect(mockAddExceptionMechanism).toBeCalledTimes(1);
299+
expect(mockAddExceptionMechanism).toBeCalledTimes(2);
300300
expect(mockAddExceptionMechanism).toBeCalledWith(
301301
{},
302302
{ handled: false, type: 'sveltekit', data: { function: 'handle' } },

packages/types/src/client.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ export interface Client<O extends ClientOptions = ClientOptions> {
149149
addIntegration?(integration: Integration): void;
150150

151151
/** This is an internal function to setup all integrations that should run on the client */
152-
setupIntegrations(): void;
152+
setupIntegrations(forceInitialize?: boolean): void;
153153

154154
/** Creates an {@link Event} from all inputs to `captureException` and non-primitive inputs to `captureMessage`. */
155155
// eslint-disable-next-line @typescript-eslint/no-explicit-any

packages/utils/src/envelope.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -234,14 +234,14 @@ export function createEventEnvelopeHeaders(
234234
event: Event,
235235
sdkInfo: SdkInfo | undefined,
236236
tunnel: string | undefined,
237-
dsn: DsnComponents,
237+
dsn?: DsnComponents,
238238
): EventEnvelopeHeaders {
239239
const dynamicSamplingContext = event.sdkProcessingMetadata && event.sdkProcessingMetadata.dynamicSamplingContext;
240240
return {
241241
event_id: event.event_id as string,
242242
sent_at: new Date().toISOString(),
243243
...(sdkInfo && { sdk: sdkInfo }),
244-
...(!!tunnel && { dsn: dsnToString(dsn) }),
244+
...(!!tunnel && dsn && { dsn: dsnToString(dsn) }),
245245
...(dynamicSamplingContext && {
246246
trace: dropUndefinedKeys({ ...dynamicSamplingContext }),
247247
}),

0 commit comments

Comments
 (0)