Repository navigation
Expand file tree
/
Copy pathDuplicateEventDetectionEventProcessor.java
More file actions
94 lines (85 loc) · 3.03 KB
/
Copy pathDuplicateEventDetectionEventProcessor.java
File metadata and controls
94 lines (85 loc) · 3.03 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
package io.sentry;
import io.sentry.internal.eventprocessor.SentryEventProcessor;
import java.util.ArrayList;
import java.util.Collections;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.WeakHashMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/** Deduplicates events containing throwable that has been already processed. */
public final class DuplicateEventDetectionEventProcessor implements SentryEventProcessor {
private final @NotNull Map<Throwable, Object> capturedObjects =
Collections.synchronizedMap(new WeakHashMap<>());
private final @NotNull SentryOptions options;
public DuplicateEventDetectionEventProcessor(final @NotNull SentryOptions options) {
this.options = options;
}
@Override
public @Nullable SentryEvent process(final @NotNull SentryEvent event, final @NotNull Hint hint) {
if (options.isEnableDeduplication()) {
final Throwable throwable = event.getThrowable();
if (throwable != null) {
if (isIgnoredForDeduplication(throwable)) {
return event;
}
if (capturedObjects.containsKey(throwable) || containsAnyKey(allCauses(throwable))) {
options
.getLogger()
.log(
SentryLevel.DEBUG,
"Duplicate Exception detected. Event %s will be discarded.",
event.getEventId());
return null;
}
capturedObjects.put(throwable, null);
}
} else {
options.getLogger().log(SentryLevel.DEBUG, "Event deduplication is disabled.");
}
return event;
}
private boolean containsAnyKey(final @NotNull List<Throwable> throwables) {
for (final Throwable throwable : throwables) {
if (isIgnoredForDeduplication(throwable)) {
return false;
}
if (capturedObjects.containsKey(throwable)) {
return true;
}
}
return false;
}
private boolean isIgnoredForDeduplication(final @NotNull Throwable throwable) {
final @Nullable List<FilterString> ignoredErrors =
options.getIgnoredErrorFiltersForDeduplication();
if (ignoredErrors == null || ignoredErrors.isEmpty()) {
return false;
}
final String exceptionClassName = throwable.getClass().getName();
for (final FilterString ignoredError : ignoredErrors) {
if (ignoredError.getFilterString().equals(exceptionClassName)
|| ignoredError.matches(exceptionClassName)) {
return true;
}
}
return false;
}
private static @NotNull List<Throwable> allCauses(final @NotNull Throwable throwable) {
final List<Throwable> causes = new ArrayList<>();
final Set<Throwable> visited = Collections.newSetFromMap(new IdentityHashMap<>());
visited.add(throwable);
Throwable cause = throwable.getCause();
while (cause != null && visited.add(cause)) {
causes.add(cause);
cause = cause.getCause();
}
return causes;
}
@Override
public @Nullable Long getOrder() {
return 1000L;
}
}