From 82810f519aaf66e3d9bc45269477c9630aacf49f Mon Sep 17 00:00:00 2001 From: Alexander Dinauer Date: Thu, 16 Jan 2025 05:43:49 +0100 Subject: [PATCH] Wrap exceptions when there is a suppressed exception and mark the wrapper as group --- .../io/sentry/SentryExceptionFactory.java | 30 +++++++++++++++---- 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/sentry/src/main/java/io/sentry/SentryExceptionFactory.java b/sentry/src/main/java/io/sentry/SentryExceptionFactory.java index 2808df11c0b..29b5f041e7e 100644 --- a/sentry/src/main/java/io/sentry/SentryExceptionFactory.java +++ b/sentry/src/main/java/io/sentry/SentryExceptionFactory.java @@ -137,19 +137,20 @@ public List getSentryExceptions(final @NotNull Throwable throwa @NotNull Deque extractExceptionQueue(final @NotNull Throwable throwable) { return extractExceptionQueueInternal( - throwable, new AtomicInteger(-1), new HashSet<>(), new ArrayDeque<>()); + throwable, new AtomicInteger(-1), new HashSet<>(), new ArrayDeque<>(), null); } Deque extractExceptionQueueInternal( final @NotNull Throwable throwable, final @NotNull AtomicInteger exceptionId, final @NotNull HashSet circularityDetector, - final @NotNull Deque exceptions) { + final @NotNull Deque exceptions, + final @Nullable Integer parentIdOverride) { Mechanism exceptionMechanism; Thread thread; Throwable currentThrowable = throwable; - int parentId = exceptionId.get(); + int parentId = parentIdOverride == null ? exceptionId.get() : parentIdOverride; // Stack the exceptions to send them in the reverse order while (currentThrowable != null && circularityDetector.add(currentThrowable)) { @@ -167,6 +168,21 @@ Deque extractExceptionQueueInternal( thread = Thread.currentThread(); } + if (currentThrowable instanceof SentryExceptionGroupException) { + exceptionMechanism.setExceptionGroup(true); + } + + Throwable[] suppressed = currentThrowable.getSuppressed(); + if (suppressed != null && suppressed.length > 0) { + extractExceptionQueueInternal( + new SentryExceptionGroupException(), + exceptionId, + circularityDetector, + exceptions, + null); + parentId = exceptionId.get(); + } + final boolean includeSentryFrames = Boolean.FALSE.equals(exceptionMechanism.isHandled()); final List frames = sentryStackTraceFactory.getStackFrames( @@ -187,12 +203,10 @@ Deque extractExceptionQueueInternal( final int currentExceptionId = exceptionId.incrementAndGet(); exceptionMechanism.setExceptionId(currentExceptionId); - Throwable[] suppressed = currentThrowable.getSuppressed(); if (suppressed != null && suppressed.length > 0) { - exceptionMechanism.setExceptionGroup(true); for (Throwable suppressedThrowable : suppressed) { extractExceptionQueueInternal( - suppressedThrowable, exceptionId, circularityDetector, exceptions); + suppressedThrowable, exceptionId, circularityDetector, exceptions, parentId); } } currentThrowable = currentThrowable.getCause(); @@ -201,4 +215,8 @@ Deque extractExceptionQueueInternal( return exceptions; } + + private static final class SentryExceptionGroupException extends RuntimeException { + private static final long serialVersionUID = 6909700354645201267L; + } }