diff --git a/src/main/java/org/toop/Logging.java b/src/main/java/org/toop/Logging.java
index f60c6d1..2810016 100644
--- a/src/main/java/org/toop/Logging.java
+++ b/src/main/java/org/toop/Logging.java
@@ -6,8 +6,18 @@ import org.apache.logging.log4j.core.LoggerContext;
import org.apache.logging.log4j.core.config.Configuration;
import org.apache.logging.log4j.core.config.LoggerConfig;
-/** Options for logging. */
+/**
+ * Utility class for configuring logging levels dynamically at runtime using Log4j 2.
+ *
+ * Provides methods to enable or disable logs globally or per class, with support for
+ * specifying log levels either via {@link Level} enums or string names.
+ *
+ */
public final class Logging {
+
+ /**
+ * Disables all logging globally by setting the root logger level to {@link Level#OFF}.
+ */
public static void disableAllLogs() {
LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
Configuration config = ctx.getConfiguration();
@@ -16,6 +26,22 @@ public final class Logging {
ctx.updateLoggers();
}
+ /**
+ * Enables all logging globally by setting the root logger level to {@link Level#ALL}.
+ */
+ public static void enableAllLogs() {
+ LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
+ Configuration config = ctx.getConfiguration();
+ LoggerConfig rootLoggerConfig = config.getRootLogger();
+ rootLoggerConfig.setLevel(Level.ALL);
+ ctx.updateLoggers();
+ }
+
+ /**
+ * Enables global logging at a specific level by setting the root logger.
+ *
+ * @param level the logging level to enable for all logs
+ */
public static void enableAllLogs(Level level) {
LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
Configuration config = ctx.getConfiguration();
@@ -24,48 +50,157 @@ public final class Logging {
ctx.updateLoggers();
}
- public static void disableLogsForClass(Class class_) {
+ /**
+ * Verifies whether the provided string corresponds to a valid class name.
+ *
+ * @param className fully-qualified class name to check
+ * @return true if the class exists, false otherwise
+ */
+ private static boolean verifyStringIsActualClass(String className) {
+ try {
+ Class.forName(className);
+ return true;
+ } catch (ClassNotFoundException e) {
+ return false;
+ }
+ }
+
+ /**
+ * Internal helper to disable logs for a specific class by name.
+ *
+ * @param className fully-qualified class name
+ */
+ private static void disableLogsForClassInternal(String className) {
LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
Configuration config = ctx.getConfiguration();
- LoggerConfig specificConfig = new LoggerConfig(class_.getName(), Level.OFF, true);
- config.addLogger(class_.getName(), specificConfig);
+ config.removeLogger(className);
+ LoggerConfig specificConfig = new LoggerConfig(className, Level.OFF, false);
+ config.addLogger(className, specificConfig);
ctx.updateLoggers();
}
- public static void enableLogsForClass(Class class_, Level levelToLog) {
+ /**
+ * Disables logs for a specific class.
+ *
+ * @param class_ the class for which logs should be disabled
+ * @param type of the class
+ */
+ public static void disableLogsForClass(Class class_) {
+ disableLogsForClassInternal(class_.getName());
+ }
+
+ /**
+ * Disables logs for a class specified by fully-qualified name, if the class exists.
+ *
+ * @param className fully-qualified class name
+ */
+ public static void disableLogsForClass(String className) {
+ if (verifyStringIsActualClass(className)) {
+ disableLogsForClassInternal(className);
+ }
+ }
+
+ /**
+ * Internal helper to enable logs for a specific class at a specific level.
+ *
+ * @param className fully-qualified class name
+ * @param level logging level to set
+ */
+ private static void enableLogsForClassInternal(String className, Level level) {
LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
Configuration config = ctx.getConfiguration();
- LoggerConfig loggerConfig = config.getLoggers().get(class_.getName());
+ LoggerConfig loggerConfig = config.getLoggers().get(className);
if (loggerConfig == null) {
- loggerConfig = new LoggerConfig(class_.getName(), levelToLog, true);
- config.addLogger(class_.getName(), loggerConfig);
+ loggerConfig = new LoggerConfig(className, level, false);
+ config.addLogger(className, loggerConfig);
} else {
- loggerConfig.setLevel(levelToLog);
+ loggerConfig.setLevel(level);
}
ctx.updateLoggers();
}
+ /**
+ * Enables logging for a class at a specific level.
+ *
+ * @param class_ class to configure
+ * @param levelToLog the logging level to set
+ * @param type of the class
+ */
+ public static void enableLogsForClass(Class class_, Level levelToLog) {
+ enableLogsForClassInternal(class_.getName(), levelToLog);
+ }
+
+ /**
+ * Enables logging for a class specified by name at a specific level, if the class exists.
+ *
+ * @param className fully-qualified class name
+ * @param levelToLog the logging level to set
+ */
+ public static void enableLogsForClass(String className, Level levelToLog) {
+ if (verifyStringIsActualClass(className)) {
+ enableLogsForClassInternal(className, levelToLog);
+ }
+ }
+
+ /**
+ * Enables logging for a class specified by name at a specific level using a string.
+ *
+ * @param className fully-qualified class name
+ * @param levelToLog name of the logging level (e.g., "DEBUG", "INFO")
+ */
+ public static void enableLogsForClass(String className, String levelToLog) {
+ Level level = Level.valueOf(levelToLog.trim().toUpperCase());
+ if (level != null && verifyStringIsActualClass(className)) {
+ enableLogsForClassInternal(className, level);
+ }
+ }
+
+ /** Convenience methods for enabling logs at specific levels for classes. */
public static void enableAllLogsForClass(Class class_) {
enableLogsForClass(class_, Level.ALL);
}
+ public static void enableAllLogsForClass(String className) {
+ enableLogsForClass(className, Level.ALL);
+ }
+
public static void enableDebugLogsForClass(Class class_) {
enableLogsForClass(class_, Level.DEBUG);
}
+ public static void enableDebugLogsForClass(String className) {
+ enableLogsForClass(className, Level.DEBUG);
+ }
+
public static void enableErrorLogsForClass(Class class_) {
enableLogsForClass(class_, Level.ERROR);
}
+ public static void enableErrorLogsForClass(String className) {
+ enableLogsForClass(className, Level.ERROR);
+ }
+
public static void enableFatalLogsForClass(Class class_) {
enableLogsForClass(class_, Level.FATAL);
}
+ public static void enableFatalLogsForClass(String className) {
+ enableLogsForClass(className, Level.FATAL);
+ }
+
public static void enableInfoLogsForClass(Class class_) {
enableLogsForClass(class_, Level.INFO);
}
+ public static void enableInfoLogsForClass(String className) {
+ enableLogsForClass(className, Level.INFO);
+ }
+
public static void enableTraceLogsForClass(Class class_) {
enableLogsForClass(class_, Level.TRACE);
}
+
+ public static void enableTraceLogsForClass(String className) {
+ enableLogsForClass(className, Level.TRACE);
+ }
}
diff --git a/src/test/java/org/toop/LoggingTest.java b/src/test/java/org/toop/LoggingTest.java
new file mode 100644
index 0000000..dda0202
--- /dev/null
+++ b/src/test/java/org/toop/LoggingTest.java
@@ -0,0 +1,104 @@
+package org.toop;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.core.LoggerContext;
+import org.apache.logging.log4j.core.config.LoggerConfig;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+public class LoggingTest {
+
+ private LoggerContext ctx;
+
+ @BeforeEach
+ void setUp() {
+ ctx = (LoggerContext) LogManager.getContext(false);
+ Logging.enableAllLogs(Level.DEBUG); // reset root logger before each test
+ }
+
+ @AfterEach
+ void tearDown() {
+ Logging.enableAllLogs(Level.DEBUG); // restore root logger after each test
+ }
+
+ @Test
+ void testDisableAllLogs_setsRootLevelOff() {
+ Logging.disableAllLogs();
+
+ LoggerConfig rootConfig = ctx.getConfiguration().getRootLogger();
+ assertEquals(Level.OFF, rootConfig.getLevel());
+ }
+
+ @Test
+ void testEnableAllLogs_setsRootLevelAll() {
+ Logging.enableAllLogs();
+
+ LoggerConfig rootConfig = ctx.getConfiguration().getRootLogger();
+ assertEquals(Level.ALL, rootConfig.getLevel());
+ }
+
+ @Test
+ void testEnableAllLogs_LevelParam_setsRootLevel() {
+ Logging.enableAllLogs(Level.WARN);
+
+ LoggerConfig rootConfig = ctx.getConfiguration().getRootLogger();
+ assertEquals(Level.WARN, rootConfig.getLevel());
+ }
+
+ @Test
+ void testDisableLogsForClass_addsLoggerWithOff() {
+ Logging.disableLogsForClass(LoggingTest.class);
+
+ LoggerConfig loggerConfig = ctx.getConfiguration().getLoggers().get(LoggingTest.class.getName());
+ assertNotNull(loggerConfig);
+ assertEquals(Level.OFF, loggerConfig.getLevel());
+ }
+
+ @Test
+ void testEnableLogsForClass_addsLoggerWithLevel() {
+ Logging.enableLogsForClass(LoggingTest.class, Level.ERROR);
+
+ LoggerConfig loggerConfig = ctx.getConfiguration().getLoggers().get(LoggingTest.class.getName());
+ assertNotNull(loggerConfig);
+ assertEquals(Level.ERROR, loggerConfig.getLevel());
+ }
+
+ @Test
+ void testEnableLogsForClass_withStringLevel() {
+ Logging.enableLogsForClass(LoggingTest.class.getName(), "INFO");
+
+ LoggerConfig loggerConfig = ctx.getConfiguration().getLoggers().get(LoggingTest.class.getName());
+ assertNotNull(loggerConfig);
+ assertEquals(Level.INFO, loggerConfig.getLevel());
+ }
+
+ @Test
+ void testEnableDebugLogsForClass_setsDebug() {
+ Logging.enableDebugLogsForClass(LoggingTest.class);
+
+ LoggerConfig loggerConfig = ctx.getConfiguration().getLoggers().get(LoggingTest.class.getName());
+ assertNotNull(loggerConfig);
+ assertEquals(Level.DEBUG, loggerConfig.getLevel());
+ }
+
+ @Test
+ void testEnableInfoLogsForClass_setsInfo() {
+ Logging.enableInfoLogsForClass(LoggingTest.class);
+
+ LoggerConfig loggerConfig = ctx.getConfiguration().getLoggers().get(LoggingTest.class.getName());
+ assertNotNull(loggerConfig);
+ assertEquals(Level.INFO, loggerConfig.getLevel());
+ }
+
+ @Test
+ void testDisableLogsForNonexistentClass_doesNothing() {
+ Logging.disableLogsForClass("org.toop.DoesNotExist");
+
+ LoggerConfig loggerConfig = ctx.getConfiguration().getLoggers().get("org.toop.DoesNotExist");
+ assertNull(loggerConfig); // class doesn't exist, so no logger added
+ }
+}
\ No newline at end of file