@@ -4,67 +4,50 @@ import { IEventPlugin } from '../IEventPlugin';
44import { EventPluginContext } from '../EventPluginContext' ;
55import { Utils } from '../../Utils' ;
66
7- const ERROR_KEY : string = '@error' ;
8- const WINDOW_MILLISECONDS = 2000 ;
9- const MAX_QUEUE_LENGTH = 10 ;
10-
117export 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