From d6a19daca97f341c4259607dcfb4364b8c0df25f Mon Sep 17 00:00:00 2001 From: Aman Nijhawan Date: Thu, 26 Sep 2024 13:59:55 +0000 Subject: [PATCH] [PLAT-15377] Adding a global uncaught exception handler to yugaware Summary: [PLAT-15377] Adding a global uncaught exception handler to yugaware Test Plan: build locally, phabricator Reviewers: sanketh, svarshney, nsingh Reviewed By: svarshney, nsingh Subscribers: yugaware Differential Revision: https://phorge.dev.yugabyte.com/D38344 --- .../src/main/java/GlobalExceptionHandler.java | 20 +++++++++++++ managed/src/main/java/MainModule.java | 2 ++ .../yw/commissioner/TaskExecutor.java | 8 +++--- .../test/java/GlobalExceptionHandlerTest.java | 28 +++++++++++++++++++ 4 files changed, 54 insertions(+), 4 deletions(-) create mode 100644 managed/src/main/java/GlobalExceptionHandler.java create mode 100644 managed/src/test/java/GlobalExceptionHandlerTest.java diff --git a/managed/src/main/java/GlobalExceptionHandler.java b/managed/src/main/java/GlobalExceptionHandler.java new file mode 100644 index 000000000000..a67f9313d52b --- /dev/null +++ b/managed/src/main/java/GlobalExceptionHandler.java @@ -0,0 +1,20 @@ +// Copyright (c) Yugabyte, Inc. + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class GlobalExceptionHandler implements Thread.UncaughtExceptionHandler { + + private static Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class); + + // Added for test + public static void setLogger(Logger l) { + logger = l; + } + + @Override + public void uncaughtException(Thread t, Throwable e) { + // Log the exception + logger.error("Yugaware uncaught exception in thread '{}'", t.getName(), e); + } +} diff --git a/managed/src/main/java/MainModule.java b/managed/src/main/java/MainModule.java index 7e611753ef23..4795664821ed 100644 --- a/managed/src/main/java/MainModule.java +++ b/managed/src/main/java/MainModule.java @@ -135,6 +135,8 @@ public MainModule(Environment environment, Config config) { @Override public void configure() { + // Bind the uncaught exception handler at the application startup + Thread.setDefaultUncaughtExceptionHandler(new GlobalExceptionHandler()); bind(StaticInjectorHolder.class).asEagerSingleton(); bind(Long.class) .annotatedWith(Names.named("AppStartupTimeMs")) diff --git a/managed/src/main/java/com/yugabyte/yw/commissioner/TaskExecutor.java b/managed/src/main/java/com/yugabyte/yw/commissioner/TaskExecutor.java index 877ee1980cab..66818b0bfade 100644 --- a/managed/src/main/java/com/yugabyte/yw/commissioner/TaskExecutor.java +++ b/managed/src/main/java/com/yugabyte/yw/commissioner/TaskExecutor.java @@ -723,10 +723,10 @@ private void waitForSubTasks(boolean abortOnFailure) { anyEx = (anyEx != null) ? anyEx : thisEx; runnableSubTask.updateTaskDetailsOnError(TaskInfo.State.Aborted, thisEx); removeCompletedSubTask(iter, runnableSubTask, anyEx); - } catch (Exception e) { - anyEx = e; - runnableSubTask.updateTaskDetailsOnError(TaskInfo.State.Failure, e); - removeCompletedSubTask(iter, runnableSubTask, e); + } catch (Throwable th) { + anyEx = th; + runnableSubTask.updateTaskDetailsOnError(TaskInfo.State.Failure, th); + removeCompletedSubTask(iter, runnableSubTask, th); } } } diff --git a/managed/src/test/java/GlobalExceptionHandlerTest.java b/managed/src/test/java/GlobalExceptionHandlerTest.java new file mode 100644 index 000000000000..a38f01141a06 --- /dev/null +++ b/managed/src/test/java/GlobalExceptionHandlerTest.java @@ -0,0 +1,28 @@ +// Copyright (c) Yugabyte, Inc. + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; + +import org.junit.Test; +import org.slf4j.Logger; + +public class GlobalExceptionHandlerTest { + + @Test + public void testUncaughtExceptionLogsError() throws Exception { + Logger mockLogger = mock(Logger.class); + + // Create an instance of the handler + GlobalExceptionHandler handler = new GlobalExceptionHandler(); + GlobalExceptionHandler.setLogger(mockLogger); + + Thread thread = new Thread(() -> {}); + Throwable exception = new RuntimeException("Test exception"); + + handler.uncaughtException(thread, exception); + + // Verify that the logger was called with the expected message + verify(mockLogger) + .error("Yugaware uncaught exception in thread '{}'", thread.getName(), exception); + } +}