Skip to content

Commit 63b05b9

Browse files
committed
Simplified the duplicate checker plugin
1 parent 7780f76 commit 63b05b9

File tree

2 files changed

+31
-51
lines changed

2 files changed

+31
-51
lines changed

src/plugins/default/DuplicateCheckerPlugin-spec.ts

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,11 @@ import { createFixture } from './EventPluginTestFixture';
66
import { expect } from 'chai';
77

88
describe('DuplicateCheckerPlugin', () => {
9-
10-
let target: DuplicateCheckerPlugin;
11-
let now: number;
9+
let now: number = 0;
10+
let plugin: DuplicateCheckerPlugin;
1211

1312
beforeEach(() => {
14-
target = new DuplicateCheckerPlugin();
15-
(<any>target).getNow = () => now;
16-
now = 0;
13+
plugin = new DuplicateCheckerPlugin(() => now);
1714
});
1815

1916
function run(exception: Error) {
@@ -28,7 +25,7 @@ describe('DuplicateCheckerPlugin', () => {
2825

2926
let errorPlugin = new ErrorPlugin();
3027
errorPlugin.run(context);
31-
target.run(context);
28+
plugin.run(context);
3229

3330
return context;
3431
}

src/plugins/default/DuplicateCheckerPlugin.ts

Lines changed: 27 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -4,67 +4,50 @@ import { IEventPlugin } from '../IEventPlugin';
44
import { EventPluginContext } from '../EventPluginContext';
55
import { Utils } from '../../Utils';
66

7-
const ERROR_KEY: string = '@error';
8-
const WINDOW_MILLISECONDS = 2000;
9-
const MAX_QUEUE_LENGTH = 10;
10-
117
export class DuplicateCheckerPlugin implements IEventPlugin {
128
public priority: number = 40;
139
public name: string = 'DuplicateCheckerPlugin';
1410

15-
private recentlyProcessedErrors: TimestampedHash[] = [];
16-
17-
public run(context: EventPluginContext, next?: () => void): void {
18-
if (context.event.type === 'error') {
19-
let error = context.event.data[ERROR_KEY];
20-
let isDuplicate = this.checkDuplicate(error, context.log);
21-
if (isDuplicate) {
22-
context.cancelled = true;
23-
return;
24-
}
25-
}
11+
private _processedHashcodes: TimestampedHash[] = [];
12+
private _getCurrentTime: () => number;
2613

27-
next && next();
14+
constructor(getCurrentTime:() => number = () => Date.now()) {
15+
this._getCurrentTime = getCurrentTime;
2816
}
2917

30-
private getNow() {
31-
return Date.now();
32-
}
18+
public run(context: EventPluginContext, next?: () => void): void {
19+
function isDuplicate(error: IInnerError, processedHashcodes, now, log: ILog): boolean {
20+
while (error) {
21+
let hashCode = Utils.getHashCode(error.stack_trace && JSON.stringify(error.stack_trace));
3322

34-
private checkDuplicate(error: IInnerError, log: ILog): boolean {
35-
function getHashCodeForError(err: IInnerError): number {
36-
if (!err.stack_trace) {
37-
return null;
38-
}
23+
// Only process the unique errors times within a 2 second window.
24+
if (hashCode && processedHashcodes.some(h => h.hash === hashCode && h.timestamp >= (now - 2000))) {
25+
log.info(`Ignoring duplicate error event hash: ${hashCode}`);
26+
return true;
27+
}
3928

40-
return Utils.getHashCode(JSON.stringify(err.stack_trace));
41-
}
29+
// Add this exception to our list of recent processed errors.
30+
processedHashcodes.push({ hash: hashCode, timestamp: now });
4231

43-
let now = this.getNow();
44-
let repeatWindow = now - WINDOW_MILLISECONDS;
45-
let hashCode: number;
46-
while (error) {
47-
hashCode = getHashCodeForError(error);
32+
// Only keep the last 20 recent errors.
33+
while (processedHashcodes.length > 20) {
34+
processedHashcodes.shift();
35+
}
4836

49-
// make sure that we don't process the same error multiple times within the repeat window
50-
if (hashCode && this.recentlyProcessedErrors.some(h =>
51-
h.hash === hashCode && h.timestamp >= repeatWindow)) {
52-
log.info(`Ignoring duplicate error event: hash=${hashCode}`);
53-
return true;
37+
error = error.inner;
5438
}
5539

56-
// add this exception to our list of recent errors that we have processed
57-
this.recentlyProcessedErrors.push({ hash: hashCode, timestamp: now });
40+
return false;
41+
}
5842

59-
// only keep the last 10 recent errors
60-
while (this.recentlyProcessedErrors.length > MAX_QUEUE_LENGTH) {
61-
this.recentlyProcessedErrors.shift();
43+
if (context.event.type === 'error') {
44+
if (isDuplicate(context.event.data['@error'], this._processedHashcodes, this._getCurrentTime(), context.log)) {
45+
context.cancelled = true;
46+
return;
6247
}
63-
64-
error = error.inner;
6548
}
6649

67-
return false;
50+
next && next();
6851
}
6952
}
7053

0 commit comments

Comments
 (0)