11import { IInnerError } from '../../models/IInnerError' ;
22import { IStackFrame } from '../../models/IStackFrame' ;
3-
43import { ILog } from '../../logging/ILog' ;
5-
64import { IEventPlugin } from '../IEventPlugin' ;
75import { EventPluginContext } from '../EventPluginContext' ;
6+ import { Utils } from '../../Utils' ;
87
98const ERROR_KEY : string = '@error' ;
109const WINDOW_MILLISECONDS = 2000 ;
@@ -17,71 +16,56 @@ export class DuplicateCheckerPlugin implements IEventPlugin {
1716 private recentlyProcessedErrors : TimestampedHash [ ] = [ ] ;
1817
1918 public run ( context : EventPluginContext , next ?: ( ) => void ) : void {
20- if ( context . event . type === 'error' ) {
21- let error = context . event . data [ ERROR_KEY ] ;
22- let isDuplicate = this . checkDuplicate ( error , context . log ) ;
23- if ( isDuplicate ) {
24- context . cancelled = true ;
25- return ;
19+ function checkDuplicate ( error : IInnerError , log : ILog ) : boolean {
20+ function getHashCodeForError ( err : IInnerError ) : number {
21+ if ( ! err . stack_trace ) {
22+ return null ;
23+ }
24+
25+ return Utils . getHashCode ( JSON . stringify ( err . stack_trace ) ) ;
2626 }
27- }
2827
29- next && next ( ) ;
30- }
28+ let now = Date . now ( ) ;
29+ let repeatWindow = now - WINDOW_MILLISECONDS ;
30+ let hashCode : number ;
31+ while ( error ) {
32+ hashCode = getHashCodeForError ( error ) ;
3133
32- private getNow ( ) {
33- return Date . now ( ) ;
34- }
34+ // make sure that we don't process the same error multiple times within the repeat window
35+ if ( hashCode && this . recentlyProcessedErrors . some ( h =>
36+ h . hash === hashCode && h . timestamp >= repeatWindow ) ) {
37+ log . info ( `Ignoring duplicate error event: hash=${ hashCode } ` ) ;
38+ return true ;
39+ }
40+
41+ // add this exception to our list of recent errors that we have processed
42+ this . recentlyProcessedErrors . push ( { hash : hashCode , timestamp : now } ) ;
3543
36- private checkDuplicate ( error : IInnerError , log : ILog ) : boolean {
37- let now = this . getNow ( ) ;
38- let repeatWindow = now - WINDOW_MILLISECONDS ;
39- let hashCode : number ;
40- while ( error ) {
41- hashCode = getHashCodeForError ( error ) ;
44+ // only keep the last 10 recent errors
45+ while ( this . recentlyProcessedErrors . length > MAX_QUEUE_LENGTH ) {
46+ this . recentlyProcessedErrors . shift ( ) ;
47+ }
4248
43- // make sure that we don't process the same error multiple times within the repeat window
44- if ( hashCode && this . recentlyProcessedErrors . some ( h =>
45- h . hash === hashCode && h . timestamp >= repeatWindow ) ) {
46- log . info ( `Ignoring duplicate error event: hash=${ hashCode } ` ) ;
47- return true ;
49+ error = error . inner ;
4850 }
4951
50- // add this exception to our list of recent errors that we have processed
51- this . recentlyProcessedErrors . push ( { hash : hashCode , timestamp : now } ) ;
52+ return false ;
53+ }
5254
53- // only keep the last 10 recent errors
54- while ( this . recentlyProcessedErrors . length > MAX_QUEUE_LENGTH ) {
55- this . recentlyProcessedErrors . shift ( ) ;
55+ if ( context . event . type === 'error' ) {
56+ let error = context . event . data [ ERROR_KEY ] ;
57+ let isDuplicate = checkDuplicate ( error , context . log ) ;
58+ if ( isDuplicate ) {
59+ context . cancelled = true ;
60+ return ;
5661 }
57-
58- error = error . inner ;
5962 }
6063
61- return false ;
64+ next && next ( ) ;
6265 }
6366}
6467
6568interface TimestampedHash {
6669 hash : number ;
6770 timestamp : number ;
6871}
69-
70- function getHashCodeForError ( error : IInnerError ) : number {
71- if ( ! error . stack_trace ) {
72- return null ;
73- }
74-
75- let stack = JSON . stringify ( error . stack_trace ) ;
76- return getHashCode ( stack ) ;
77- }
78-
79- function getHashCode ( s : string ) : number {
80- let hash = 0 , length = s . length , char ;
81- for ( let i = 0 ; i < length ; i ++ ) {
82- char = s . charCodeAt ( i ) ;
83- hash = ( ( hash << 5 ) - hash ) + char ;
84- hash |= 0 ;
85- }
86- return hash ;
87- }
0 commit comments