Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to configure Logger Programmatically in log4j2.02?

Tags:

java

log4j

I want to use log4j without any configure file. What I wan to do is something as:

logger = (Logger) LogManager.getLogger(this.getClass());
String pattern = "[%level] %m%n";
//do something to make this logger output to an local file "/xxx/yyy/zzz.log"

I have found this answer: Configuring Log4j Loggers Programmatically.

But the docs of Logger#addAppender says: This method is not exposed through the public API and is used primarily for unit testing.

I am not sure if it is the right way to use this method in my code or there is other better solution to solve my problem.

like image 965
Eastsun Avatar asked Oct 31 '14 06:10

Eastsun


People also ask

How do I reconfigure log4j2 in code with a specific configuration file?

Reconfigure Log4j Using ConfigurationBuilder with the Configurator. An alternative to a custom ConfigurationFactory is to configure with the Configurator . Once a Configuration object has been constructed, it can be passed to one of the Configurator. initialize methods to set up the Log4j configuration.

What is Loggers in log4j2?

LoggerContext is a vocal point for Logging system as you may have multiple LoggerContexts inside your application. Per each LoggerContext an active configuration should be set. Log4j2 configuration contains all Logging system assets; LoggerConfig(s), Appender(s), Filter(s) and many others. Calling of LogManager.


2 Answers

The official documentation shows an example : Programatically Adding to the Current Configuration

final LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
final Configuration config = ctx.getConfiguration();

Layout layout = PatternLayout.createLayout(PatternLayout.SIMPLE_CONVERSION_PATTERN, config, null, null,null, null);
Appender appender = FileAppender.createAppender("target/test.log", "false", "false", "File", "true", "false", "false", "4000", layout, null, "false", null, config);
appender.start();
config.addAppender(appender);

AppenderRef ref = AppenderRef.createAppenderRef("File", null, null);
AppenderRef[] refs = new AppenderRef[] {ref};
LoggerConfig loggerConfig = LoggerConfig.createLogger("false", "info", "org.apache.logging.log4j", "true", refs, null, config, null );
loggerConfig.addAppender(appender, null, null);
config.addLogger("org.apache.logging.log4j", loggerConfig);
ctx.updateLoggers();

With these limitations :

  1. If the configuration file is changed the configuration will be reloaded and the manual changes will be lost.
  2. Modification to the running configuration requires that all the methods being called (addAppender and addLogger) be synchronized.

This solution avoids to use method from the core implementation org.apache.logging.log4j.core.Logger, and it avoids dirty cast like that :

import org.apache.logging.log4j.Logger;

Logger logger = (Logger) LogManager.getLogger(this.getClass());
((org.apache.logging.log4j.core.Logger) logger).addAppender(...); // Bypassing the public API 
like image 197
ToYonos Avatar answered Oct 10 '22 19:10

ToYonos


With the latest version of log4j2, all create the APIs like

PatternLayout.createLayout, 
FileAppender.createAppender, 
LoggerConfig.createLogger 

have become deprecated, it's better to use a custom log ConfigurationFactory along with ConfigurationBuilder for defining the log configuration programmatically.

like image 34
Dev Avatar answered Oct 10 '22 17:10

Dev