how to set loglevel from INFO to ERROR using log4j2 api at runtime?

13,994

Solution 1

I'm not sure if this is the best way, but you set the level on org.apache.logging.log4j.core.config.LoggerConfig which you can get from the LoggerContext via the LogManager.

Once set, you can update the loggers with the new configuration.

As an example:

public static void main(String[] args) {
    Logger log = LogManager.getLogger(LogManager.ROOT_LOGGER_NAME);
    log.error("An error");
    log.debug("A debug");

    LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
    Configuration conf = ctx.getConfiguration();
    conf.getLoggerConfig(LogManager.ROOT_LOGGER_NAME).setLevel(Level.DEBUG);
    ctx.updateLoggers(conf);

    log.error("Another error");
    log.debug("Another debug");
}

Yields:

14:03:41.346 [main] ERROR  - An error
14:03:41.348 [main] ERROR  - Another error
14:03:41.348 [main] DEBUG  - Another debug

Solution 2

Credit to amcintosh, I wrapped their answer in a function:

/** Override the logging level of a given logger, return the previous level */
public static Level setLevel(Logger log, Level level) {
  LoggerContext ctx = (LoggerContext)LogManager.getContext(false);
  Configuration conf = ctx.getConfiguration();
  LoggerConfig lconf = conf.getLoggerConfig(log.getName());
  Level oldLevel = lconf.getLevel();
  lconf.setLevel(level);
  ctx.updateLoggers(conf);
  return oldLevel;
}

Despite amoe's comment, this seems to be working correctly for me using Log4J 2.5.

Solution 3

On my side, i had to use this code in order to have this working fine (based on previous answers).

import org.apache.logging.log4j.core.LoggerContext;
import org.apache.logging.log4j.core.config.AbstractConfiguration;

...

public static void changeLoggerLevel(final String module, final Level level) {
  String moduleRenamed = module.replaceAll("/", ".");
  LoggerContext ctx = (LoggerContext)LogManager.getContext(false);
  AbstractConfiguration configuration = (AbstractConfiguration) ctx
        .getConfiguration();
  if (configuration.getLogger(moduleRenamed) != null) {
    LoggerConfig loggerConfig = configuration.getLoggerConfig(moduleRenamed);
    loggerConfig.setLevel(level);
  } else {
    LoggerConfig loggerConfig = new LoggerConfig(moduleRenamed, level, true);
    configuration.addLogger(moduleRenamed, loggerConfig);
  }
  ctx.updateLoggers(configuration);
}

The problem was with the getLoggerConfig() call; if the module you are trying to give a new level is not yet registered, this method returns the root logger (or any intermediate sub path registered), and thus instead of altering the level for com.mycompany you will alter root or com level. That's why you have to add a new LoggerConfig in case the module to alter is not yet registered.

Solution 4

Gary Gregory is correct.

Also the answer to this question is right there on the FAQ page in log4j2's site

https://logging.apache.org/log4j/2.x/faq.html#reconfig_level_from_code

Sample Code below:

Configurator.setLevel(logger.getName(), Level.INFO);

Solution 5

The following APIs in the class org.apache.logging.log4j.core.config.Configurator allow you to change Levels:

Share:
13,994

Related videos on Youtube

Nandan
Author by

Nandan

JAVA Developer

Updated on June 04, 2022

Comments

  • Nandan
    Nandan almost 2 years

    logger.setLevel() method is not available in log4j2 API. So how to set log level at run time.

  • amoe
    amoe over 10 years
    Works well for the root logger, but doesn't work for any other logger -- per-package, for instance. In this case, the log level seems unchanged, even when calling reconfigure on the context.
  • oak
    oak almost 10 years
    @amoe same issue here. i guess this related to the right context on webapp program. did you manager to change all logger level?
  • Ar5hv1r
    Ar5hv1r over 9 years
    Good catch, that behavior is documented, but not what people would usually expect. If I understand what you're saying however, this could equivalently be addressed by simply ensuring the Logger exists before calling getLoggerConfig(), right?
  • SRG
    SRG over 9 years
    I haven't tryied, but i would have say that the logger inherits from a previous (upper) level (possibly root), and so is always defined ... it seems to just be the configuration inheritance that is not fully offered (and it is the configuration that have to be altered in order to change the log level, not the logger itself).
  • theGamblerRises
    theGamblerRises almost 8 years
    Can it be configured for thread specific? Behaviour same as ThreadContext.
  • Ar5hv1r
    Ar5hv1r almost 8 years
    @theGamblerRises I'd suggest posting a separate question, rather than trying to explore this in the comments. Offhand I'd guess that you cannot control log levels per-thread with this mechanism, but there may well be other ways to do what you want. If you post a separate question feel free to share a link to it here.
  • Draken
    Draken about 7 years
    Whilst this may theoretically answer the question, it would be preferable to include the essential parts of the answer here, and provide the link for reference.
  • Jeryl Cook
    Jeryl Cook about 3 years
    why do all of this when you can just do "'Configurator.setLevel(logger.getName(), Level.INFO);" as explained above?