Reputation: 371
I have the following problem. I´m developing an application that uses a file appender for all loggers (log4j version 1.2). Everything works ok, but now i need to log to different files based on some runtime parameters.
As a restriction, i need also to restrict the amount of log4j.xml configuration info, because i don´t know beforehand how many values will this parameters take, and for that reason i can´t configure different appenders (FileAppenders) that point to different files in the log4j configuration file. I also need to restrict the amount of new code added, for example, it may be ok to pass the runtime parameter as part of the logger name (LoggerFactory.getLogger(runtimeParameter + getClass), etc) but i wouldn´t like to create a new FileAppender by code and then adding that new Appender to the recently created logger (as a side question, will this alternative work?).
I think that perhaps creating a new appender that open different files based on his provided name (based on the runtime parameter) will work, but i don´t know how to do that, and i don´t know how it will behave when executed concurrently (as it will be a single appender for all loggers).
Thank you and excuse my english!
Upvotes: 0
Views: 241
Reputation: 2012
It sounds like the easiest workaround in your case would be to programmatically configure and create logger objects in real time.
Yes it works. Lucky for you I just tackled this problem and have example code. This is for log4j2, though. I believe it's much easier and straightforward in 1.2
/**
* Dynamically creates an instance of a Logger.
*
* @param appenderName
* most often will be the name of the class this logger will
* belong to.
* @param logFileName
* the file name to save the logs to
* @return
*/
public static org.apache.logging.log4j.Logger createInstanceLogger(String appenderName,
String logFileName) {
//call getLogger() which will create and load a logger with a default configuration
org.apache.logging.log4j.Logger logger = org.apache.logging.log4j.LogManager
.getLogger(String.format("DynamicLogger%s",
String.valueOf(DynamicLogManager.loggerCount++)));
org.apache.logging.log4j.core.Logger coreLogger = (org.apache.logging.log4j.core.Logger) logger; // cast logger to core logger to access protected methods
org.apache.logging.log4j.core.LoggerContext context = coreLogger.getContext();
org.apache.logging.log4j.core.config.BaseConfiguration configuration = (org.apache.logging.log4j.core.config.BaseConfiguration) context
.getConfiguration();
TriggeringPolicy compositePolicy = CompositeTriggeringPolicy.createPolicy(
SizeBasedTriggeringPolicy.createPolicy("5mb"),
TimeBasedTriggeringPolicy.createPolicy("1", "true"));
String fileName = String.format("%1$s/%2$s", appenderName, logFileName);
String filePattern = String.format("%1$s/%2$s.%%d{yyyy-MM-dd}",
appenderName, logFileName);
Layout<String> layout = PatternLayout.createLayout(DynamicLogManager._conversionPattern,
configuration, RegexReplacement.createRegexReplacement("a^", "."), //empty regex replacement
"utf-8", "false");
Filter f = ThresholdFilter.createFilter("trace", "accept", "accept");
Appender a = RollingFileAppender.createAppender(fileName, //fileName
filePattern, //filePattern
"true", //append
appenderName, //appender name
"true", //bufferred io
"true", //immediate flush
compositePolicy, //policy
null, //strategy default
layout, //layout
f, //filter none
"true", //ignore exceptions
"false", //advertise
"null", //advertise uri
configuration //configuration
);
a.start();
coreLogger.addAppender(a);
//this is where we would figure out how to configure the logger to listen on a configuration file
coreLogger.setLevel(Level.ALL); //set the log level of the logger that we are returning to Level.ALL
return coreLogger; //cast logger back to Logger interface
Upvotes: 0