Configuring Log4J Loggers Programmatically

Configuring Log4j Loggers Programmatically

You can add/remove Appender programmatically to Log4j:

  ConsoleAppender console = new ConsoleAppender(); //create appender
//configure the appender
String PATTERN = "%d [%p|%c|%C{1}] %m%n";
console.setLayout(new PatternLayout(PATTERN));
console.setThreshold(Level.FATAL);
console.activateOptions();
//add appender to any Logger (here is root)
Logger.getRootLogger().addAppender(console);

FileAppender fa = new FileAppender();
fa.setName("FileLogger");
fa.setFile("mylog.log");
fa.setLayout(new PatternLayout("%d %-5p [%c{1}] %m%n"));
fa.setThreshold(Level.DEBUG);
fa.setAppend(true);
fa.activateOptions();

//add appender to any Logger (here is root)
Logger.getRootLogger().addAppender(fa);
//repeat with all other desired appenders

I'd suggest you put it into an init() somewhere, where you are sure, that this will be executed before anything else.
You can then remove all existing appenders on the root logger with

 Logger.getRootLogger().getLoggerRepository().resetConfiguration();

and start with adding your own. You need log4j in the classpath of course for this to work.

Remark:

You can take any Logger.getLogger(...) you like to add appenders. I just took the root logger because it is at the bottom of all things and will handle everything that is passed through other appenders in other categories (unless configured otherwise by setting the additivity flag).

If you need to know how logging works and how is decided where logs are written read this manual for more infos about that.

In Short:

  Logger fizz = LoggerFactory.getLogger("com.fizz")

will give you a logger for the category "com.fizz".

For the above example this means that everything logged with it will be referred to the console and file appender on the root logger.

If you add an appender to
Logger.getLogger("com.fizz").addAppender(newAppender)
then logging from fizz will be handled by alle the appenders from the root logger and the newAppender.

You don't create Loggers with the configuration, you just provide handlers for all possible categories in your system.

How to configure Logger Programmatically in log4j2.02?

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

Configuring a Logger Programmatically with Log4J 2?

You do this:

// 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);

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

Gary

log4j - Programmatical configuration

Simple! After you create your third appender (C) get a logger for your namespace (darius.ws), set the INFO level for this logger. At the end just append this C appender to the logger.

FileAppender fileAppender = new FileAppender();
fileAppender.setName("C");
fileAppender.setFile("C.log");
fileAppender.setLayout(new PatternLayout("%d %-5p [%c{1}] %m%n"));
fileAppender.setThreshold(Level.INFO);
fileAppender.setAppend(true);
...
Logger someLogger = Logger.getLogger("darius.ws");
someLogger.setLevel(Level.INFO);
someLogger.addAppender(fileAppender);

Best regards

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.

How to configure log4j 2 to asynchonous mode programmatically?

If you can't use system property and log4j2.component.properties file. You can try the ConfigurationFactory.setConfigurationFactory method.

Here's a brief example:

Log4j2.java

public class Log4j2 {

static {
ConfigurationFactory.setConfigurationFactory(new CustomConfigurationFactory()); // This must be called before any other calls to Log4j
}

private static Logger logger = LogManager.getLogger();

public static void main(String[] args) {
logger.info("hello");
}
}

CustomConfigurationFactory.java

@Plugin(name = "CustomConfigurationFactory", category = ConfigurationFactory.CATEGORY)
@Order(50)
public class CustomConfigurationFactory extends ConfigurationFactory {

private static Configuration createConfiguration(final String name, ConfigurationBuilder<BuiltConfiguration> builder) {
builder.setConfigurationName(name);

AppenderComponentBuilder appenderBuilder = builder.newAppender("Stdout", "CONSOLE").
addAttribute("target", ConsoleAppender.Target.SYSTEM_OUT);
appenderBuilder.add(builder.newLayout("PatternLayout").
addAttribute("pattern", "%level: %msg%n"));
builder.add(appenderBuilder);

RootLoggerComponentBuilder rootLoggerBuilder = builder.newAsyncRootLogger(Level.DEBUG); // use newAsyncRootLogger instead of newRootLogger
rootLoggerBuilder.add(builder.newAppenderRef("Stdout"));

builder.add(rootLoggerBuilder);
return builder.build();
}

@Override
public Configuration getConfiguration(final LoggerContext loggerContext, final ConfigurationSource source) {
return getConfiguration(loggerContext, source.toString(), null);
}

@Override
public Configuration getConfiguration(final LoggerContext loggerContext, final String name, final URI configLocation) {
ConfigurationBuilder<BuiltConfiguration> builder = newConfigurationBuilder();
return createConfiguration(name, builder);
}

@Override
protected String[] getSupportedTypes() {
return new String[]{"*"};
}
}

Hope this helps :-)

Programmatically Configuring Log4J From Kotlin

Thanks for the helpful comments, guys. I was not aware that this was an ongoing issue. I have since mitigated it by dual-compiling Java and Kotlin in the project. Will close this once SO allows me to answer my own question.



Related Topics



Leave a reply



Submit