Skip to content

Commit c49b247

Browse files
Lms24lforst
andauthored
feat(core): Add handled option to captureConsoleIntegration (#14664)
Add a `handled` option to the `captureConsoleIntegration`. Right now, for v8, it will default to `false` as previously but it gives users the option to override the handled value. In v9, we will flip the default value to `true` after discussing this offline with the team. In this integration we can never be sure about the `handled` state at all. But flipping it to handled by default seems reasonable. Co-authored-by: Luca Forstner <[email protected]>
1 parent 0aa7d95 commit c49b247

File tree

3 files changed

+92
-21
lines changed

3 files changed

+92
-21
lines changed

dev-packages/browser-integration-tests/suites/integrations/captureConsole/test.ts

+10
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ sentryTest('it captures console messages correctly', async ({ getLocalTestUrl, p
3030
extra: {
3131
arguments: ['console log'],
3232
},
33+
message: 'console log',
3334
}),
3435
);
3536
expect(logEvent?.exception).toBeUndefined();
@@ -40,6 +41,7 @@ sentryTest('it captures console messages correctly', async ({ getLocalTestUrl, p
4041
extra: {
4142
arguments: ['console warn'],
4243
},
44+
message: 'console warn',
4345
}),
4446
);
4547
expect(warnEvent?.exception).toBeUndefined();
@@ -50,6 +52,7 @@ sentryTest('it captures console messages correctly', async ({ getLocalTestUrl, p
5052
extra: {
5153
arguments: ['console info'],
5254
},
55+
message: 'console info',
5356
}),
5457
);
5558
expect(infoEvent?.exception).toBeUndefined();
@@ -60,6 +63,7 @@ sentryTest('it captures console messages correctly', async ({ getLocalTestUrl, p
6063
extra: {
6164
arguments: ['console error'],
6265
},
66+
message: 'console error',
6367
}),
6468
);
6569
expect(errorEvent?.exception).toBeUndefined();
@@ -70,6 +74,7 @@ sentryTest('it captures console messages correctly', async ({ getLocalTestUrl, p
7074
extra: {
7175
arguments: ['console trace'],
7276
},
77+
message: 'console trace',
7378
}),
7479
);
7580
expect(traceEvent?.exception).toBeUndefined();
@@ -90,6 +95,11 @@ sentryTest('it captures console messages correctly', async ({ getLocalTestUrl, p
9095
}),
9196
);
9297
expect(errorWithErrorEvent?.exception?.values?.[0].value).toBe('console error with error object');
98+
expect(errorWithErrorEvent?.exception?.values?.[0].mechanism).toEqual({
99+
// TODO (v9): Adjust to true after changing the integration's default value
100+
handled: false,
101+
type: 'console',
102+
});
93103
expect(traceWithErrorEvent).toEqual(
94104
expect.objectContaining({
95105
level: 'log',

packages/core/src/integrations/captureconsole.ts

+15-3
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,24 @@ import { GLOBAL_OBJ } from '../utils-hoist/worldwide';
1111

1212
interface CaptureConsoleOptions {
1313
levels?: string[];
14+
15+
// TODO(v9): Flip default value to `true` and adjust JSDoc!
16+
/**
17+
* By default, Sentry will mark captured console messages as unhandled.
18+
* Set this to `true` if you want to mark them as handled instead.
19+
*
20+
* Note: in v9 of the SDK, this option will default to `true`, meaning the default behavior will change to mark console messages as handled.
21+
* @default false
22+
*/
23+
handled?: boolean;
1424
}
1525

1626
const INTEGRATION_NAME = 'CaptureConsole';
1727

1828
const _captureConsoleIntegration = ((options: CaptureConsoleOptions = {}) => {
1929
const levels = options.levels || CONSOLE_LEVELS;
30+
// TODO(v9): Flip default value to `true`
31+
const handled = !!options.handled;
2032

2133
return {
2234
name: INTEGRATION_NAME,
@@ -30,7 +42,7 @@ const _captureConsoleIntegration = ((options: CaptureConsoleOptions = {}) => {
3042
return;
3143
}
3244

33-
consoleHandler(args, level);
45+
consoleHandler(args, level, handled);
3446
});
3547
},
3648
};
@@ -41,7 +53,7 @@ const _captureConsoleIntegration = ((options: CaptureConsoleOptions = {}) => {
4153
*/
4254
export const captureConsoleIntegration = defineIntegration(_captureConsoleIntegration);
4355

44-
function consoleHandler(args: unknown[], level: string): void {
56+
function consoleHandler(args: unknown[], level: string, handled: boolean): void {
4557
const captureContext: CaptureContext = {
4658
level: severityLevelFromString(level),
4759
extra: {
@@ -54,7 +66,7 @@ function consoleHandler(args: unknown[], level: string): void {
5466
event.logger = 'console';
5567

5668
addExceptionMechanism(event, {
57-
handled: false,
69+
handled,
5870
type: 'console',
5971
});
6072

packages/core/test/lib/integrations/captureconsole.test.ts

+67-18
Original file line numberDiff line numberDiff line change
@@ -305,29 +305,78 @@ describe('CaptureConsole setup', () => {
305305
}).not.toThrow();
306306
});
307307

308-
it("marks captured exception's mechanism as unhandled", () => {
309-
// const addExceptionMechanismSpy = jest.spyOn(utils, 'addExceptionMechanism');
308+
describe('exception mechanism', () => {
309+
// TODO (v9): Flip this below after adjusting the default value for `handled` in the integration
310+
it("marks captured exception's mechanism as unhandled by default", () => {
311+
const captureConsole = captureConsoleIntegration({ levels: ['error'] });
312+
captureConsole.setup?.(mockClient);
310313

311-
const captureConsole = captureConsoleIntegration({ levels: ['error'] });
312-
captureConsole.setup?.(mockClient);
314+
const someError = new Error('some error');
315+
GLOBAL_OBJ.console.error(someError);
313316

314-
const someError = new Error('some error');
315-
GLOBAL_OBJ.console.error(someError);
317+
const addedEventProcessor = (mockScope.addEventProcessor as jest.Mock).mock.calls[0][0];
318+
const someEvent: Event = {
319+
exception: {
320+
values: [{}],
321+
},
322+
};
323+
addedEventProcessor(someEvent);
316324

317-
const addedEventProcessor = (mockScope.addEventProcessor as jest.Mock).mock.calls[0][0];
318-
const someEvent: Event = {
319-
exception: {
320-
values: [{}],
321-
},
322-
};
323-
addedEventProcessor(someEvent);
325+
expect(captureException).toHaveBeenCalledTimes(1);
326+
expect(mockScope.addEventProcessor).toHaveBeenCalledTimes(1);
324327

325-
expect(captureException).toHaveBeenCalledTimes(1);
326-
expect(mockScope.addEventProcessor).toHaveBeenCalledTimes(1);
328+
expect(someEvent.exception?.values?.[0]?.mechanism).toEqual({
329+
handled: false,
330+
type: 'console',
331+
});
332+
});
333+
334+
it("marks captured exception's mechanism as handled if set in the options", () => {
335+
const captureConsole = captureConsoleIntegration({ levels: ['error'], handled: true });
336+
captureConsole.setup?.(mockClient);
327337

328-
expect(someEvent.exception?.values?.[0]?.mechanism).toEqual({
329-
handled: false,
330-
type: 'console',
338+
const someError = new Error('some error');
339+
GLOBAL_OBJ.console.error(someError);
340+
341+
const addedEventProcessor = (mockScope.addEventProcessor as jest.Mock).mock.calls[0][0];
342+
const someEvent: Event = {
343+
exception: {
344+
values: [{}],
345+
},
346+
};
347+
addedEventProcessor(someEvent);
348+
349+
expect(captureException).toHaveBeenCalledTimes(1);
350+
expect(mockScope.addEventProcessor).toHaveBeenCalledTimes(1);
351+
352+
expect(someEvent.exception?.values?.[0]?.mechanism).toEqual({
353+
handled: true,
354+
type: 'console',
355+
});
356+
});
357+
358+
it("marks captured exception's mechanism as unhandled if set in the options", () => {
359+
const captureConsole = captureConsoleIntegration({ levels: ['error'], handled: false });
360+
captureConsole.setup?.(mockClient);
361+
362+
const someError = new Error('some error');
363+
GLOBAL_OBJ.console.error(someError);
364+
365+
const addedEventProcessor = (mockScope.addEventProcessor as jest.Mock).mock.calls[0][0];
366+
const someEvent: Event = {
367+
exception: {
368+
values: [{}],
369+
},
370+
};
371+
addedEventProcessor(someEvent);
372+
373+
expect(captureException).toHaveBeenCalledTimes(1);
374+
expect(mockScope.addEventProcessor).toHaveBeenCalledTimes(1);
375+
376+
expect(someEvent.exception?.values?.[0]?.mechanism).toEqual({
377+
handled: false,
378+
type: 'console',
379+
});
331380
});
332381
});
333382
});

0 commit comments

Comments
 (0)