Skip to content

Instantly share code, notes, and snippets.

@mmdemirbas
Last active November 26, 2021 11:41
Show Gist options
  • Select an option

  • Save mmdemirbas/5411395 to your computer and use it in GitHub Desktop.

Select an option

Save mmdemirbas/5411395 to your computer and use it in GitHub Desktop.
Changing log level for logback-classic using reflection if it is present in the classpath without depending to the JAR.
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.text.MessageFormat;
/**
* Contains methods to access and manipulate logback framework dynamically at run-time. Here 'dynamically' means without
* referencing the logback JAR, but using it if found in the classpath.
*
* @author Muhammed Demirbas
* @since 19 Mar 2013
*/
public final class LogbackUtils
{
public static final String LOGBACK_CLASSIC = "ch.qos.logback.classic";
public static final String LOGBACK_CLASSIC_LOGGER = "ch.qos.logback.classic.Logger";
public static final String LOGBACK_CLASSIC_LEVEL = "ch.qos.logback.classic.Level";
private static final Logger logger = LoggerFactory.getLogger(LogbackUtils.class);
private LogbackUtils()
{
// Prevent instance creation
}
/**
* Dynamically sets the logback log level for the given class to the specified level.
*
* @param loggerName Name of the logger to set its log level. If blank, root logger will be used.
* @param logLevel One of the supported log levels: TRACE, DEBUG, INFO, WARN, ERROR, FATAL,
* OFF. {@code null} value is considered as 'OFF'.
*/
public static boolean setLogLevel(String loggerName, String logLevel)
{
String logLevelUpper = (logLevel == null) ? "OFF" : logLevel.toUpperCase();
try
{
Package logbackPackage = Package.getPackage(LOGBACK_CLASSIC);
if (logbackPackage == null)
{
logger.info("Logback is not in the classpath!");
return false;
}
// Use ROOT logger if given logger name is blank.
if ((loggerName == null) || loggerName.trim().isEmpty())
{
loggerName = (String) getFieldVaulue(LOGBACK_CLASSIC_LOGGER, "ROOT_LOGGER_NAME");
}
// Obtain logger by the name
Logger loggerObtained = LoggerFactory.getLogger(loggerName);
if (loggerObtained == null)
{
// I don't know if this case occurs
logger.warn("No logger for the name: {}", loggerName);
return false;
}
Object logLevelObj = getFieldVaulue(LOGBACK_CLASSIC_LEVEL, logLevelUpper);
if (logLevelObj == null)
{
logger.warn("No such log level: {}", logLevelUpper);
return false;
}
Class<?>[] paramTypes = { logLevelObj.getClass() };
Object[] params = { logLevelObj };
Class<?> clz = Class.forName(LOGBACK_CLASSIC_LOGGER);
Method method = clz.getMethod("setLevel", paramTypes);
method.invoke(loggerObtained, params);
logger.debug("Log level set to {} for the logger '{}'", logLevelUpper, loggerName);
return true;
}
catch (Exception e)
{
logger.warn("Couldn't set log level to {} for the logger '{}'", logLevelUpper, loggerName, e);
return false;
}
}
private static Object getFieldVaulue(String fullClassName, String fieldName)
{
try
{
Class<?> clazz = Class.forName(fullClassName);
Field field = clazz.getField(fieldName);
return field.get(null);
}
catch (ClassNotFoundException | IllegalAccessException | IllegalArgumentException | NoSuchFieldException |
SecurityException ignored)
{
return null;
}
}
}
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertSame;
public final class LogbackUtilsTest
{
@Test
public void testSetLogLevel() throws Throwable
{
assertEquals(true, LogbackUtils.setLogLevel(null, null)); // Set ROOT logger level to 'OFF'
assertEquals(true, LogbackUtils.setLogLevel(null, "TRACE")); // Set ROOT logger level to TRACE
assertEquals(true, LogbackUtils.setLogLevel(".", "DEBUG"));
assertEquals(true, LogbackUtils.setLogLevel(null, "INFO"));
assertEquals(true, LogbackUtils.setLogLevel(null, "WARN"));
assertEquals(false, LogbackUtils.setLogLevel(null, "WARNING")); // No such log level
assertEquals(false, LogbackUtils.setLogLevel(null, "")); // No such log level
assertEquals(false, LogbackUtils.setLogLevel(null, "-")); // No such log level
assertEquals(true, LogbackUtils.setLogLevel("org.", "DEBUG"));
}
}
@mmdemirbas
Copy link
Copy Markdown
Author

mmdemirbas commented Aug 3, 2019 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment