This repository has been archived by the owner on Aug 30, 2023. It is now read-only.
-
-
Notifications
You must be signed in to change notification settings - Fork 32
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
60af521
commit 923f9fc
Showing
38 changed files
with
1,036 additions
and
49 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
75 changes: 75 additions & 0 deletions
75
sentry-core/src/main/java/io/sentry/core/DuplicateEventDetectionEventProcessor.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
package io.sentry.core; | ||
|
||
import io.sentry.core.exception.ExceptionMechanismException; | ||
import io.sentry.core.util.Objects; | ||
import java.util.ArrayList; | ||
import java.util.List; | ||
import java.util.Map; | ||
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 EventProcessor { | ||
private final WeakHashMap<Throwable, Object> capturedObjects = new WeakHashMap<>(); | ||
private final SentryOptions options; | ||
|
||
public DuplicateEventDetectionEventProcessor(final @NotNull SentryOptions options) { | ||
this.options = Objects.requireNonNull(options, "options are required"); | ||
} | ||
|
||
@Override | ||
public SentryEvent process(final @NotNull SentryEvent event, final @Nullable Object hint) { | ||
final Throwable throwable = event.getThrowable(); | ||
if (throwable != null) { | ||
if (throwable instanceof ExceptionMechanismException) { | ||
final ExceptionMechanismException ex = (ExceptionMechanismException) throwable; | ||
if (capturedObjects.containsKey(ex.getThrowable())) { | ||
options | ||
.getLogger() | ||
.log( | ||
SentryLevel.DEBUG, | ||
"Duplicate Exception detected. Event %s will be discarded.", | ||
event.getEventId()); | ||
return null; | ||
} else { | ||
capturedObjects.put(ex.getThrowable(), null); | ||
} | ||
} else { | ||
if (capturedObjects.containsKey(throwable) | ||
|| containsAnyKey(capturedObjects, allCauses(throwable))) { | ||
options | ||
.getLogger() | ||
.log( | ||
SentryLevel.DEBUG, | ||
"Duplicate Exception detected. Event %s will be discarded.", | ||
event.getEventId()); | ||
return null; | ||
} else { | ||
capturedObjects.put(throwable, null); | ||
} | ||
} | ||
} | ||
return event; | ||
} | ||
|
||
private static <T> boolean containsAnyKey( | ||
final @NotNull Map<T, Object> map, final @NotNull List<T> list) { | ||
for (T entry : list) { | ||
if (map.containsKey(entry)) { | ||
return true; | ||
} | ||
} | ||
return false; | ||
} | ||
|
||
private static @NotNull List<Throwable> allCauses(final @NotNull Throwable throwable) { | ||
final List<Throwable> causes = new ArrayList<>(); | ||
Throwable ex = throwable; | ||
while (ex.getCause() != null) { | ||
causes.add(ex.getCause()); | ||
ex = ex.getCause(); | ||
} | ||
return causes; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
70 changes: 70 additions & 0 deletions
70
sentry-core/src/test/java/io/sentry/core/DuplicateEventDetectionEventProcessorTest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
package io.sentry.core | ||
|
||
import io.sentry.core.exception.ExceptionMechanismException | ||
import io.sentry.core.protocol.Mechanism | ||
import java.lang.RuntimeException | ||
import kotlin.test.Test | ||
import kotlin.test.assertNotNull | ||
import kotlin.test.assertNull | ||
|
||
class DuplicateEventDetectionEventProcessorTest { | ||
|
||
val processor = DuplicateEventDetectionEventProcessor(SentryOptions()) | ||
|
||
@Test | ||
fun `does not drop event if no previous event with same exception was processed`() { | ||
processor.process(SentryEvent(), null) | ||
|
||
val result = processor.process(SentryEvent(RuntimeException()), null) | ||
|
||
assertNotNull(result) | ||
} | ||
|
||
@Test | ||
fun `drops event with the same exception`() { | ||
val event = SentryEvent(RuntimeException()) | ||
processor.process(event, null) | ||
|
||
val result = processor.process(event, null) | ||
assertNull(result) | ||
} | ||
|
||
@Test | ||
fun `drops event with mechanism exception having an exception that has already been processed`() { | ||
val event = SentryEvent(RuntimeException()) | ||
processor.process(event, null) | ||
|
||
val result = processor.process(SentryEvent(ExceptionMechanismException(Mechanism(), event.throwable, null)), null) | ||
assertNull(result) | ||
} | ||
|
||
@Test | ||
fun `drops event with exception that has already been processed with event with mechanism exception`() { | ||
val sentryEvent = SentryEvent(ExceptionMechanismException(Mechanism(), RuntimeException(), null)) | ||
processor.process(sentryEvent, null) | ||
|
||
val result = processor.process(SentryEvent((sentryEvent.throwable as ExceptionMechanismException).throwable), null) | ||
|
||
assertNull(result) | ||
} | ||
|
||
@Test | ||
fun `drops event with the cause equal to exception in already processed event`() { | ||
val event = SentryEvent(RuntimeException()) | ||
processor.process(event, null) | ||
|
||
val result = processor.process(SentryEvent(RuntimeException(event.throwable)), null) | ||
|
||
assertNull(result) | ||
} | ||
|
||
@Test | ||
fun `drops event with any of the causes has been already processed`() { | ||
val event = SentryEvent(RuntimeException()) | ||
processor.process(event, null) | ||
|
||
val result = processor.process(SentryEvent(RuntimeException(RuntimeException(event.throwable))), null) | ||
|
||
assertNull(result) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
35 changes: 35 additions & 0 deletions
35
...samples-spring-boot/src/main/java/io/sentry/samples/spring/boot/CustomEventProcessor.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
package io.sentry.samples.spring.boot; | ||
|
||
import io.sentry.core.EventProcessor; | ||
import io.sentry.core.SentryEvent; | ||
import io.sentry.core.protocol.SentryRuntime; | ||
import org.jetbrains.annotations.Nullable; | ||
import org.springframework.stereotype.Component; | ||
|
||
/** | ||
* Custom {@link EventProcessor} implementation lets modifying {@link SentryEvent}s before they are | ||
* sent to Sentry. | ||
*/ | ||
@Component | ||
public class CustomEventProcessor implements EventProcessor { | ||
private final String javaVersion; | ||
private final String javaVendor; | ||
|
||
public CustomEventProcessor(String javaVersion, String javaVendor) { | ||
this.javaVersion = javaVersion; | ||
this.javaVendor = javaVendor; | ||
} | ||
|
||
public CustomEventProcessor() { | ||
this(System.getProperty("java.version"), System.getProperty("java.vendor")); | ||
} | ||
|
||
@Override | ||
public SentryEvent process(SentryEvent event, @Nullable Object hint) { | ||
final SentryRuntime runtime = new SentryRuntime(); | ||
runtime.setVersion(javaVersion); | ||
runtime.setName(javaVendor); | ||
event.getContexts().setRuntime(runtime); | ||
return event; | ||
} | ||
} |
24 changes: 24 additions & 0 deletions
24
...amples/sentry-samples-spring-boot/src/main/java/io/sentry/samples/spring/boot/Person.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
package io.sentry.samples.spring.boot; | ||
|
||
public class Person { | ||
private final String firstName; | ||
private final String lastName; | ||
|
||
public Person(String firstName, String lastName) { | ||
this.firstName = firstName; | ||
this.lastName = lastName; | ||
} | ||
|
||
public String getFirstName() { | ||
return firstName; | ||
} | ||
|
||
public String getLastName() { | ||
return lastName; | ||
} | ||
|
||
@Override | ||
public String toString() { | ||
return "Person{" + "firstName='" + firstName + '\'' + ", lastName='" + lastName + '\'' + '}'; | ||
} | ||
} |
28 changes: 28 additions & 0 deletions
28
...try-samples-spring-boot/src/main/java/io/sentry/samples/spring/boot/PersonController.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
package io.sentry.samples.spring.boot; | ||
|
||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
import org.springframework.web.bind.annotation.GetMapping; | ||
import org.springframework.web.bind.annotation.PathVariable; | ||
import org.springframework.web.bind.annotation.PostMapping; | ||
import org.springframework.web.bind.annotation.RequestBody; | ||
import org.springframework.web.bind.annotation.RequestMapping; | ||
import org.springframework.web.bind.annotation.RestController; | ||
|
||
@RestController | ||
@RequestMapping("/person/") | ||
public class PersonController { | ||
private static final Logger LOGGER = LoggerFactory.getLogger(PersonController.class); | ||
|
||
@GetMapping("{id}") | ||
Person person(@PathVariable Long id) { | ||
LOGGER.info("Loading person with id={}", id); | ||
throw new IllegalArgumentException("Something went wrong [id=" + id + "]"); | ||
} | ||
|
||
@PostMapping | ||
Person create(@RequestBody Person person) { | ||
LOGGER.warn("Creating person: {}", person); | ||
return person; | ||
} | ||
} |
Oops, something went wrong.