this repo has no description
1import { logger } from '@sentry/utils'; 2 3/** Deduplication filter */ 4class Dedupe {constructor() { Dedupe.prototype.__init.call(this); } 5 /** 6 * @inheritDoc 7 */ 8 static __initStatic() {this.id = 'Dedupe';} 9 10 /** 11 * @inheritDoc 12 */ 13 __init() {this.name = Dedupe.id;} 14 15 /** 16 * @inheritDoc 17 */ 18 19 /** 20 * @inheritDoc 21 */ 22 setupOnce(addGlobalEventProcessor, getCurrentHub) { 23 const eventProcessor = currentEvent => { 24 // We want to ignore any non-error type events, e.g. transactions or replays 25 // These should never be deduped, and also not be compared against as _previousEvent. 26 if (currentEvent.type) { 27 return currentEvent; 28 } 29 30 const self = getCurrentHub().getIntegration(Dedupe); 31 if (self) { 32 // Juuust in case something goes wrong 33 try { 34 if (_shouldDropEvent(currentEvent, self._previousEvent)) { 35 (typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__) && logger.warn('Event dropped due to being a duplicate of previously captured event.'); 36 return null; 37 } 38 } catch (_oO) { 39 return (self._previousEvent = currentEvent); 40 } 41 42 return (self._previousEvent = currentEvent); 43 } 44 return currentEvent; 45 }; 46 47 eventProcessor.id = this.name; 48 addGlobalEventProcessor(eventProcessor); 49 } 50} Dedupe.__initStatic(); 51 52/** JSDoc */ 53function _shouldDropEvent(currentEvent, previousEvent) { 54 if (!previousEvent) { 55 return false; 56 } 57 58 if (_isSameMessageEvent(currentEvent, previousEvent)) { 59 return true; 60 } 61 62 if (_isSameExceptionEvent(currentEvent, previousEvent)) { 63 return true; 64 } 65 66 return false; 67} 68 69/** JSDoc */ 70function _isSameMessageEvent(currentEvent, previousEvent) { 71 const currentMessage = currentEvent.message; 72 const previousMessage = previousEvent.message; 73 74 // If neither event has a message property, they were both exceptions, so bail out 75 if (!currentMessage && !previousMessage) { 76 return false; 77 } 78 79 // If only one event has a stacktrace, but not the other one, they are not the same 80 if ((currentMessage && !previousMessage) || (!currentMessage && previousMessage)) { 81 return false; 82 } 83 84 if (currentMessage !== previousMessage) { 85 return false; 86 } 87 88 if (!_isSameFingerprint(currentEvent, previousEvent)) { 89 return false; 90 } 91 92 if (!_isSameStacktrace(currentEvent, previousEvent)) { 93 return false; 94 } 95 96 return true; 97} 98 99/** JSDoc */ 100function _isSameExceptionEvent(currentEvent, previousEvent) { 101 const previousException = _getExceptionFromEvent(previousEvent); 102 const currentException = _getExceptionFromEvent(currentEvent); 103 104 if (!previousException || !currentException) { 105 return false; 106 } 107 108 if (previousException.type !== currentException.type || previousException.value !== currentException.value) { 109 return false; 110 } 111 112 if (!_isSameFingerprint(currentEvent, previousEvent)) { 113 return false; 114 } 115 116 if (!_isSameStacktrace(currentEvent, previousEvent)) { 117 return false; 118 } 119 120 return true; 121} 122 123/** JSDoc */ 124function _isSameStacktrace(currentEvent, previousEvent) { 125 let currentFrames = _getFramesFromEvent(currentEvent); 126 let previousFrames = _getFramesFromEvent(previousEvent); 127 128 // If neither event has a stacktrace, they are assumed to be the same 129 if (!currentFrames && !previousFrames) { 130 return true; 131 } 132 133 // If only one event has a stacktrace, but not the other one, they are not the same 134 if ((currentFrames && !previousFrames) || (!currentFrames && previousFrames)) { 135 return false; 136 } 137 138 currentFrames = currentFrames ; 139 previousFrames = previousFrames ; 140 141 // If number of frames differ, they are not the same 142 if (previousFrames.length !== currentFrames.length) { 143 return false; 144 } 145 146 // Otherwise, compare the two 147 for (let i = 0; i < previousFrames.length; i++) { 148 const frameA = previousFrames[i]; 149 const frameB = currentFrames[i]; 150 151 if ( 152 frameA.filename !== frameB.filename || 153 frameA.lineno !== frameB.lineno || 154 frameA.colno !== frameB.colno || 155 frameA.function !== frameB.function 156 ) { 157 return false; 158 } 159 } 160 161 return true; 162} 163 164/** JSDoc */ 165function _isSameFingerprint(currentEvent, previousEvent) { 166 let currentFingerprint = currentEvent.fingerprint; 167 let previousFingerprint = previousEvent.fingerprint; 168 169 // If neither event has a fingerprint, they are assumed to be the same 170 if (!currentFingerprint && !previousFingerprint) { 171 return true; 172 } 173 174 // If only one event has a fingerprint, but not the other one, they are not the same 175 if ((currentFingerprint && !previousFingerprint) || (!currentFingerprint && previousFingerprint)) { 176 return false; 177 } 178 179 currentFingerprint = currentFingerprint ; 180 previousFingerprint = previousFingerprint ; 181 182 // Otherwise, compare the two 183 try { 184 return !!(currentFingerprint.join('') === previousFingerprint.join('')); 185 } catch (_oO) { 186 return false; 187 } 188} 189 190/** JSDoc */ 191function _getExceptionFromEvent(event) { 192 return event.exception && event.exception.values && event.exception.values[0]; 193} 194 195/** JSDoc */ 196function _getFramesFromEvent(event) { 197 const exception = event.exception; 198 199 if (exception) { 200 try { 201 // @ts-ignore Object could be undefined 202 return exception.values[0].stacktrace.frames; 203 } catch (_oO) { 204 return undefined; 205 } 206 } 207 return undefined; 208} 209 210export { Dedupe }; 211//# sourceMappingURL=dedupe.js.map