Programmatically Change Log Level in Log4J2

Programmatically change log level in Log4j2

The Easy Way :

EDITED according to log4j2 version 2.4 FAQ

You can set a logger’s level with the class Configurator from Log4j Core. BUT be aware that the Configurator class is not part of the public API.

// org.apache.logging.log4j.core.config.Configurator;
Configurator.setLevel("com.example.Foo", Level.DEBUG);

// You can also set the root logger:
Configurator.setRootLevel(Level.DEBUG);

Source

The Preferable Way :

EDITED to reflect changes in the API introduced in Log4j2 version 2.0.2

If you wish to change the root logger level, do something like this :

LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
Configuration config = ctx.getConfiguration();
LoggerConfig loggerConfig = config.getLoggerConfig(LogManager.ROOT_LOGGER_NAME);
loggerConfig.setLevel(level);
ctx.updateLoggers(); // This causes all Loggers to refetch information from their LoggerConfig.

Here is the javadoc for LoggerConfig.

Change log level programmatically

I would strongly suggest that you do NOT use a programmatic solution for this because it will make your code depend on the implementation details of log4j2. This will make long term maintenance of your code problematic if the implementation changes. So, if you don't want to go with the JMX approach then you could set up your log4j2 configuration to use a DynamicThresholdFilter.

Here is a simple example of the filter approach:

First, a log4j2.xml file to configure the log4j2 system:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
<DynamicThresholdFilter key="myLogLvl" defaultThreshold="ERROR"
onMatch="ACCEPT" onMismatch="DENY">
<KeyValuePair key="TRACE" value="TRACE"/>
<KeyValuePair key="DEBUG" value="DEBUG"/>
<KeyValuePair key="INFO" value="INFO"/>
<KeyValuePair key="WARN" value="WARN"/>
<KeyValuePair key="FATAL" value="FATAL"/>
</DynamicThresholdFilter>
</Console>
</Appenders>

<Loggers>
<Root level="ALL">
<AppenderRef ref="Console" />
</Root>
</Loggers>
</Configuration>

Notice how I have set up the filter so that the DynamicThresholdFilter has a key of "myLogLvl" and then several KeyValuePair that define the log level threshold based on the value in ThreadContext for the key "myLogLvl". I assumed you wanted to use the names of the levels as the value you would put into ThreadContext.

Also notice that I have set the Root logger's level to "ALL". This is so that all messages will be accepted by the logger and then filtered by the filter. In other words I'm putting the filter in control of which messages are accepted rather than the logger.

Here is a simple Java class to generate some logs:

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.ThreadContext;

public class SomeClass {

private static final Logger log = LogManager.getLogger();

public static void main(String[] args){

ThreadContext.put("myLogLvl", "WARN");

if(log.isDebugEnabled())
log.debug("This is some debug! (This should not appear in console)");
log.info("Here's some info! (This should not appear in console)");
log.error("Some error happened! (We will see this in the console)");

//Maybe now I want INFO log level
ThreadContext.put("myLogLvl", "INFO");

log.info("This should now appear in the console");
log.debug("This still should --not-- appear");
log.fatal("This will also appear");
}
}

Notice the first I do is set the ThreadContext variable "myLogLvl" to "WARN" so that only messages that are "WARN" level or more specific are accepted. If you don't do this there will be no value for "myLogLvl" which means the default level defined in the filter will not apply either, so all messages will be accepted.

Here is sample output generated by the above:

10:39:44.668 [main] ERROR example.SomeClass - Some error happened! (We will see this in the console)
10:39:44.670 [main] INFO example.SomeClass - This should now appear in the console
10:39:44.670 [main] FATAL example.SomeClass - This will also appear

Hope this helps!

Log4j: Change log level programmatically that works for to-be created loggers

Didn't find the resource anymore, but as to my faded memory LogManager.getLogger("com.my.company").setLevel(whateverloglevel) should do the job.

All loggers that are created with LogManager.getLogger(MyClass.class) where MyClass is in com.my.company or in a subtree of that will be affected.

whateverloglevel is one of Level:


ALL
    The ALL has the lowest possible rank and is intended to turn on all logging.

DEBUG
    The DEBUG Level designates fine-grained informational events that are most useful to debug an application.

ERROR
    The ERROR level designates error events that might still allow the application to continue running.

FATAL
    The FATAL level designates very severe error events that will presumably lead the application to abort.

INFO
    The INFO level designates informational messages that highlight the progress of the application at coarse-grained level.
OFF
    The OFF has the highest possible rank and is intended to turn off logging.

TRACE
    The TRACE Level designates finer-grained informational events than the DEBUG

WARN
    The WARN level designates potentially harmful situations.



Be aware that this probably does not work in log4j 2.

For (I think) version >= 2.4 see:

  • log4j FAQ
  • Programmatically change log level in Log4j2

Dynamically Changing log4j log level

Changing the log level is simple; modifying other portions of the configuration will pose a more in depth approach.

LogManager.getRootLogger().setLevel(Level.DEBUG);

The changes are permanent through the life cyle of the Logger. On reinitialization the configuration will be read and used as setting the level at runtime does not persist the level change.

UPDATE: If you are using Log4j 2 you should remove the calls to setLevel per the documentation as this can be achieved via implementation classes.

Calls to logger.setLevel() or similar methods are not supported in the
API. Applications should remove these. Equivalent functionality is
provided in the Log4j 2 implementation classes but may leave the
application susceptible to changes in Log4j 2 internals.

Log4j2 does not change logging level at runtime

Found the real issue. Had to use:

LoggerContext ctx = (LoggerContext) LogManager.getContext(false);

instead of

LoggerContext ctx = (LoggerContext) LogManager.getContext();

API stating the difference being "returns the LoggerContext" and "returns the current LoggerContext". And I clearly missed this bit of information for the version without boolean parameter:

"WARNING - The LoggerContext returned by this method may not be the LoggerContext used to create a Logger for the calling class."

Changing log level for a keyword in log4j2

@fatCop's answer is mostly correct. You can start with log4j2.xml configured as

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn" name="AppName" packages="">
<RegexFilter regex="*database*" onMatch="DENY" onMismatch="DENY"/>
<Appenders>
<RollingFile name="RollingFile" fileName="logs/app.log"
filePattern="logs/app-%d{MM-dd-yyyy}.log.gz">
<PatternLayout>
<pattern>%d %p %c{1.} [%t] %m%n</pattern>
</PatternLayout>
<TimeBasedTriggeringPolicy />
</RollingFile>
</Appenders>
<Loggers>
<Root level="error">
<AppenderRef ref="RollingFile"/>
</Root>
</Loggers>
</Configuration>

Because this is using a global filter it will cause nothing to be logged. When you are ready to enable logging do

final LoggerContext loggerContext = LoggerContext.getContext(false);
final Configuration config = loggerContext.getConfiguration();
Filter filter = RegexFilter.createFilter("database", null, false, Result.ACCEPT, RESULT.DENY);
config.setFilter(filter);

When you want it disabled then replace the filter with a new one that is set back to DENY on a match.

Note that the logging level on the root logger is irrelevant since the filter is only accepting or denying events.



Related Topics



Leave a reply



Submit