Reputation: 347
I have never worked with logging before and I want to initialize the logger for each class again in the middle of the application. We are using log4j
and On each
class, we have
public class MyClass {
private static Logger logger = Logger.getLogger(MyClass.class);
public void method(){
logger.info("This is info");
}
So what I want is to reinitialize this logger
object at a certain point at runtime in my application. So far I have noticed that this logger
object is initialized on application startup
but I want to execute this
private static Logger logger = Logger.getLogger(MyClass.class);
line while my application is running and user performs a certain action.
My real objective is to store these log files on disk. But I want to store the log files on different folders depending on user actions. So we have two siteIDs
in our application and therefore, we have made 2 folders on disk where we expect log files to be stored. So, when the site is selected these logger
objects on each class
needs to be reinitialized. Any suggestions how can I achieve this? Following is my log.properties file:
logger.pattern=%d{dd-MM-yyyy HH:mm:ss.SSS} [%thread] %-5level %logger{36}.%M - %msg%n
logger.base.dir=../logs
logger.archive.dir=/archive
logger.archived.file.pattern=_%d{dd-MM-yyyy}.%i
logger.file.ext=.log
logger.file.size=10 mb
logger.archived.size.cap=100 mb
logger.file.retention.days=7
logger.debug.file.retention.days=1
logger.level=TRACE
Then we have a class named LoggerConfig
public class LoggerConfig {
private static LoggerConfig loggerConfig = null;
private Properties prop = new Properties();
private String pattern;
private String baseDir;
private String archiveDir;
private String archivedFilePattern;
private String fileExt;
private String fileSize;
private String archivedSizeCap;
private Integer fileRetentionDays;
private Integer debugFileRetentionDays;
private Level loggerLevel;
private LoggerConfig() {
loadProperties();
}
public static LoggerConfig getInstance() {
if (loggerConfig == null) {
loggerConfig = new LoggerConfig();
}
return loggerConfig;
}
private void loadProperties() {
try {
InputStream input = LoggerConfig.class.getClassLoader().getResourceAsStream("logger.properties");
prop.load(input);
this.pattern = prop.getProperty("logger.pattern");
this.baseDir = prop.getProperty("logger.base.dir");
this.archiveDir = prop.getProperty("logger.archive.dir");
this.archivedFilePattern = prop.getProperty("logger.archived.file.pattern");
this.fileExt = prop.getProperty("logger.file.ext");
this.fileSize = prop.getProperty("logger.file.size");
this.archivedSizeCap = prop.getProperty("logger.archived.size.cap");
this.fileRetentionDays = Integer.parseInt(prop.getProperty("logger.file.retention.days"));
this.debugFileRetentionDays = Integer.parseInt(prop.getProperty("logger.debug.file.retention.days"));
this.loggerLevel = Level.toLevel(prop.getProperty("logger.level"));
} catch (Exception ex) {
System.out.println("Exception occourred while loading the configration file " + ex);
}
}
/**
* Getters and setters
*/
And Finally another Logger file:
public class ApplicationLogger {
private static LoggerConfig config = LoggerConfig.getInstance();
private static Map<String, Logger> loggers = new HashMap<String, Logger>();
public static Logger getLogger(String orgID, Class<?> className) {
init(orgID, className);
return loggers.get(orgID);
}
private static void init(String orgID, Class<?> className) {
if (!loggers.containsKey(orgID)) {
LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();
Logger logger = loggerContext.getLogger(orgID + className);
logger.setAdditive(Boolean.FALSE);
logger.setLevel(config.getLoggerLevel());
logger.addAppender(getFileAppender(loggerContext, Level.TRACE, orgID));
logger.addAppender(getFileAppender(loggerContext, Level.DEBUG, orgID));
logger.addAppender(getFileAppender(loggerContext, Level.INFO, orgID));
logger.addAppender(getFileAppender(loggerContext, Level.WARN, orgID));
logger.addAppender(getFileAppender(loggerContext, Level.ERROR, orgID));
loggers.put(orgID, logger);
}
}
private static FileAppender<ILoggingEvent> getFileAppender(LoggerContext loggerContext, Level level, String orgID) {
PatternLayoutEncoder encoder = new PatternLayoutEncoder();
encoder.setContext(loggerContext);
encoder.setPattern(config.getPattern());
encoder.setImmediateFlush(Boolean.TRUE);
encoder.start();
LevelFilter filter = new LevelFilter();
filter.setContext(loggerContext);
filter.setLevel(level);
filter.setOnMismatch(FilterReply.DENY);
filter.start();
RollingFileAppender<ILoggingEvent> fileAppender = new RollingFileAppender<ILoggingEvent>();
SizeAndTimeBasedRollingPolicy<ILoggingEvent> rollingPolicy = new SizeAndTimeBasedRollingPolicy<ILoggingEvent>();
rollingPolicy.setContext(loggerContext);
rollingPolicy.setFileNamePattern(config.getBaseDir() + config.getArchiveDir() + File.separator + orgID
+ File.separator + level.toString() + config.getArchivedFilePattern() + config.getFileExt());
rollingPolicy.setMaxFileSize(FileSize.valueOf(config.getFileSize()));
rollingPolicy.setMaxHistory(
Level.DEBUG.equals(level) ? config.getDebugFileRetentionDays() : config.getFileRetentionDays());
rollingPolicy.setTotalSizeCap(FileSize.valueOf(config.getArchivedSizeCap()));
rollingPolicy.setParent(fileAppender);
rollingPolicy.start();
fileAppender.setContext(loggerContext);
fileAppender.setAppend(true);
fileAppender.setEncoder(encoder);
fileAppender.addFilter(filter);
fileAppender.setFile(
config.getBaseDir() + File.separator + orgID + File.separator + level.toString() + config.getFileExt());
fileAppender.setRollingPolicy(rollingPolicy);
fileAppender.start();
return fileAppender;
}
}
Please note orgID is the siteID which is changed by user and on changing it, I want to reinitialize all logger
objects
Upvotes: 0
Views: 762
Reputation: 16185
A standard solution to you problem in Log4j2 is to use a single logger, the ThreadContext
and a RoutingAppender
. This requires almost no programmatic configuration:
siteId
ThreadContext
key:
ThreadContext.put("siteId", "site1");
log4j2.xml
file you need to configure a routing appender that chooses the real appender based on the value of siteId
:
<Configuration>
<Appenders>
<RollingFile name="ROLLING-site1" fileName="..." filePattern="...">
...
</RollingFile>
<RollingFile name="ROLLING-site2" fileName="..." filePattern="...">
...
</RollingFile>
<Routing name="ROUTING">
<Routes pattern="$${ctx:siteId}">
<Route key="site1" appenderRef="ROLLING-site1" />
<Route key="site2" appenderRef="ROLLING-site2" />
</Routes>
</Routing>
</Appenders>
<Loggers>
<Root level="DEBUG">
<AppenderRef ref="ROUTING" />
</Root>
</Loggers>
</Configuration>
LogManager.getLogger
and do not need to be aware of the logic behind the choice of the appender.A similar configuration can probably be obtained in Logback using filters, but my knowledge of Logback is quite limited.
Upvotes: 1