Skip to content

Commit

Permalink
feat: add max breadcrumbs limitation
Browse files Browse the repository at this point in the history
  • Loading branch information
ihsnow committed Jul 22, 2024
1 parent 721312b commit 0fa140b
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 3 deletions.
1 change: 1 addition & 0 deletions libs/browser/src/lib/consts/max-breadcrumbs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const MAX_BREADCRUMBS = 100;
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@ export interface BrowserSentryClientOptions extends SentryClientOptions {
ignoreErrors?: Array<string | RegExp>;
blacklistUrls?: Array<string | RegExp>;
release?: string;
maxBreadcrumbs?: number;
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
import { BrowserMicroSentryClient } from './browser-micro-sentry-client';
import { Severity } from '@micro-sentry/core';
import { MAX_BREADCRUMBS } from '../consts/max-breadcrumbs';

describe('BrowserMicroSentryClient', () => {
let client: BrowserMicroSentryClient;
const maxBreadcrumbs = 10;

beforeAll(() => {
client = new BrowserMicroSentryClient({
dsn: 'http://[email protected]/2',
release: '1.0.0',
maxBreadcrumbs,
});
});

Expand Down Expand Up @@ -205,6 +208,76 @@ describe('BrowserMicroSentryClient', () => {
});
});

it('should limit breadcrumbs amount - with custom limit', () => {
for (let i = 0; i < maxBreadcrumbs + 2; i++) {
client.addBreadcrumb({
event_id: `id${i}`,
type: 'console',
level: Severity.critical,
});
}

expect(client.state.breadcrumbs?.length).toBe(maxBreadcrumbs);
});

it('should limit breadcrumbs amount - with default limit', () => {
const anotherClient = new BrowserMicroSentryClient({});

for (let i = 0; i < MAX_BREADCRUMBS + 2; i++) {
anotherClient.addBreadcrumb({
event_id: `id${i}`,
type: 'console',
level: Severity.critical,
});
}

expect(anotherClient.state.breadcrumbs?.length).toBe(MAX_BREADCRUMBS);
});

it('should save only last breadcrumbs', () => {
for (let i = 0; i < maxBreadcrumbs + 2; i++) {
client.addBreadcrumb({
event_id: `id${i}`,
type: 'console',
level: Severity.critical,
});
}

expect(
(client.state.breadcrumbs ?? [])
.map((breadcrumb) => breadcrumb.event_id)
.join(',')
).toEqual('id2,id3,id4,id5,id6,id7,id8,id9,id10,id11');
});

it('should not add breadcrumbs at all if maxBreadcrumbs is set to 0', () => {
const anotherClient = new BrowserMicroSentryClient({ maxBreadcrumbs: 0 });

anotherClient.addBreadcrumb({
event_id: 'id',
type: 'console',
level: Severity.critical,
});

expect(anotherClient.state.breadcrumbs?.length).toBe(0);
});

it('should ignore maxBreadcrumbs option if maxBreadcrumbs is a negative number', () => {
const anotherClient = new BrowserMicroSentryClient({
maxBreadcrumbs: -100,
});

for (let i = 0; i < MAX_BREADCRUMBS + 2; i++) {
anotherClient.addBreadcrumb({
event_id: `id${i}`,
type: 'console',
level: Severity.critical,
});
}

expect(anotherClient.state.breadcrumbs?.length).toBe(MAX_BREADCRUMBS);
});

it('should skip breadcrumbs if beforeBreadcrumb returns null', () => {
client = new BrowserMicroSentryClient({
dsn: 'http://[email protected]/2',
Expand Down Expand Up @@ -237,7 +310,7 @@ describe('BrowserMicroSentryClient', () => {
]);
});

afterAll(() => {
afterEach(() => {
client.clearState();
});
});
Expand Down
23 changes: 21 additions & 2 deletions libs/browser/src/lib/services/browser-micro-sentry-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,14 @@ import { State } from '../models/state';
import { MicroSentryPlugin } from '../models/plugin';
import { BrowserSentryClientOptions } from '../models/browser-sentry-client-options';
import { isMatchingPattern } from '../utils/is-matching-pattern';
import { MAX_BREADCRUMBS } from '../consts/max-breadcrumbs';

function getWindow(): Window {
return window;
}

export class BrowserMicroSentryClient extends MicroSentryClient {
private readonly breadcrumbsKeyName = 'breadcrumbs';
private destroyed = false;
private readonly plugins: MicroSentryPlugin[];
private readonly beforeSend: NonNullable<
Expand All @@ -33,6 +35,7 @@ export class BrowserMicroSentryClient extends MicroSentryClient {
BrowserSentryClientOptions['ignoreErrors']
>;
private readonly release?: string;
private readonly maxBreadcrumbs: number;

constructor(
private options: BrowserSentryClientOptions,
Expand All @@ -47,14 +50,17 @@ export class BrowserMicroSentryClient extends MicroSentryClient {
blacklistUrls = [],
ignoreErrors = [],
release = undefined,
} = this.options || {};
maxBreadcrumbs = MAX_BREADCRUMBS,
} = this.options || {} || [];

this.plugins = plugins.map((Plugin) => new Plugin(this));
this.beforeSend = beforeSend;
this.beforeBreadcrumb = beforeBreadcrumb;
this.blacklistUrls = blacklistUrls;
this.ignoreErrors = ignoreErrors;
this.release = release;
this.maxBreadcrumbs =
maxBreadcrumbs >= 0 ? maxBreadcrumbs : MAX_BREADCRUMBS;
}

protected _state: State = {};
Expand Down Expand Up @@ -126,13 +132,22 @@ export class BrowserMicroSentryClient extends MicroSentryClient {
}

this.extendState({
breadcrumbs: [
[this.breadcrumbsKeyName]: [
{
timestamp: Date.now() / 1_000,
...result,
},
],
});

const breadcrumbs = this.getKeyState(this.breadcrumbsKeyName);

if (!!breadcrumbs && (breadcrumbs.length ?? 0) > this.maxBreadcrumbs) {
this.setKeyState(
this.breadcrumbsKeyName,
this.maxBreadcrumbs > 0 ? breadcrumbs.slice(-this.maxBreadcrumbs) : []
);
}
}

setBreadcrumbs(breadcrumbs: Breadcrumb[] | undefined) {
Expand Down Expand Up @@ -307,4 +322,8 @@ export class BrowserMicroSentryClient extends MicroSentryClient {
private setKeyState<T extends keyof State>(key: T, value: State[T]) {
this._state[key] = value;
}

private getKeyState<T extends keyof State>(key: T): State[T] {
return this._state[key];
}
}

0 comments on commit 0fa140b

Please sign in to comment.