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.
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.
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 log level in log4j version 1 and bridge to version 2
You should use these 2 dependencies:
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>2.11.1</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-1.2-api</artifactId>
<version>2.11.1</version>
</dependency>
And adapt log4j.properties, which must be placed in the project´s classpath. See: https://logging.apache.org/log4j/2.x/manual/configuration.html#Properties
How to dynamically change log level in SLF4j OR Log4J
Consider Logback http://logback.qos.ch/ - "a successor to the popular log4j project, picking up where log4j leaves off". If instructed to do so, logback-classic will scan for changes in its configuration file and automatically reconfigure itself when the configuration file changes. Besides, you can control Logback's logging levels with JMX.
can we change the logging level of log4j at runtime
Calling the Logger.setLevel
method with the desired Level
can alter a Logger
's output level at runtime.
The following is an example which demonstrates its usage:
Logger logger = Logger.getLogger("myLogger");
logger.addAppender(new ConsoleAppender(new SimpleLayout()));
System.out.println("*** The current level will be INFO");
logger.setLevel(Level.INFO);
logger.warn("Only INFO and higher will appear");
logger.info("Only INFO and higher will appear");
logger.debug("Only INFO and higher will appear");
System.out.println("*** Changing level to DEBUG");
// remember the previous level
Level previousLevel = logger.getLevel();
logger.setLevel(Level.DEBUG);
logger.warn("DEBUG and higher will appear");
logger.info("DEBUG and higher will appear");
logger.debug("DEBUG and higher will appear");
System.out.println("*** Changing level back to previous level");
// revert to previous level
logger.setLevel(previousLevel);
logger.warn("Only INFO and higher will appear");
logger.info("Only INFO and higher will appear");
logger.debug("Only INFO and higher will appear");
The above outputs:
*** The current level will be INFO
WARN - Only INFO and higher will appear
INFO - Only INFO and higher will appear
*** Changing level to DEBUG
WARN - DEBUG and higher will appear
INFO - DEBUG and higher will appear
DEBUG - DEBUG and higher will appear
*** Changing level back to previous level
WARN - Only INFO and higher will appear
INFO - Only INFO and higher will appear
The above demonstrates how to change the level of one Logger
named myLogger
, but if the levels of all the loggers in the current repository should be changed, then the setLevel
method on the root logger obtained by Logger.getRootLogger
should be called to change the levels on all the child loggers.
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!
Related Topics
How to Add Unique Jcomboboxes to a Column in a Jtable (Java)
Java, Simplified Check If Int Array Contains Int
Run Exe Which Is Packaged Inside Jar File
Rotating Image with Affinetransform
Pdfbox 2.0.2 > Calling of Pagedrawer.Processpage Method Caught Exceptions
How to Use @Id with String Type in JPA/Hibernate
Use Custom Fonts When Creating PDF Using Ireport
Import Xxx Cannot Be Resolved for Java Se Standard Classes
Springboot 2.6.0/Spring Fox 3 - Failed to Start Bean 'Documentationpluginsbootstrapper'
Manipulating and Comparing Floating Points in Java
Java, How to Add Library Files in Netbeans
Convert Each Animated Gif Frame to a Separate Bufferedimage
Default Constructors and Inheritance in Java
How to Call Subclasses' Methods on a Superclass Object