UNPKG

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