11

I want to use default SLF4J + Logback configuration except setting org.springframework.data.document.mongodb logging level to DEBUG.

How can I do it with Java code?

I'm not using XML, and this decision made at runtime.

1
  • I hope there will be better answers: this also applies to unit/func/integration tests, where one often wants to suppress noise during tests. Having to use config files is bit of a pain. Commented Feb 21, 2013 at 0:56

2 Answers 2

11

The following works for me but generally this is not a good idea. Your code will depend on Logback (you can't choose another logging framework behind SLF4J).

final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger("test.package"); if (!(logger instanceof ch.qos.logback.classic.Logger)) { return; } ch.qos.logback.classic.Logger logbackLogger = (ch.qos.logback.classic.Logger) logger; logbackLogger.setLevel(ch.qos.logback.classic.Level.TRACE); logger.trace("some log"); 
Sign up to request clarification or add additional context in comments.

1 Comment

If you use a class name instead a package, the above will not work, since the logger obtained is different instance. However when using package, it is OK, because the logging level is propagated to children.
6

Depending to logback-classic is not a good idea as @palacsint stated. You can achieve what you want using Java's Reflection API. Note that this approach puts some overhead to your program because of use of reflection.

Usage:

LogbackUtils.setLogLevel("com.stackoverflow.sample", "DEBUG") 

Code:

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); /** * 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) getFieldValue(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 = getFieldValue(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; } } // getFieldValue() method omitted for bravity from here, // but available at GitHub link below. 

Full code including tests: Github Gist.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.