From 3ce6d4cec19baa2ada2693d100520e6d9899c35c Mon Sep 17 00:00:00 2001 From: Maciej Walkowiak Date: Fri, 12 Feb 2021 18:07:39 +0100 Subject: [PATCH 1/8] Optimize DuplicateEventDetectionEventProcessor performance. Using WeakHashMap to store objects opens up a possibility that the map will grow to thousands of entries and causes performance loss when searching for stored exception. This may happen either if outside of the SDK code references to exceptions are kept or if GC does not run for long time. Changing the implementation to `ConcurrentLinkedDeque` gives the event processor control over how many exceptions are stored in the memory. --- ...DuplicateEventDetectionEventProcessor.java | 30 ++++++++++++++----- ...plicateEventDetectionEventProcessorTest.kt | 29 +++++++++++++++++- 2 files changed, 51 insertions(+), 8 deletions(-) diff --git a/sentry/src/main/java/io/sentry/DuplicateEventDetectionEventProcessor.java b/sentry/src/main/java/io/sentry/DuplicateEventDetectionEventProcessor.java index 97e6f8b2b33..0528e1fe486 100644 --- a/sentry/src/main/java/io/sentry/DuplicateEventDetectionEventProcessor.java +++ b/sentry/src/main/java/io/sentry/DuplicateEventDetectionEventProcessor.java @@ -2,26 +2,34 @@ import io.sentry.util.Objects; import java.util.ArrayList; +import java.util.Collection; import java.util.List; -import java.util.Map; -import java.util.WeakHashMap; +import java.util.concurrent.ConcurrentLinkedDeque; + import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.TestOnly; /** Deduplicates events containing throwable that has been already processed. */ public final class DuplicateEventDetectionEventProcessor implements EventProcessor { - private final WeakHashMap capturedObjects = new WeakHashMap<>(); + private final ConcurrentLinkedDeque capturedObjects = new ConcurrentLinkedDeque<>(); private final SentryOptions options; + private final int bufferSize; public DuplicateEventDetectionEventProcessor(final @NotNull SentryOptions options) { + this(options, 100); + } + + public DuplicateEventDetectionEventProcessor(final @NotNull SentryOptions options, int bufferSize) { this.options = Objects.requireNonNull(options, "options are required"); + this.bufferSize = bufferSize; } @Override public SentryEvent process(final @NotNull SentryEvent event, final @Nullable Object hint) { final Throwable throwable = event.getOriginThrowable(); if (throwable != null) { - if (capturedObjects.containsKey(throwable) + if (capturedObjects.contains(throwable) || containsAnyKey(capturedObjects, allCauses(throwable))) { options .getLogger() @@ -31,16 +39,24 @@ public SentryEvent process(final @NotNull SentryEvent event, final @Nullable Obj event.getEventId()); return null; } else { - capturedObjects.put(throwable, null); + capturedObjects.add(throwable); + if (capturedObjects.size() > bufferSize) { + capturedObjects.poll(); + } } } return event; } + @TestOnly + int size() { + return capturedObjects.size(); + } + private static boolean containsAnyKey( - final @NotNull Map map, final @NotNull List list) { + final @NotNull Collection map, final @NotNull List list) { for (T entry : list) { - if (map.containsKey(entry)) { + if (map.contains(entry)) { return true; } } diff --git a/sentry/src/test/java/io/sentry/DuplicateEventDetectionEventProcessorTest.kt b/sentry/src/test/java/io/sentry/DuplicateEventDetectionEventProcessorTest.kt index b2e7ec0efb0..3ca67c2aae7 100644 --- a/sentry/src/test/java/io/sentry/DuplicateEventDetectionEventProcessorTest.kt +++ b/sentry/src/test/java/io/sentry/DuplicateEventDetectionEventProcessorTest.kt @@ -4,15 +4,27 @@ import io.sentry.exception.ExceptionMechanismException import io.sentry.protocol.Mechanism import java.lang.RuntimeException import kotlin.test.Test +import kotlin.test.assertEquals import kotlin.test.assertNotNull import kotlin.test.assertNull class DuplicateEventDetectionEventProcessorTest { - val processor = DuplicateEventDetectionEventProcessor(SentryOptions()) + class Fixture { + fun getSut(bufferSize: Int? = null): DuplicateEventDetectionEventProcessor { + return if (bufferSize != null) { + DuplicateEventDetectionEventProcessor(SentryOptions(), bufferSize) + } else { + DuplicateEventDetectionEventProcessor(SentryOptions()) + } + } + } + + var fixture = Fixture() @Test fun `does not drop event if no previous event with same exception was processed`() { + val processor = fixture.getSut() processor.process(SentryEvent(), null) val result = processor.process(SentryEvent(RuntimeException()), null) @@ -22,6 +34,7 @@ class DuplicateEventDetectionEventProcessorTest { @Test fun `drops event with the same exception`() { + val processor = fixture.getSut() val event = SentryEvent(RuntimeException()) processor.process(event, null) @@ -31,6 +44,7 @@ class DuplicateEventDetectionEventProcessorTest { @Test fun `drops event with mechanism exception having an exception that has already been processed`() { + val processor = fixture.getSut() val event = SentryEvent(RuntimeException()) processor.process(event, null) @@ -40,6 +54,7 @@ class DuplicateEventDetectionEventProcessorTest { @Test fun `drops event with exception that has already been processed with event with mechanism exception`() { + val processor = fixture.getSut() val sentryEvent = SentryEvent(ExceptionMechanismException(Mechanism(), RuntimeException(), null)) processor.process(sentryEvent, null) @@ -50,6 +65,7 @@ class DuplicateEventDetectionEventProcessorTest { @Test fun `drops event with the cause equal to exception in already processed event`() { + val processor = fixture.getSut() val event = SentryEvent(RuntimeException()) processor.process(event, null) @@ -60,6 +76,7 @@ class DuplicateEventDetectionEventProcessorTest { @Test fun `drops event with any of the causes has been already processed`() { + val processor = fixture.getSut() val event = SentryEvent(RuntimeException()) processor.process(event, null) @@ -67,4 +84,14 @@ class DuplicateEventDetectionEventProcessorTest { assertNull(result) } + + @Test + fun `does not keep in memory more items than the buffer size`() { + val processor = fixture.getSut(50) + for (i in 1..100) { + val event = SentryEvent(RuntimeException()) + processor.process(event, null) + } + assertEquals(50, processor.size()) + } } From 7c2b411893b9f512833ac09ae2efcb3dcf0e5c06 Mon Sep 17 00:00:00 2001 From: Maciej Walkowiak Date: Fri, 12 Feb 2021 18:43:17 +0100 Subject: [PATCH 2/8] Fix Android compatiblility. --- sentry/api/sentry.api | 1 + .../sentry/DuplicateEventDetectionEventProcessor.java | 10 +++++----- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/sentry/api/sentry.api b/sentry/api/sentry.api index 241adc788e4..dfa02fab7c8 100644 --- a/sentry/api/sentry.api +++ b/sentry/api/sentry.api @@ -71,6 +71,7 @@ public final class io/sentry/DiagnosticLogger : io/sentry/ILogger { public final class io/sentry/DuplicateEventDetectionEventProcessor : io/sentry/EventProcessor { public fun (Lio/sentry/SentryOptions;)V + public fun (Lio/sentry/SentryOptions;I)V public fun process (Lio/sentry/SentryEvent;Ljava/lang/Object;)Lio/sentry/SentryEvent; } diff --git a/sentry/src/main/java/io/sentry/DuplicateEventDetectionEventProcessor.java b/sentry/src/main/java/io/sentry/DuplicateEventDetectionEventProcessor.java index 0528e1fe486..79d8235555f 100644 --- a/sentry/src/main/java/io/sentry/DuplicateEventDetectionEventProcessor.java +++ b/sentry/src/main/java/io/sentry/DuplicateEventDetectionEventProcessor.java @@ -4,15 +4,14 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; -import java.util.concurrent.ConcurrentLinkedDeque; - +import java.util.concurrent.ConcurrentLinkedQueue; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.TestOnly; /** Deduplicates events containing throwable that has been already processed. */ public final class DuplicateEventDetectionEventProcessor implements EventProcessor { - private final ConcurrentLinkedDeque capturedObjects = new ConcurrentLinkedDeque<>(); + private final ConcurrentLinkedQueue capturedObjects = new ConcurrentLinkedQueue<>(); private final SentryOptions options; private final int bufferSize; @@ -20,7 +19,8 @@ public DuplicateEventDetectionEventProcessor(final @NotNull SentryOptions option this(options, 100); } - public DuplicateEventDetectionEventProcessor(final @NotNull SentryOptions options, int bufferSize) { + public DuplicateEventDetectionEventProcessor( + final @NotNull SentryOptions options, int bufferSize) { this.options = Objects.requireNonNull(options, "options are required"); this.bufferSize = bufferSize; } @@ -54,7 +54,7 @@ int size() { } private static boolean containsAnyKey( - final @NotNull Collection map, final @NotNull List list) { + final @NotNull Collection map, final @NotNull List list) { for (T entry : list) { if (map.contains(entry)) { return true; From d6b75c9ad6a6c4876d883bc48ecd714cfa32d082 Mon Sep 17 00:00:00 2001 From: Maciej Walkowiak Date: Fri, 12 Feb 2021 18:43:56 +0100 Subject: [PATCH 3/8] Changelog. --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 78d8e784af6..4e72b64ad33 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ * Enchancement: Support @SentrySpan and @SentryTransaction on classes and interfaces. (#1243) * Enchancement: Do not serialize empty collections and maps (#1245) * Ref: Simplify RestTemplate instrumentation (#1246) +* Ref: Optimize DuplicateEventDetectionEventProcessor performance. # 4.1.0 From fe1c9c1ea56db3e2e0593ebba7430e9c5115b063 Mon Sep 17 00:00:00 2001 From: Maciej Walkowiak Date: Fri, 12 Feb 2021 18:45:34 +0100 Subject: [PATCH 4/8] Changelog. --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4e72b64ad33..3a7c7500044 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,7 @@ * Enchancement: Support @SentrySpan and @SentryTransaction on classes and interfaces. (#1243) * Enchancement: Do not serialize empty collections and maps (#1245) * Ref: Simplify RestTemplate instrumentation (#1246) -* Ref: Optimize DuplicateEventDetectionEventProcessor performance. +* Ref: Optimize DuplicateEventDetectionEventProcessor performance (#1247). # 4.1.0 From a66b5ad7ba317b1deb230c0bb25af438234ff136 Mon Sep 17 00:00:00 2001 From: Maciej Walkowiak Date: Tue, 16 Feb 2021 18:35:37 +0100 Subject: [PATCH 5/8] Add a flag to disable deduplication. --- ...DuplicateEventDetectionEventProcessor.java | 32 ++++++++-------- .../main/java/io/sentry/SentryOptions.java | 38 +++++++++++++++++++ ...plicateEventDetectionEventProcessorTest.kt | 19 ++++++++-- .../test/java/io/sentry/SentryOptionsTest.kt | 18 +++++++++ 4 files changed, 89 insertions(+), 18 deletions(-) diff --git a/sentry/src/main/java/io/sentry/DuplicateEventDetectionEventProcessor.java b/sentry/src/main/java/io/sentry/DuplicateEventDetectionEventProcessor.java index 79d8235555f..3b00b864ca7 100644 --- a/sentry/src/main/java/io/sentry/DuplicateEventDetectionEventProcessor.java +++ b/sentry/src/main/java/io/sentry/DuplicateEventDetectionEventProcessor.java @@ -27,21 +27,23 @@ public DuplicateEventDetectionEventProcessor( @Override public SentryEvent process(final @NotNull SentryEvent event, final @Nullable Object hint) { - final Throwable throwable = event.getOriginThrowable(); - if (throwable != null) { - if (capturedObjects.contains(throwable) - || containsAnyKey(capturedObjects, allCauses(throwable))) { - options - .getLogger() - .log( - SentryLevel.DEBUG, - "Duplicate Exception detected. Event %s will be discarded.", - event.getEventId()); - return null; - } else { - capturedObjects.add(throwable); - if (capturedObjects.size() > bufferSize) { - capturedObjects.poll(); + if (options.isEnableDeduplication()) { + final Throwable throwable = event.getOriginThrowable(); + if (throwable != null) { + if (capturedObjects.contains(throwable) + || containsAnyKey(capturedObjects, allCauses(throwable))) { + options + .getLogger() + .log( + SentryLevel.DEBUG, + "Duplicate Exception detected. Event %s will be discarded.", + event.getEventId()); + return null; + } else { + capturedObjects.add(throwable); + if (capturedObjects.size() > bufferSize) { + capturedObjects.poll(); + } } } } diff --git a/sentry/src/main/java/io/sentry/SentryOptions.java b/sentry/src/main/java/io/sentry/SentryOptions.java index a766bead90f..eefac3972be 100644 --- a/sentry/src/main/java/io/sentry/SentryOptions.java +++ b/sentry/src/main/java/io/sentry/SentryOptions.java @@ -254,6 +254,13 @@ public class SentryOptions { /** max attachment size in bytes. */ private long maxAttachmentSize = 20 * 1024 * 1024; + /** + * Enables event deduplication with {@link DuplicateEventDetectionEventProcessor}. Event + * deduplication prevents from receiving the same exception multiple times when there is more than + * one framework active that captures errors, for example Logback and Spring Boot. + */ + private Boolean enableDeduplication = true; + /** * Creates {@link SentryOptions} from properties provided by a {@link PropertiesProvider}. * @@ -271,6 +278,7 @@ public class SentryOptions { propertiesProvider.getBooleanProperty("uncaught.handler.enabled")); options.setTracesSampleRate(propertiesProvider.getDoubleProperty("traces-sample-rate")); options.setDebug(propertiesProvider.getBooleanProperty("debug")); + options.setEnableDeduplication(propertiesProvider.getBooleanProperty("enable-deduplication")); final Map tags = propertiesProvider.getMap("tags"); for (final Map.Entry tag : tags.entrySet()) { options.setTag(tag.getKey(), tag.getValue()); @@ -1224,6 +1232,33 @@ public void setMaxAttachmentSize(long maxAttachmentSize) { this.maxAttachmentSize = maxAttachmentSize; } + /** + * Returns if event deduplication is turned on. + * + * @return if event deduplication is turned on. + */ + public boolean isEnableDeduplication() { + return Boolean.TRUE.equals(enableDeduplication); + } + + /** + * Returns if event deduplication is turned on or of or {@code null} if not specified. + * + * @return if event deduplication is turned on or of or {@code null} if not specified. + */ + private @Nullable Boolean getEnableDeduplication() { + return enableDeduplication; + } + + /** + * Enables or disables event deduplication. + * + * @param enableDeduplication true if enabled false otherwise + */ + public void setEnableDeduplication(final @Nullable Boolean enableDeduplication) { + this.enableDeduplication = enableDeduplication; + } + /** The BeforeSend callback */ public interface BeforeSendCallback { @@ -1318,6 +1353,9 @@ void merge(final @NotNull SentryOptions options) { if (options.getDebug() != null) { setDebug(options.getDebug()); } + if (options.getEnableDeduplication() != null) { + setEnableDeduplication(options.getEnableDeduplication()); + } final Map tags = new HashMap<>(options.getTags()); for (final Map.Entry tag : tags.entrySet()) { this.tags.put(tag.getKey(), tag.getValue()); diff --git a/sentry/src/test/java/io/sentry/DuplicateEventDetectionEventProcessorTest.kt b/sentry/src/test/java/io/sentry/DuplicateEventDetectionEventProcessorTest.kt index 93f226f39ce..50c279d4205 100644 --- a/sentry/src/test/java/io/sentry/DuplicateEventDetectionEventProcessorTest.kt +++ b/sentry/src/test/java/io/sentry/DuplicateEventDetectionEventProcessorTest.kt @@ -11,11 +11,16 @@ import kotlin.test.assertNull class DuplicateEventDetectionEventProcessorTest { class Fixture { - fun getSut(bufferSize: Int? = null): DuplicateEventDetectionEventProcessor { + fun getSut(bufferSize: Int? = null, enableDeduplication: Boolean? = null): DuplicateEventDetectionEventProcessor { + val options = SentryOptions().apply { + if (enableDeduplication != null) { + this.setEnableDeduplication(enableDeduplication) + } + } return if (bufferSize != null) { - DuplicateEventDetectionEventProcessor(SentryOptions(), bufferSize) + DuplicateEventDetectionEventProcessor(options, bufferSize) } else { - DuplicateEventDetectionEventProcessor(SentryOptions()) + DuplicateEventDetectionEventProcessor(options) } } } @@ -94,4 +99,12 @@ class DuplicateEventDetectionEventProcessorTest { } assertEquals(50, processor.size()) } + + @Test + fun `does not deduplicate is deduplication is disabled`() { + val processor = fixture.getSut(enableDeduplication = false) + val event = SentryEvent(RuntimeException()) + assertNotNull(processor.process(event, null)) + assertNotNull(processor.process(event, null)) + } } diff --git a/sentry/src/test/java/io/sentry/SentryOptionsTest.kt b/sentry/src/test/java/io/sentry/SentryOptionsTest.kt index 3ff3c62479b..75db348a6f8 100644 --- a/sentry/src/test/java/io/sentry/SentryOptionsTest.kt +++ b/sentry/src/test/java/io/sentry/SentryOptionsTest.kt @@ -436,6 +436,24 @@ class SentryOptionsTest { } } + @Test + fun `creates options with enableDeduplication using external properties`() { + // create a sentry.properties file in temporary folder + val temporaryFolder = TemporaryFolder() + temporaryFolder.create() + val file = temporaryFolder.newFile("sentry.properties") + file.appendText("enable-deduplication=true") + // set location of the sentry.properties file + System.setProperty("sentry.properties.file", file.absolutePath) + + try { + val options = SentryOptions.from(PropertiesProviderFactory.create()) + assertTrue(options.isEnableDeduplication) + } finally { + temporaryFolder.delete() + } + } + @Test fun `when options are initialized, maxAttachmentSize is 20`() { assertEquals(20 * 1024 * 1024, SentryOptions().maxAttachmentSize) From 0497e6888bbf4b8cc2e3613805d25743547556cc Mon Sep 17 00:00:00 2001 From: Maciej Walkowiak Date: Tue, 16 Feb 2021 18:36:58 +0100 Subject: [PATCH 6/8] Api. --- sentry/api/sentry.api | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sentry/api/sentry.api b/sentry/api/sentry.api index 774c74b5e21..cfd5d42a890 100644 --- a/sentry/api/sentry.api +++ b/sentry/api/sentry.api @@ -750,6 +750,7 @@ public class io/sentry/SentryOptions { public fun isAttachStacktrace ()Z public fun isAttachThreads ()Z public fun isDebug ()Z + public fun isEnableDeduplication ()Z public fun isEnableExternalConfiguration ()Z public fun isEnableNdk ()Z public fun isEnableScopeSync ()Z @@ -769,6 +770,7 @@ public class io/sentry/SentryOptions { public fun setDist (Ljava/lang/String;)V public fun setDistinctId (Ljava/lang/String;)V public fun setDsn (Ljava/lang/String;)V + public fun setEnableDeduplication (Ljava/lang/Boolean;)V public fun setEnableExternalConfiguration (Z)V public fun setEnableNdk (Z)V public fun setEnableScopeSync (Z)V From 065e73e80d936239f1a9b14a573dfab39c3cb8b6 Mon Sep 17 00:00:00 2001 From: Maciej Walkowiak Date: Wed, 17 Feb 2021 10:58:50 +0100 Subject: [PATCH 7/8] Synchronize WeakHashMap. --- sentry/api/sentry.api | 1 - ...DuplicateEventDetectionEventProcessor.java | 32 ++++++------------- ...plicateEventDetectionEventProcessorTest.kt | 19 ++--------- 3 files changed, 11 insertions(+), 41 deletions(-) diff --git a/sentry/api/sentry.api b/sentry/api/sentry.api index cfd5d42a890..bf31ee75877 100644 --- a/sentry/api/sentry.api +++ b/sentry/api/sentry.api @@ -71,7 +71,6 @@ public final class io/sentry/DiagnosticLogger : io/sentry/ILogger { public final class io/sentry/DuplicateEventDetectionEventProcessor : io/sentry/EventProcessor { public fun (Lio/sentry/SentryOptions;)V - public fun (Lio/sentry/SentryOptions;I)V public fun process (Lio/sentry/SentryEvent;Ljava/lang/Object;)Lio/sentry/SentryEvent; } diff --git a/sentry/src/main/java/io/sentry/DuplicateEventDetectionEventProcessor.java b/sentry/src/main/java/io/sentry/DuplicateEventDetectionEventProcessor.java index 3b00b864ca7..c8f04f07fc3 100644 --- a/sentry/src/main/java/io/sentry/DuplicateEventDetectionEventProcessor.java +++ b/sentry/src/main/java/io/sentry/DuplicateEventDetectionEventProcessor.java @@ -2,27 +2,21 @@ import io.sentry.util.Objects; import java.util.ArrayList; -import java.util.Collection; +import java.util.Collections; import java.util.List; -import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.Map; +import java.util.WeakHashMap; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.annotations.TestOnly; /** Deduplicates events containing throwable that has been already processed. */ public final class DuplicateEventDetectionEventProcessor implements EventProcessor { - private final ConcurrentLinkedQueue capturedObjects = new ConcurrentLinkedQueue<>(); + private final Map capturedObjects = + Collections.synchronizedMap(new WeakHashMap<>()); private final SentryOptions options; - private final int bufferSize; public DuplicateEventDetectionEventProcessor(final @NotNull SentryOptions options) { - this(options, 100); - } - - public DuplicateEventDetectionEventProcessor( - final @NotNull SentryOptions options, int bufferSize) { this.options = Objects.requireNonNull(options, "options are required"); - this.bufferSize = bufferSize; } @Override @@ -30,7 +24,7 @@ public SentryEvent process(final @NotNull SentryEvent event, final @Nullable Obj if (options.isEnableDeduplication()) { final Throwable throwable = event.getOriginThrowable(); if (throwable != null) { - if (capturedObjects.contains(throwable) + if (capturedObjects.containsKey(throwable) || containsAnyKey(capturedObjects, allCauses(throwable))) { options .getLogger() @@ -40,25 +34,17 @@ public SentryEvent process(final @NotNull SentryEvent event, final @Nullable Obj event.getEventId()); return null; } else { - capturedObjects.add(throwable); - if (capturedObjects.size() > bufferSize) { - capturedObjects.poll(); - } + capturedObjects.put(throwable, null); } } } return event; } - @TestOnly - int size() { - return capturedObjects.size(); - } - private static boolean containsAnyKey( - final @NotNull Collection map, final @NotNull List list) { + final @NotNull Map map, final @NotNull List list) { for (T entry : list) { - if (map.contains(entry)) { + if (map.containsKey(entry)) { return true; } } diff --git a/sentry/src/test/java/io/sentry/DuplicateEventDetectionEventProcessorTest.kt b/sentry/src/test/java/io/sentry/DuplicateEventDetectionEventProcessorTest.kt index 50c279d4205..22e569cc6a4 100644 --- a/sentry/src/test/java/io/sentry/DuplicateEventDetectionEventProcessorTest.kt +++ b/sentry/src/test/java/io/sentry/DuplicateEventDetectionEventProcessorTest.kt @@ -4,24 +4,19 @@ import io.sentry.exception.ExceptionMechanismException import io.sentry.protocol.Mechanism import java.lang.RuntimeException import kotlin.test.Test -import kotlin.test.assertEquals import kotlin.test.assertNotNull import kotlin.test.assertNull class DuplicateEventDetectionEventProcessorTest { class Fixture { - fun getSut(bufferSize: Int? = null, enableDeduplication: Boolean? = null): DuplicateEventDetectionEventProcessor { + fun getSut(enableDeduplication: Boolean? = null): DuplicateEventDetectionEventProcessor { val options = SentryOptions().apply { if (enableDeduplication != null) { this.setEnableDeduplication(enableDeduplication) } } - return if (bufferSize != null) { - DuplicateEventDetectionEventProcessor(options, bufferSize) - } else { - DuplicateEventDetectionEventProcessor(options) - } + return DuplicateEventDetectionEventProcessor(options) } } @@ -90,16 +85,6 @@ class DuplicateEventDetectionEventProcessorTest { assertNull(result) } - @Test - fun `does not keep in memory more items than the buffer size`() { - val processor = fixture.getSut(50) - for (i in 1..100) { - val event = SentryEvent(RuntimeException()) - processor.process(event, null) - } - assertEquals(50, processor.size()) - } - @Test fun `does not deduplicate is deduplication is disabled`() { val processor = fixture.getSut(enableDeduplication = false) From 4d219328ace43b829d0aad05c15f4254cdcfc93f Mon Sep 17 00:00:00 2001 From: Maciej Walkowiak Date: Wed, 17 Feb 2021 11:00:44 +0100 Subject: [PATCH 8/8] Log when deduplication is disabled. --- .../java/io/sentry/DuplicateEventDetectionEventProcessor.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sentry/src/main/java/io/sentry/DuplicateEventDetectionEventProcessor.java b/sentry/src/main/java/io/sentry/DuplicateEventDetectionEventProcessor.java index c8f04f07fc3..1d70d2f2b7f 100644 --- a/sentry/src/main/java/io/sentry/DuplicateEventDetectionEventProcessor.java +++ b/sentry/src/main/java/io/sentry/DuplicateEventDetectionEventProcessor.java @@ -37,6 +37,8 @@ public SentryEvent process(final @NotNull SentryEvent event, final @Nullable Obj capturedObjects.put(throwable, null); } } + } else { + options.getLogger().log(SentryLevel.DEBUG, "Event deduplication is disabled."); } return event; }