diff --git a/bugsnag-spring/src/main/java/com/bugsnag/BugsnagSpringConfiguration.java b/bugsnag-spring/src/main/java/com/bugsnag/BugsnagSpringConfiguration.java index 36f70550..88aeae99 100644 --- a/bugsnag-spring/src/main/java/com/bugsnag/BugsnagSpringConfiguration.java +++ b/bugsnag-spring/src/main/java/com/bugsnag/BugsnagSpringConfiguration.java @@ -28,8 +28,9 @@ public class BugsnagSpringConfiguration implements InitializingBean { Callback springVersionErrorCallback() { Callback callback = new Callback() { @Override - public void beforeNotify(Report report) { + public boolean onError(Report report) { addSpringRuntimeVersion(report.getDevice()); + return true; } }; bugsnag.addCallback(callback); @@ -37,15 +38,16 @@ public void beforeNotify(Report report) { } @Bean - BeforeSendSession springVersionSessionCallback() { - BeforeSendSession beforeSendSession = new BeforeSendSession() { + OnSession springVersionSessionCallback() { + OnSession onSession = new OnSession() { @Override - public void beforeSendSession(SessionPayload payload) { + public boolean onSession(SessionPayload payload) { addSpringRuntimeVersion(payload.getDevice()); + return true; } }; - bugsnag.addBeforeSendSession(beforeSendSession); - return beforeSendSession; + bugsnag.addOnSession(onSession); + return onSession; } private void addSpringRuntimeVersion(Map device) { diff --git a/bugsnag-spring/src/main/java/com/bugsnag/ExceptionClassCallback.java b/bugsnag-spring/src/main/java/com/bugsnag/ExceptionClassCallback.java index 3c93b35b..008f09d1 100644 --- a/bugsnag-spring/src/main/java/com/bugsnag/ExceptionClassCallback.java +++ b/bugsnag-spring/src/main/java/com/bugsnag/ExceptionClassCallback.java @@ -111,7 +111,7 @@ class ExceptionClassCallback implements Callback { } @Override - public void beforeNotify(Report report) { + public boolean onError(Report report) { HandledState handledState = report.getHandledState(); @@ -119,7 +119,7 @@ public void beforeNotify(Report report) { SeverityReasonType severityReasonType = handledState.calculateSeverityReasonType(); if (severityReasonType == SeverityReasonType.REASON_USER_SPECIFIED || severityReasonType == SeverityReasonType.REASON_CALLBACK_SPECIFIED) { - return; + return true; // do not change delivery decision } Class exceptionClass = report.getException().getClass(); @@ -133,5 +133,6 @@ public void beforeNotify(Report report) { severity, handledState.isUnhandled())); } + return true; } } diff --git a/bugsnag-spring/src/main/java/com/bugsnag/SpringBootConfiguration.java b/bugsnag-spring/src/main/java/com/bugsnag/SpringBootConfiguration.java index f8f71ab0..aa5509ec 100644 --- a/bugsnag-spring/src/main/java/com/bugsnag/SpringBootConfiguration.java +++ b/bugsnag-spring/src/main/java/com/bugsnag/SpringBootConfiguration.java @@ -19,8 +19,9 @@ public class SpringBootConfiguration { Callback springBootVersionErrorCallback() { Callback callback = new Callback() { @Override - public void beforeNotify(Report report) { + public boolean onError(Report report) { addSpringRuntimeVersion(report.getDevice()); + return true; } }; bugsnag.addCallback(callback); @@ -28,15 +29,16 @@ public void beforeNotify(Report report) { } @Bean - BeforeSendSession springBootVersionSessionCallback() { - BeforeSendSession beforeSendSession = new BeforeSendSession() { + OnSession springBootVersionSessionCallback() { + OnSession onSession = new OnSession() { @Override - public void beforeSendSession(SessionPayload payload) { + public boolean onSession(SessionPayload payload) { addSpringRuntimeVersion(payload.getDevice()); + return true; } }; - bugsnag.addBeforeSendSession(beforeSendSession); - return beforeSendSession; + bugsnag.addOnSession(onSession); + return onSession; } private void addSpringRuntimeVersion(Map device) { diff --git a/bugsnag-spring/src/test/java/com/bugsnag/SpringMvcTest.java b/bugsnag-spring/src/test/java/com/bugsnag/SpringMvcTest.java index 6acb31a1..fcded466 100644 --- a/bugsnag-spring/src/test/java/com/bugsnag/SpringMvcTest.java +++ b/bugsnag-spring/src/test/java/com/bugsnag/SpringMvcTest.java @@ -190,8 +190,9 @@ public void unhandledTypeMismatchExceptionCallbackSeverity() Report report; Callback callback = new Callback() { @Override - public void beforeNotify(Report report) { + public boolean onError(Report report) { report.setSeverity(Severity.WARNING); + return true; } }; diff --git a/bugsnag-spring/src/test/java/com/bugsnag/testapp/springboot/TestController.java b/bugsnag-spring/src/test/java/com/bugsnag/testapp/springboot/TestController.java index 86e064bf..650bbf98 100644 --- a/bugsnag-spring/src/test/java/com/bugsnag/testapp/springboot/TestController.java +++ b/bugsnag-spring/src/test/java/com/bugsnag/testapp/springboot/TestController.java @@ -67,8 +67,9 @@ public void handledTypeMismatchExceptionCallbackSeverity() { } catch (TypeMismatchException ex) { bugsnag.notify(ex, new Callback() { @Override - public void beforeNotify(Report report) { + public boolean onError(Report report) { report.setSeverity(Severity.WARNING); + return true; } }); } diff --git a/bugsnag/src/main/java/com/bugsnag/BeforeSendSession.java b/bugsnag/src/main/java/com/bugsnag/BeforeSendSession.java deleted file mode 100644 index dcd6a50d..00000000 --- a/bugsnag/src/main/java/com/bugsnag/BeforeSendSession.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.bugsnag; - -interface BeforeSendSession { - void beforeSendSession(SessionPayload payload); -} diff --git a/bugsnag/src/main/java/com/bugsnag/Bugsnag.java b/bugsnag/src/main/java/com/bugsnag/Bugsnag.java index 635a0439..21758962 100644 --- a/bugsnag/src/main/java/com/bugsnag/Bugsnag.java +++ b/bugsnag/src/main/java/com/bugsnag/Bugsnag.java @@ -452,16 +452,12 @@ public boolean notify(Report report, Callback reportCallback) { return false; } - // Run all client-wide beforeNotify callbacks + // Run all client-wide onError callbacks for (Callback callback : config.callbacks) { try { - // Run the callback - callback.beforeNotify(report); - - // Check if callback cancelled delivery - if (report.getShouldCancel()) { - LOGGER.debug("Error not reported to Bugsnag - " - + "cancelled by a client-wide beforeNotify callback"); + boolean proceed = callback.onError(report); + if (!proceed || report.getShouldCancel()) { + LOGGER.debug("Error not reported to Bugsnag - cancelled by a client-wide onError callback"); return false; } } catch (Throwable ex) { @@ -472,16 +468,12 @@ public boolean notify(Report report, Callback reportCallback) { // Add thread metadata to the report report.mergeMetadata(THREAD_METADATA.get()); - // Run the report-specific beforeNotify callback, if given + // Run the report-specific onError callback, if given if (reportCallback != null) { try { - // Run the callback - reportCallback.beforeNotify(report); - - // Check if callback cancelled delivery - if (report.getShouldCancel()) { - LOGGER.debug( - "Error not reported to Bugsnag - cancelled by a report-specific callback"); + boolean proceed = reportCallback.onError(report); + if (!proceed || report.getShouldCancel()) { + LOGGER.debug("Error not reported to Bugsnag - cancelled by a report-specific callback"); return false; } } catch (Throwable ex) { @@ -676,7 +668,7 @@ public static Set uncaughtExceptionClients() { return Collections.emptySet(); } - void addBeforeSendSession(BeforeSendSession beforeSendSession) { - sessionTracker.addBeforeSendSession(beforeSendSession); + void addOnSession(OnSession onSession) { + sessionTracker.addOnSession(onSession); } } diff --git a/bugsnag/src/main/java/com/bugsnag/BugsnagAppender.java b/bugsnag/src/main/java/com/bugsnag/BugsnagAppender.java index c65df317..7fe93bfd 100644 --- a/bugsnag/src/main/java/com/bugsnag/BugsnagAppender.java +++ b/bugsnag/src/main/java/com/bugsnag/BugsnagAppender.java @@ -134,7 +134,7 @@ protected void append(final ILoggingEvent event) { calculateSeverity(event), new Callback() { @Override - public void beforeNotify(Report report) { + public boolean onError(Report report) { // Add some data from the logging event report.addToTab("Log event data", @@ -146,8 +146,12 @@ public void beforeNotify(Report report) { populateContextData(report, event); if (reportCallback != null) { - reportCallback.beforeNotify(report); + boolean proceed = reportCallback.onError(report); + if (!proceed) { + return false; // suppress delivery + } } + return true; } }); } @@ -270,7 +274,7 @@ private Bugsnag createBugsnag() { // Add a callback to put global metadata on every report bugsnag.addCallback(new Callback() { @Override - public void beforeNotify(Report report) { + public boolean onError(Report report) { for (LogbackMetadata metadata : globalMetadata) { for (LogbackMetadataTab tab : metadata.getTabs()) { @@ -282,6 +286,7 @@ public void beforeNotify(Report report) { } } + return true; } }); diff --git a/bugsnag/src/main/java/com/bugsnag/OnSession.java b/bugsnag/src/main/java/com/bugsnag/OnSession.java new file mode 100644 index 00000000..b3349f54 --- /dev/null +++ b/bugsnag/src/main/java/com/bugsnag/OnSession.java @@ -0,0 +1,6 @@ +package com.bugsnag; + +@FunctionalInterface +interface OnSession { + boolean onSession(SessionPayload payload); +} diff --git a/bugsnag/src/main/java/com/bugsnag/SessionPayload.java b/bugsnag/src/main/java/com/bugsnag/SessionPayload.java index ac259dab..f7ef93d9 100644 --- a/bugsnag/src/main/java/com/bugsnag/SessionPayload.java +++ b/bugsnag/src/main/java/com/bugsnag/SessionPayload.java @@ -9,10 +9,21 @@ final class SessionPayload { private final Collection sessionCounts; private final Diagnostics diagnostics; + private final Map device; + private final Map app; SessionPayload(Collection sessionCounts, Configuration configuration) { this.sessionCounts = sessionCounts; diagnostics = new Diagnostics(configuration); + this.device = null; + this.app = null; + } + + SessionPayload(Collection sessionCounts, Map device, Map app) { + this.sessionCounts = sessionCounts; + this.diagnostics = null; + this.device = device; + this.app = app; } @Expose @@ -22,12 +33,12 @@ Notifier getNotifier() { @Expose Map getDevice() { - return diagnostics.device; + return device != null ? device : diagnostics.device; } @Expose Map getApp() { - return diagnostics.app; + return app != null ? app : diagnostics.app; } @Expose diff --git a/bugsnag/src/main/java/com/bugsnag/SessionTracker.java b/bugsnag/src/main/java/com/bugsnag/SessionTracker.java index d0a50472..65ab82a6 100644 --- a/bugsnag/src/main/java/com/bugsnag/SessionTracker.java +++ b/bugsnag/src/main/java/com/bugsnag/SessionTracker.java @@ -4,6 +4,7 @@ import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.Date; import java.util.UUID; import java.util.concurrent.ConcurrentLinkedQueue; @@ -16,12 +17,11 @@ class SessionTracker { private final Configuration config; private final ThreadLocal session = new ThreadLocal(); private final AtomicReference batchCount = new AtomicReference(); - private final Collection - enqueuedSessionCounts = new ConcurrentLinkedQueue(); + private final Collection enqueuedSessionCounts = new ConcurrentLinkedQueue(); private final Semaphore flushingRequest = new Semaphore(1); private final AtomicBoolean shuttingDown = new AtomicBoolean(); - private final Collection sessionCallbacks = new ConcurrentLinkedQueue(); + private final Collection sessionCallbacks = new ConcurrentLinkedQueue(); SessionTracker(Configuration configuration) { this.config = configuration; @@ -86,17 +86,40 @@ private void sendSessions(Date now) { if (!enqueuedSessionCounts.isEmpty() && flushingRequest.tryAcquire(1)) { try { - Collection requestValues - = new ArrayList(enqueuedSessionCounts); - SessionPayload payload = new SessionPayload(requestValues, config); + Collection requestValues = new ArrayList(enqueuedSessionCounts); + Collection approvedSessions = new ArrayList(); + SessionPayload firstPayload = null; + + for (SessionCount sessionCount : requestValues) { + SessionPayload payload = new SessionPayload(Collections.singleton(sessionCount), config); + + boolean sendThisSession = true; + for (OnSession callback : sessionCallbacks) { + if (!callback.onSession(payload)) { + sendThisSession = false; + break; + } + } - for (BeforeSendSession callback : sessionCallbacks) { - callback.beforeSendSession(payload); + if (sendThisSession) { + approvedSessions.add(sessionCount); + if (firstPayload == null) { + firstPayload = payload; + } + } + } + + if (!approvedSessions.isEmpty()) { + // Reuse the device/app from the first approved payload to preserve runtime + // versions + SessionPayload batchPayload = new SessionPayload(approvedSessions, firstPayload.getDevice(), + firstPayload.getApp()); + Delivery delivery = config.sessionDelivery; + delivery.deliver(config.serializer, batchPayload, config.getSessionApiHeaders()); } - Delivery delivery = config.sessionDelivery; - delivery.deliver(config.serializer, payload, config.getSessionApiHeaders()); enqueuedSessionCounts.removeAll(requestValues); + } finally { flushingRequest.release(1); } @@ -109,7 +132,7 @@ void shutdown() { } } - void addBeforeSendSession(BeforeSendSession beforeSendSession) { - sessionCallbacks.add(beforeSendSession); + void addOnSession(OnSession onSession) { + sessionCallbacks.add(onSession); } } diff --git a/bugsnag/src/main/java/com/bugsnag/callbacks/AppCallback.java b/bugsnag/src/main/java/com/bugsnag/callbacks/AppCallback.java index 1b3db326..bcdc3b3b 100644 --- a/bugsnag/src/main/java/com/bugsnag/callbacks/AppCallback.java +++ b/bugsnag/src/main/java/com/bugsnag/callbacks/AppCallback.java @@ -11,7 +11,7 @@ public AppCallback(Configuration config) { } @Override - public void beforeNotify(Report report) { + public boolean onError(Report report) { if (config.appType != null) { report.setAppInfo("type", config.appType); } @@ -23,5 +23,6 @@ public void beforeNotify(Report report) { if (config.releaseStage != null) { report.setAppInfo("releaseStage", config.releaseStage); } + return true; } } diff --git a/bugsnag/src/main/java/com/bugsnag/callbacks/Callback.java b/bugsnag/src/main/java/com/bugsnag/callbacks/Callback.java index 8ba80297..1ef45428 100644 --- a/bugsnag/src/main/java/com/bugsnag/callbacks/Callback.java +++ b/bugsnag/src/main/java/com/bugsnag/callbacks/Callback.java @@ -5,8 +5,12 @@ public interface Callback { /** * Perform changes to the report before delivery. + * Return {@code true} to continue sending, or {@code false} to cancel delivery. + * Implementations may also call {@code report.cancel()} for backward + * compatibility. * * @param report the report to perform changes on. + * @return true to send, false to suppress delivery */ - void beforeNotify(Report report); + boolean onError(Report report); } diff --git a/bugsnag/src/main/java/com/bugsnag/callbacks/DeviceCallback.java b/bugsnag/src/main/java/com/bugsnag/callbacks/DeviceCallback.java index e6d21297..59005e59 100644 --- a/bugsnag/src/main/java/com/bugsnag/callbacks/DeviceCallback.java +++ b/bugsnag/src/main/java/com/bugsnag/callbacks/DeviceCallback.java @@ -84,12 +84,13 @@ public void run() { } @Override - public void beforeNotify(Report report) { + public boolean onError(Report report) { report .addToTab("device", "osArch", System.getProperty("os.arch")) .addToTab("device", "locale", Locale.getDefault()) .setDeviceInfo("hostname", getHostnameValue()) .setDeviceInfo("osName", System.getProperty("os.name")) .setDeviceInfo("osVersion", System.getProperty("os.version")); + return true; } } diff --git a/bugsnag/src/main/java/com/bugsnag/callbacks/JakartaServletCallback.java b/bugsnag/src/main/java/com/bugsnag/callbacks/JakartaServletCallback.java index 17c4f67c..b11dd73b 100644 --- a/bugsnag/src/main/java/com/bugsnag/callbacks/JakartaServletCallback.java +++ b/bugsnag/src/main/java/com/bugsnag/callbacks/JakartaServletCallback.java @@ -26,11 +26,11 @@ public static boolean isAvailable() { } @Override - public void beforeNotify(Report report) { + public boolean onError(Report report) { // Check if we have any servlet request data available HttpServletRequest request = BugsnagServletRequestListener.getServletRequest(); if (request == null) { - return; + return true; // nothing to add, but do not cancel } // Add request information to metadata @@ -46,6 +46,7 @@ public void beforeNotify(Report report) { if (report.getContext() == null) { report.setContext(request.getMethod() + " " + request.getRequestURI()); } + return true; } private String getClientIp(HttpServletRequest request) { diff --git a/bugsnag/src/test/java/com/bugsnag/AppenderMetadataTest.java b/bugsnag/src/test/java/com/bugsnag/AppenderMetadataTest.java index 4ba4dc0a..682087c5 100644 --- a/bugsnag/src/test/java/com/bugsnag/AppenderMetadataTest.java +++ b/bugsnag/src/test/java/com/bugsnag/AppenderMetadataTest.java @@ -6,7 +6,6 @@ import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; -import com.bugsnag.callbacks.Callback; import com.bugsnag.delivery.Delivery; import com.bugsnag.logback.BugsnagMarker; @@ -109,14 +108,11 @@ public void testMetadataRemoval() { Bugsnag.addThreadMetadata("thread", "some key", "some thread value"); // Send three test logs, the first one with report metadata added - LOGGER.warn(new BugsnagMarker(new Callback() { - @Override - public void beforeNotify(Report report) { - report.addToTab("report", "some key", "some report value"); - } + LOGGER.warn(new BugsnagMarker(report -> { + report.addToTab("report", "some key", "some report value"); + return true; }), "Test exception", new RuntimeException("test")); - LOGGER.warn("Test exception", new RuntimeException("test")); Bugsnag.clearThreadMetadata(); LOGGER.warn("Test exception", new RuntimeException("test")); diff --git a/bugsnag/src/test/java/com/bugsnag/AppenderTest.java b/bugsnag/src/test/java/com/bugsnag/AppenderTest.java index 248e50e1..e09d41af 100644 --- a/bugsnag/src/test/java/com/bugsnag/AppenderTest.java +++ b/bugsnag/src/test/java/com/bugsnag/AppenderTest.java @@ -5,7 +5,6 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; -import com.bugsnag.callbacks.Callback; import com.bugsnag.delivery.Delivery; import com.bugsnag.logback.ProxyConfiguration; @@ -296,19 +295,16 @@ public void testRedactedKeys() { public void testCallback() { // Setup a callback to set the user - appender.addCallback(new Callback() { - @Override - public void beforeNotify(Report report) { - report.setUserName("User Name"); - report.setUserEmail("user@example.com"); - report.setUserId("12345"); + appender.addCallback(report -> { + report.setUserName("User Name"); + report.setUserEmail("user@example.com"); + report.setUserId("12345"); - report.setContext("the context"); + report.setContext("the context"); - report.setGroupingHash("the grouping hash"); - - report.setApiKey("newapikey"); - } + report.setGroupingHash("the grouping hash"); + report.setApiKey("newapikey"); + return true; }); // Send a log message diff --git a/bugsnag/src/test/java/com/bugsnag/BugsnagTest.java b/bugsnag/src/test/java/com/bugsnag/BugsnagTest.java index e075be43..10d19d49 100644 --- a/bugsnag/src/test/java/com/bugsnag/BugsnagTest.java +++ b/bugsnag/src/test/java/com/bugsnag/BugsnagTest.java @@ -6,7 +6,6 @@ import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; -import com.bugsnag.callbacks.Callback; import com.bugsnag.delivery.Delivery; import com.bugsnag.delivery.HttpDelivery; import com.bugsnag.delivery.OutputStreamDelivery; @@ -186,14 +185,12 @@ public void deliver(Serializer serializer, Object object, Map he public void close() { } }); - assertTrue(bugsnag.notify(new Throwable(), new Callback() { - @Override - public void beforeNotify(Report report) { - report.addToTab("firsttab", "testredact1", "secretpassword"); - report.addToTab("firsttab", "testredact2", "secretpassword"); - report.addToTab("firsttab", "testredact3", "secretpassword"); - report.addToTab("secondtab", "testredact1", "secretpassword"); - } + assertTrue(bugsnag.notify(new Throwable(), report -> { + report.addToTab("firsttab", "testredact1", "secretpassword"); + report.addToTab("firsttab", "testredact2", "secretpassword"); + report.addToTab("firsttab", "testredact3", "secretpassword"); + report.addToTab("secondtab", "testredact1", "secretpassword"); + return true; })); } @@ -221,17 +218,15 @@ public void close() { } }); - assertTrue(bugsnag.notify(new Throwable(), new Callback() { - @Override - public void beforeNotify(Report report) { - Map headers = new HashMap(); - headers.put("Authorization", "User:Password"); - headers.put("authorization", "User:Password"); - headers.put("Cookie", "123456ABCDEF"); - headers.put("cookie", "123456ABCDEF"); + assertTrue(bugsnag.notify(new Throwable(), report -> { + Map headers = new HashMap(); + headers.put("Authorization", "User:Password"); + headers.put("authorization", "User:Password"); + headers.put("Cookie", "123456ABCDEF"); + headers.put("cookie", "123456ABCDEF"); - report.addToTab("request", "headers", headers); - } + report.addToTab("request", "headers", headers); + return true; })); } @@ -250,21 +245,17 @@ public void deliver(Serializer serializer, Object object, Map he public void close() { } }); - assertTrue(bugsnag.notify(new Throwable(), new Callback() { - @Override - public void beforeNotify(Report report) { - report.setUser("123", "test@example.com", "test name"); - } + assertTrue(bugsnag.notify(new Throwable(), report -> { + report.setUser("123", "test@example.com", "test name"); + return true; })); } @Test public void testContext() { - bugsnag.addCallback(new Callback() { - @Override - public void beforeNotify(Report report) { - report.setContext("the context"); - } + bugsnag.addCallback(report -> { + report.setContext("the context"); + return true; }); bugsnag.setDelivery(new Delivery() { @Override @@ -282,11 +273,9 @@ public void close() { @Test public void testGroupingHash() { - bugsnag.addCallback(new Callback() { - @Override - public void beforeNotify(Report report) { - report.setGroupingHash("the grouping hash"); - } + bugsnag.addCallback(report -> { + report.setGroupingHash("the grouping hash"); + return true; }); bugsnag.setDelivery(new Delivery() { @Override @@ -304,11 +293,9 @@ public void close() { @Test public void testSingleCallback() { - bugsnag.addCallback(new Callback() { - @Override - public void beforeNotify(Report report) { - report.setApiKey("newapikey"); - } + bugsnag.addCallback(report -> { + report.setApiKey("newapikey"); + return true; }); bugsnag.setDelivery(new Delivery() { @Override @@ -338,27 +325,21 @@ public void close() { } }); - assertTrue(bugsnag.notify(new Throwable(), new Callback() { - @Override - public void beforeNotify(Report report) { - report.setApiKey("newapikey"); - } + assertTrue(bugsnag.notify(new Throwable(), report -> { + report.setApiKey("newapikey"); + return true; })); } @Test public void testCallbackOrder() { - bugsnag.addCallback(new Callback() { - @Override - public void beforeNotify(Report report) { - report.setApiKey("newapikey"); - } + bugsnag.addCallback(report -> { + report.setApiKey("newapikey"); + return true; }); - bugsnag.addCallback(new Callback() { - @Override - public void beforeNotify(Report report) { - report.setApiKey("secondnewapikey"); - } + bugsnag.addCallback(report -> { + report.setApiKey("secondnewapikey"); + return true; }); bugsnag.setDelivery(new Delivery() { @Override @@ -377,11 +358,9 @@ public void close() { @Test public void testCallbackCancel() { bugsnag.setDelivery(BugsnagTestUtils.generateDelivery()); - bugsnag.addCallback(new Callback() { - @Override - public void beforeNotify(Report report) { - report.cancel(); - } + bugsnag.addCallback(report -> { + report.cancel(); + return true; // cancellation flag respected }); // Test the report is not sent assertFalse(bugsnag.notify(new Throwable())); diff --git a/bugsnag/src/test/java/com/bugsnag/CallbackSuppressionTest.java b/bugsnag/src/test/java/com/bugsnag/CallbackSuppressionTest.java new file mode 100644 index 00000000..3de59d54 --- /dev/null +++ b/bugsnag/src/test/java/com/bugsnag/CallbackSuppressionTest.java @@ -0,0 +1,48 @@ +package com.bugsnag; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +public class CallbackSuppressionTest { + + private Bugsnag bugsnag; + private StubNotificationDelivery delivery; + + /** + * Set up test fixtures. + */ + @Before + public void setUp() { + bugsnag = new Bugsnag("apikey"); + delivery = new StubNotificationDelivery(); + bugsnag.setDelivery(delivery); + } + + @After + public void tearDown() { + bugsnag.close(); + } + + @Test + public void callbackReturningFalseSuppressesDelivery() { + bugsnag.addCallback(report -> false); // explicit suppression + + boolean result = bugsnag.notify(new RuntimeException("Suppressed")); + assertFalse("notify should return false when suppressed", result); + assertEquals("No notifications should be delivered", 0, delivery.getNotifications().size()); + } + + @Test + public void callbackReturningTrueAllowsDelivery() { + bugsnag.addCallback(report -> true); // allow + + boolean result = bugsnag.notify(new RuntimeException("Allowed")); + assertTrue(result); + assertEquals(1, delivery.getNotifications().size()); + } +} diff --git a/bugsnag/src/test/java/com/bugsnag/ConcurrentCallbackTest.java b/bugsnag/src/test/java/com/bugsnag/ConcurrentCallbackTest.java index dfbe2d31..ce6f8f50 100644 --- a/bugsnag/src/test/java/com/bugsnag/ConcurrentCallbackTest.java +++ b/bugsnag/src/test/java/com/bugsnag/ConcurrentCallbackTest.java @@ -1,7 +1,5 @@ package com.bugsnag; -import com.bugsnag.callbacks.Callback; - import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -28,16 +26,11 @@ public void closeBugsnag() { public void testClientNotifyModification() { final Configuration config = bugsnag.getConfig(); - config.addCallback(new Callback() { - @Override - public void beforeNotify(Report report) { - // modify the callback collection, when iterating to the next callback this should not crash - config.addCallback(new Callback() { - @Override - public void beforeNotify(Report report) { - } - }); - } + config.addCallback(report -> { + // modify the callback collection, when iterating to the next callback this + // should not crash + config.addCallback(r -> true); + return true; }); bugsnag.notify(new RuntimeException()); } diff --git a/bugsnag/src/test/java/com/bugsnag/ExceptionTest.java b/bugsnag/src/test/java/com/bugsnag/ExceptionTest.java index 861e1e36..918e04e9 100644 --- a/bugsnag/src/test/java/com/bugsnag/ExceptionTest.java +++ b/bugsnag/src/test/java/com/bugsnag/ExceptionTest.java @@ -5,7 +5,6 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; -import com.bugsnag.callbacks.Callback; import com.bugsnag.delivery.Delivery; import com.bugsnag.serialization.Serializer; @@ -60,29 +59,26 @@ public void deliver(Serializer serializer, Object object, Map he public void close() { } }); - assertTrue(bugsnag.notify(ogThrowable, new Callback() { - @Override - public void beforeNotify(Report report) { - try { - assertEquals(ogThrowable, report.getException()); - assertEquals("Test", report.getExceptionMessage()); - assertEquals("java.lang.RuntimeException", report.getExceptionName()); - - report.setExceptionName("Foo"); - assertEquals("Foo", report.getExceptionName()); - - - List exceptions = report.getExceptions(); - assertEquals(1, exceptions.size()); - - Exception exception = exceptions.get(0); - assertNotNull(exception); - assertEquals("Foo", exception.getErrorClass()); - assertEquals("Test", exception.getMessage()); - } catch (Throwable throwable) { - report.cancel(); - } + assertTrue(bugsnag.notify(ogThrowable, report -> { + try { + assertEquals(ogThrowable, report.getException()); + assertEquals("Test", report.getExceptionMessage()); + assertEquals("java.lang.RuntimeException", report.getExceptionName()); + + report.setExceptionName("Foo"); + assertEquals("Foo", report.getExceptionName()); + + List exceptions = report.getExceptions(); + assertEquals(1, exceptions.size()); + + Exception exception = exceptions.get(0); + assertNotNull(exception); + assertEquals("Foo", exception.getErrorClass()); + assertEquals("Test", exception.getMessage()); + } catch (Throwable throwable) { + report.cancel(); } + return !report.getShouldCancel(); })); bugsnag.close(); diff --git a/bugsnag/src/test/java/com/bugsnag/JakartaServletCallbackTest.java b/bugsnag/src/test/java/com/bugsnag/JakartaServletCallbackTest.java index 00ad7997..f71d0a61 100644 --- a/bugsnag/src/test/java/com/bugsnag/JakartaServletCallbackTest.java +++ b/bugsnag/src/test/java/com/bugsnag/JakartaServletCallbackTest.java @@ -83,7 +83,7 @@ public void closeBugsnag() { public void testRequestMetadataAdded() { Report report = generateReport(new java.lang.Exception("Spline reticulation failed")); JakartaServletCallback callback = new JakartaServletCallback(); - callback.beforeNotify(report); + callback.onError(report); Map metadata = report.getMetadata(); assertTrue(metadata.containsKey("request")); @@ -120,7 +120,7 @@ public void testRequestMetadataAdded() { public void testRequestContextSet() { Report report = generateReport(new java.lang.Exception("Spline reticulation failed")); JakartaServletCallback callback = new JakartaServletCallback(); - callback.beforeNotify(report); + callback.onError(report); assertEquals("PATCH /foo/bar", report.getContext()); } @@ -130,7 +130,7 @@ public void testExistingContextNotOverridden() { Report report = generateReport(new java.lang.Exception("Spline reticulation failed")); report.setContext("Honey nut corn flakes"); JakartaServletCallback callback = new JakartaServletCallback(); - callback.beforeNotify(report); + callback.onError(report); assertEquals("Honey nut corn flakes", report.getContext()); } diff --git a/bugsnag/src/test/java/com/bugsnag/MarkerTest.java b/bugsnag/src/test/java/com/bugsnag/MarkerTest.java index f746cedd..69f62666 100644 --- a/bugsnag/src/test/java/com/bugsnag/MarkerTest.java +++ b/bugsnag/src/test/java/com/bugsnag/MarkerTest.java @@ -13,7 +13,6 @@ import java.util.Iterator; - /** * Tests for the Bugsnag Marker internal logic */ @@ -27,12 +26,7 @@ public class MarkerTest { */ @Before public void createMarker() { - callback = new Callback() { - @Override - public void beforeNotify(Report report) { - - } - }; + callback = report -> true; marker = new BugsnagMarker(callback); } diff --git a/bugsnag/src/test/java/com/bugsnag/SessionTrackerTest.java b/bugsnag/src/test/java/com/bugsnag/SessionTrackerTest.java index d1dcf9ec..872b0956 100644 --- a/bugsnag/src/test/java/com/bugsnag/SessionTrackerTest.java +++ b/bugsnag/src/test/java/com/bugsnag/SessionTrackerTest.java @@ -21,7 +21,6 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicInteger; - public class SessionTrackerTest { private SessionTracker sessionTracker; @@ -185,7 +184,6 @@ public void deliver(Serializer serializer, Object object, Map he super.deliver(serializer, object, headers); SessionPayload payload = (SessionPayload) object; - List sessionCounts = (List) payload.getSessionCounts(); assertEquals(3, sessionCounts.size()); @@ -284,7 +282,8 @@ public void deliver(Serializer serializer, Object object, Map he @Test public void zeroSessionCount() { - CustomDelivery sessionDelivery = new CustomDelivery() {}; + CustomDelivery sessionDelivery = new CustomDelivery() { + }; configuration.sessionDelivery = sessionDelivery; sessionTracker.flushSessions(new Date(10120000L)); sessionTracker.flushSessions(new Date(14000000L)); @@ -300,7 +299,8 @@ public void testSessionShutdownStartSession() { @Test public void testSessionShutdownDelivers() { - CustomDelivery delivery = new CustomDelivery() {}; + CustomDelivery delivery = new CustomDelivery() { + }; configuration.sessionDelivery = delivery; sessionTracker.startSession(new Date(), true); @@ -311,7 +311,8 @@ public void testSessionShutdownDelivers() { @Test public void testMultiShutdown() { - CustomDelivery delivery = new CustomDelivery() {}; + CustomDelivery delivery = new CustomDelivery() { + }; configuration.sessionDelivery = delivery; sessionTracker.startSession(new Date(), true); @@ -321,6 +322,35 @@ public void testMultiShutdown() { assertEquals(1, delivery.count.get()); } + @Test + public void sessionDeliverySuppressedByCallback() { + // Set up a delivery stub which SHOULD NOT be invoked + CustomDelivery delivery = new CustomDelivery() { + @Override + public void deliver(Serializer serializer, Object object, Map headers) { + super.deliver(serializer, object, headers); + fail("Delivery should be suppressed by OnSession callback returning false"); + } + }; + configuration.sessionDelivery = delivery; + + // Add callback which returns false to suppress sending + sessionTracker.addOnSession(new OnSession() { + @Override + public boolean onSession(SessionPayload payload) { + return false; // suppress delivery + } + }); + + // Start a session and flush far enough in future to trigger send attempt + sessionTracker.startSession(new Date(10000000L), false); + sessionTracker.flushSessions(new Date(13600000L)); // different batch period + + // Verify delivery was NOT performed + assertFalse(delivery.delivered); + assertEquals(0, delivery.count.get()); + } + abstract static class CustomDelivery implements Delivery { boolean delivered; AtomicInteger count = new AtomicInteger(0); diff --git a/examples/logback/src/main/java/com/bugsnag/example/logback/cli/Application.java b/examples/logback/src/main/java/com/bugsnag/example/logback/cli/Application.java index 08b77577..a15208c1 100644 --- a/examples/logback/src/main/java/com/bugsnag/example/logback/cli/Application.java +++ b/examples/logback/src/main/java/com/bugsnag/example/logback/cli/Application.java @@ -16,7 +16,8 @@ public class Application { public static void main(String[] args) throws Exception { - ch.qos.logback.classic.Logger rootLogger = (ch.qos.logback.classic.Logger)LoggerFactory.getLogger(org.slf4j.Logger.ROOT_LOGGER_NAME); + ch.qos.logback.classic.Logger rootLogger = (ch.qos.logback.classic.Logger) LoggerFactory + .getLogger(org.slf4j.Logger.ROOT_LOGGER_NAME); Appender appender = rootLogger.getAppender("BUGSNAG"); if (appender instanceof BugsnagAppender) { // Set some global meta data (added to each report) @@ -28,6 +29,7 @@ public static void main(String[] args) throws Exception { report.setUserName("User Name"); report.setUserEmail("user@example.com"); report.setUserId("12345"); + return true; }); } @@ -58,6 +60,7 @@ public static void main(String[] args) throws Exception { LOGGER.warn(new BugsnagMarker((report) -> { report.addToTab("report tab", "data key 1", "data value 1"); report.addToTab("report tab", "data key 2", "data value 2"); + return true; }), "Something bad happened", e); } @@ -76,7 +79,8 @@ public void run() { // Wait for unhandled exception thread to finish before exiting thread.join(); - // Remove the thread metadata so it won't be added to future reports on this thread + // Remove the thread metadata so it won't be added to future reports on this + // thread Bugsnag.clearThreadMetadata(); // Exit the application diff --git a/examples/simple/src/main/java/com/bugsnag/example/simple/ExampleApp.java b/examples/simple/src/main/java/com/bugsnag/example/simple/ExampleApp.java index cfb24441..41059c11 100644 --- a/examples/simple/src/main/java/com/bugsnag/example/simple/ExampleApp.java +++ b/examples/simple/src/main/java/com/bugsnag/example/simple/ExampleApp.java @@ -22,7 +22,7 @@ public static void main(String[] args) throws InterruptedException { // the lifecyle of your application bugsnag.addCallback(new Callback() { @Override - public void beforeNotify(Report report) { + public boolean onError(Report report) { report.addToTab("diagnostics", "timestamp", new Date()); report.addToTab("customer", "name", "acme-inc"); report.addToTab("customer", "paying", true); @@ -30,6 +30,7 @@ public void beforeNotify(Report report) { report.setUserName("User Name"); report.setUserEmail("user@example.com"); report.setUserId("12345"); + return true; } }); @@ -53,10 +54,11 @@ public void beforeNotify(Report report) { } catch (RuntimeException e) { bugsnag.notify(e, new Callback() { @Override - public void beforeNotify(Report report) { + public boolean onError(Report report) { report.setSeverity(Severity.WARNING); report.addToTab("report", "something", "that happened"); report.setContext("the context"); + return true; } }); } diff --git a/examples/spring-web/src/main/java/com/bugsnag/example/spring/web/ApplicationRestController.java b/examples/spring-web/src/main/java/com/bugsnag/example/spring/web/ApplicationRestController.java index df5a5796..584934d8 100644 --- a/examples/spring-web/src/main/java/com/bugsnag/example/spring/web/ApplicationRestController.java +++ b/examples/spring-web/src/main/java/com/bugsnag/example/spring/web/ApplicationRestController.java @@ -71,10 +71,11 @@ public String sendHandledExceptionWithMetadata() { } catch (RuntimeException e) { bugsnag.notify(e, new Callback() { @Override - public void beforeNotify(Report report) { + public boolean onError(Report report) { report.setSeverity(Severity.WARNING); report.addToTab("report", "something", "that happened"); report.setContext("the context"); + return true; } }); } diff --git a/examples/spring-web/src/main/java/com/bugsnag/example/spring/web/Config.java b/examples/spring-web/src/main/java/com/bugsnag/example/spring/web/Config.java index 0481f59f..e7385514 100644 --- a/examples/spring-web/src/main/java/com/bugsnag/example/spring/web/Config.java +++ b/examples/spring-web/src/main/java/com/bugsnag/example/spring/web/Config.java @@ -31,7 +31,7 @@ public Bugsnag bugsnag() { // the lifecyle of your application bugsnag.addCallback(new Callback() { @Override - public void beforeNotify(Report report) { + public boolean onError(Report report) { report.addToTab("diagnostics", "timestamp", new Date()); report.addToTab("customer", "name", "acme-inc"); report.addToTab("customer", "paying", true); @@ -39,6 +39,7 @@ public void beforeNotify(Report report) { report.setUserName("User Name"); report.setUserEmail("user@example.com"); report.setUserId("12345"); + return true; } }); diff --git a/examples/spring/src/main/java/com/bugsnag/example/spring/cli/ApplicationCommandLineRunner.java b/examples/spring/src/main/java/com/bugsnag/example/spring/cli/ApplicationCommandLineRunner.java index 6e201859..2f26233d 100644 --- a/examples/spring/src/main/java/com/bugsnag/example/spring/cli/ApplicationCommandLineRunner.java +++ b/examples/spring/src/main/java/com/bugsnag/example/spring/cli/ApplicationCommandLineRunner.java @@ -50,10 +50,11 @@ public void run(final String... args) throws Exception { } catch (RuntimeException e) { bugsnag.notify(e, new Callback() { @Override - public void beforeNotify(Report report) { + public boolean onError(Report report) { report.setSeverity(Severity.WARNING); report.addToTab("report", "something", "that happened"); report.setContext("the context"); + return true; } }); } diff --git a/examples/spring/src/main/java/com/bugsnag/example/spring/cli/Config.java b/examples/spring/src/main/java/com/bugsnag/example/spring/cli/Config.java index 7921655a..3aff0375 100644 --- a/examples/spring/src/main/java/com/bugsnag/example/spring/cli/Config.java +++ b/examples/spring/src/main/java/com/bugsnag/example/spring/cli/Config.java @@ -15,7 +15,8 @@ @Import(BugsnagSpringConfiguration.class) public class Config { - // Define singleton bean "bugsnag" which can be injected into any Spring managed class with @Autowired. + // Define singleton bean "bugsnag" which can be injected into any Spring managed + // class with @Autowired. @Bean public Bugsnag bugsnag() { // Create a Bugsnag client @@ -31,7 +32,7 @@ public Bugsnag bugsnag() { // the lifecyle of your application bugsnag.addCallback(new Callback() { @Override - public void beforeNotify(Report report) { + public boolean onError(Report report) { report.addToTab("diagnostics", "timestamp", new Date()); report.addToTab("customer", "name", "acme-inc"); report.addToTab("customer", "paying", true); @@ -39,6 +40,7 @@ public void beforeNotify(Report report) { report.setUserName("User Name"); report.setUserEmail("user@example.com"); report.setUserId("12345"); + return true; } }); diff --git a/features/fixtures/mazerunnerspringboot3/src/main/java/com/bugsnag/mazerunner/scenarios/ScheduledTaskExecutorScenario.java b/features/fixtures/mazerunnerspringboot3/src/main/java/com/bugsnag/mazerunner/scenarios/ScheduledTaskExecutorScenario.java index 5dc877b2..3ab87cd8 100644 --- a/features/fixtures/mazerunnerspringboot3/src/main/java/com/bugsnag/mazerunner/scenarios/ScheduledTaskExecutorScenario.java +++ b/features/fixtures/mazerunnerspringboot3/src/main/java/com/bugsnag/mazerunner/scenarios/ScheduledTaskExecutorScenario.java @@ -27,9 +27,10 @@ public void run() { final Collection threadnames = ScheduledTaskExecutorService.getThreadNames(); bugsnag.notify(new RuntimeException("Whoops"), new Callback() { @Override - public void beforeNotify(Report report) { + public boolean onError(Report report) { report.addToTab("executor", "multiThreaded", threadnames.size() > 1); report.addToTab("executor", "names", threadnames); + return true; } }); } diff --git a/features/fixtures/scenarios/src/main/java/com/bugsnag/mazerunner/scenarios/AutoRedactScenario.java b/features/fixtures/scenarios/src/main/java/com/bugsnag/mazerunner/scenarios/AutoRedactScenario.java index bfafab71..3615278c 100644 --- a/features/fixtures/scenarios/src/main/java/com/bugsnag/mazerunner/scenarios/AutoRedactScenario.java +++ b/features/fixtures/scenarios/src/main/java/com/bugsnag/mazerunner/scenarios/AutoRedactScenario.java @@ -17,10 +17,11 @@ public AutoRedactScenario(Bugsnag bugsnag) { public void run() { bugsnag.notify(generateException(), new Callback() { @Override - public void beforeNotify(Report report) { + public boolean onError(Report report) { report.addToTab("user", "password", "hunter2"); report.addToTab("custom", "password", "hunter2"); report.addToTab("custom", "foo", "hunter2"); + return true; } }); } diff --git a/features/fixtures/scenarios/src/main/java/com/bugsnag/mazerunner/scenarios/LogbackMetadataScenario.java b/features/fixtures/scenarios/src/main/java/com/bugsnag/mazerunner/scenarios/LogbackMetadataScenario.java index 37bd1ad7..4f19a002 100644 --- a/features/fixtures/scenarios/src/main/java/com/bugsnag/mazerunner/scenarios/LogbackMetadataScenario.java +++ b/features/fixtures/scenarios/src/main/java/com/bugsnag/mazerunner/scenarios/LogbackMetadataScenario.java @@ -22,12 +22,13 @@ public LogbackMetadataScenario(Bugsnag bugsnag) { @Override public void run() { LOGGER.warn(new BugsnagMarker(new Callback() { - @Override - public void beforeNotify(Report report) { - report.addToTab("user", "foo", "hunter2"); - report.addToTab("custom", "foo", "hunter2"); - report.addToTab("custom", "bar", "hunter2"); - } - }),"Error sent to Bugsnag using the logback appender", generateException()); + @Override + public boolean onError(Report report) { + report.addToTab("user", "foo", "hunter2"); + report.addToTab("custom", "foo", "hunter2"); + report.addToTab("custom", "bar", "hunter2"); + return true; + } + }), "Error sent to Bugsnag using the logback appender", generateException()); } } diff --git a/features/fixtures/scenarios/src/main/java/com/bugsnag/mazerunner/scenarios/ManualContextScenario.java b/features/fixtures/scenarios/src/main/java/com/bugsnag/mazerunner/scenarios/ManualContextScenario.java index 2f518812..b25b8425 100644 --- a/features/fixtures/scenarios/src/main/java/com/bugsnag/mazerunner/scenarios/ManualContextScenario.java +++ b/features/fixtures/scenarios/src/main/java/com/bugsnag/mazerunner/scenarios/ManualContextScenario.java @@ -17,8 +17,9 @@ public ManualContextScenario(Bugsnag bugsnag) { public void run() { bugsnag.notify(generateException(), new Callback() { @Override - public void beforeNotify(Report report) { + public boolean onError(Report report) { report.setContext("FooContext"); + return true; } }); } diff --git a/features/fixtures/scenarios/src/main/java/com/bugsnag/mazerunner/scenarios/ManualRedactScenario.java b/features/fixtures/scenarios/src/main/java/com/bugsnag/mazerunner/scenarios/ManualRedactScenario.java index 22685510..b518d3dd 100644 --- a/features/fixtures/scenarios/src/main/java/com/bugsnag/mazerunner/scenarios/ManualRedactScenario.java +++ b/features/fixtures/scenarios/src/main/java/com/bugsnag/mazerunner/scenarios/ManualRedactScenario.java @@ -20,10 +20,11 @@ public void run() { bugsnag.notify(generateException(), new Callback() { @Override - public void beforeNotify(Report report) { + public boolean onError(Report report) { report.addToTab("user", "foo", "hunter2"); report.addToTab("custom", "foo", "hunter2"); report.addToTab("custom", "bar", "hunter2"); + return true; } }); } diff --git a/features/fixtures/scenarios/src/main/java/com/bugsnag/mazerunner/scenarios/MetadataScenario.java b/features/fixtures/scenarios/src/main/java/com/bugsnag/mazerunner/scenarios/MetadataScenario.java index e639c540..afe44e3e 100644 --- a/features/fixtures/scenarios/src/main/java/com/bugsnag/mazerunner/scenarios/MetadataScenario.java +++ b/features/fixtures/scenarios/src/main/java/com/bugsnag/mazerunner/scenarios/MetadataScenario.java @@ -17,8 +17,9 @@ public MetadataScenario(Bugsnag bugsnag) { public void run() { bugsnag.notify(generateException(), new Callback() { @Override - public void beforeNotify(Report report) { + public boolean onError(Report report) { report.addToTab("Custom", "foo", "Hello World!"); + return true; } }); } diff --git a/features/fixtures/scenarios/src/main/java/com/bugsnag/mazerunner/scenarios/ThreadMetadataScenario.java b/features/fixtures/scenarios/src/main/java/com/bugsnag/mazerunner/scenarios/ThreadMetadataScenario.java index 254718fa..81252d8c 100644 --- a/features/fixtures/scenarios/src/main/java/com/bugsnag/mazerunner/scenarios/ThreadMetadataScenario.java +++ b/features/fixtures/scenarios/src/main/java/com/bugsnag/mazerunner/scenarios/ThreadMetadataScenario.java @@ -18,9 +18,10 @@ public void run() { // Global callback metadata has lowest precedence bugsnag.addCallback(new Callback() { @Override - public void beforeNotify(Report report) { + public boolean onError(Report report) { report.addToTab("Custom", "test", "Global value"); report.addToTab("Custom", "foo", "Global value to be overwritten"); + return true; } }); @@ -47,8 +48,9 @@ public void run() { // Report-specific metadata should merge with global + thread metadata and overwrite when duplicate key bugsnag.notify(generateException(), new Callback() { @Override - public void beforeNotify(Report report) { + public boolean onError(Report report) { report.addToTab("Custom", "bar", "Hello World!"); + return true; } }); } diff --git a/features/fixtures/scenarios/src/main/java/com/bugsnag/mazerunner/scenarios/UnhandledThreadMetadataScenario.java b/features/fixtures/scenarios/src/main/java/com/bugsnag/mazerunner/scenarios/UnhandledThreadMetadataScenario.java index c8c3dbba..f4b9afe4 100644 --- a/features/fixtures/scenarios/src/main/java/com/bugsnag/mazerunner/scenarios/UnhandledThreadMetadataScenario.java +++ b/features/fixtures/scenarios/src/main/java/com/bugsnag/mazerunner/scenarios/UnhandledThreadMetadataScenario.java @@ -18,9 +18,10 @@ public void run() { // Global callback metadata has lowest precedence bugsnag.addCallback(new Callback() { @Override - public void beforeNotify(Report report) { + public boolean onError(Report report) { report.addToTab("Custom", "test", "Global value"); report.addToTab("Custom", "foo", "Global value to be overwritten"); + return true; } }); diff --git a/features/fixtures/scenarios/src/main/java/com/bugsnag/mazerunner/scenarios/UserCallbackScenario.java b/features/fixtures/scenarios/src/main/java/com/bugsnag/mazerunner/scenarios/UserCallbackScenario.java index 52289a2b..61ad3ce7 100644 --- a/features/fixtures/scenarios/src/main/java/com/bugsnag/mazerunner/scenarios/UserCallbackScenario.java +++ b/features/fixtures/scenarios/src/main/java/com/bugsnag/mazerunner/scenarios/UserCallbackScenario.java @@ -17,8 +17,9 @@ public UserCallbackScenario(Bugsnag bugsnag) { public void run() { bugsnag.notify(generateException(), new Callback() { @Override - public void beforeNotify(Report report) { + public boolean onError(Report report) { report.setUser("Agent Pink", "bob@example.com", "Zebedee"); + return true; } }); }