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 :
- If the configuration file is changed the configuration will be reloaded and the manual changes will be lost.
- 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