Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions packages/core/src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1037,16 +1037,18 @@ export abstract class Client<O extends ClientOptions = ClientOptions> {

/** Updates existing session based on the provided event */
protected _updateSessionFromEvent(session: Session, event: Event): void {
// initially, set `crashed` based on the event level and update from exceptions if there are any later on
let crashed = event.level === 'fatal';
let errored = false;
const exceptions = event.exception?.values;

if (exceptions) {
errored = true;
// reset crashed to false if there are exceptions, to ensure `mechanism.handled` is respected.
crashed = false;

for (const ex of exceptions) {
const mechanism = ex.mechanism;
if (mechanism?.handled === false) {
if (ex.mechanism?.handled === false) {
crashed = true;
break;
}
Expand Down
103 changes: 103 additions & 0 deletions packages/core/test/lib/client.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { afterEach, beforeEach, describe, expect, it, test, vi } from 'vitest';
import type { SeverityLevel } from '../../src';
import {
addBreadcrumb,
dsnToString,
Expand Down Expand Up @@ -2308,6 +2309,108 @@ describe('Client', () => {
});
});

describe('_updateSessionFromEvent()', () => {
describe('event has no exceptions', () => {
it('sets status to crashed if level is fatal', () => {
const client = new TestClient(getDefaultTestClientOptions());
const session = makeSession();
getCurrentScope().setSession(session);

client.captureEvent({ message: 'test', level: 'fatal' });

const updatedSession = client.session;

expect(updatedSession).toMatchObject({
duration: expect.any(Number),
errors: 1,
init: false,
sid: expect.any(String),
started: expect.any(Number),
status: 'crashed',
timestamp: expect.any(Number),
});
});

it.each(['error', 'warning', 'log', 'info', 'debug'] as const)(
'sets status to ok if level is %s',
(level: SeverityLevel) => {
const client = new TestClient(getDefaultTestClientOptions());
const session = makeSession();
getCurrentScope().setSession(session);

client.captureEvent({ message: 'test', level });

const updatedSession = client.session;

expect(updatedSession?.status).toEqual('ok');
},
);
});

describe('event has exceptions', () => {
it.each(['fatal', 'error', 'warning', 'log', 'info', 'debug'] as const)(
'sets status ok for handled exceptions and ignores event level %s',
(level: SeverityLevel) => {
const client = new TestClient(getDefaultTestClientOptions());
const session = makeSession();
getCurrentScope().setSession(session);

client.captureException(new Error('test'), { captureContext: { level } });

const updatedSession = client.session;

expect(updatedSession?.status).toEqual('ok');
},
);

it.each(['fatal', 'error', 'warning', 'log', 'info', 'debug'] as const)(
'sets status crashed for unhandled exceptions and ignores event level %s',
(level: SeverityLevel) => {
const client = new TestClient(getDefaultTestClientOptions());
const session = makeSession();
getCurrentScope().setSession(session);

client.captureException(new Error('test'), { captureContext: { level }, mechanism: { handled: false } });

const updatedSession = client.session;

expect(updatedSession?.status).toEqual('crashed');
},
);

it('sets status crashed if at least one exception is unhandled', () => {
const client = new TestClient(getDefaultTestClientOptions());
const session = makeSession();
getCurrentScope().setSession(session);

const event: Event = {
exception: {
values: [
{
mechanism: { type: 'generic', handled: true },
},
{
mechanism: { type: 'generic', handled: false },
},
{
mechanism: { type: 'generic', handled: true },
},
],
},
};

client.captureEvent(event);

const updatedSession = client.session;

expect(updatedSession).toMatchObject({
status: 'crashed',
errors: 1, // an event with multiple exceptions still counts as one error in the session
});
});
});
});

describe('recordDroppedEvent()/_clearOutcomes()', () => {
test('records and returns outcomes', () => {
const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN });
Expand Down