I'm developing a Web app and I'm using log4j2. In developing mode, I'm logging using RollingFile and Console appenders.
Everything is working properly, but I'd want to disable the Console appender when my project will be released and it will be in production mode. Here's a slice of my log4j2.xml code:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn" name="PropertiesConfig" packages="com.project.application">
<!-- PROPERTIES -->
<Properties>
<Property name="webName">Project</Property>
<Property name="logBaseDir">${sys:catalina.base}/logs/</Property>
<Property name="consolePattern">%highlight{[%-5level] [%d{yyyy-MM-dd HH:mm:ss,SSS}] [%c{1}] - %msg%n}</Property>
<Property name="rollingFilePattern">[%-5level] [%d{yyyy-MM-dd HH:mm:ss,SSS}] [%c{1}] - %msg%n</Property>
</Properties>
<!-- APPENDERS -->
<Appenders>
<!-- Console -->
<Console name="Console"
target="SYSTEM_OUT"
immediateFlush="true">
<PatternLayout>
<pattern>${consolePattern}</pattern>
</PatternLayout>
</Console>
<!-- RollingFile -->
<RollingFile name="RollingFile"
fileName="${sys:logBaseDir}${webName}/${webName}.log"
filePattern="${sys:logBaseDir}${webName}.%d{yyyy-MM-dd}.log"
immediateFlush="true">
<PatternLayout>
<pattern>${rollingFilePattern}</pattern>
</PatternLayout>
<Policies>
<OnStartupTriggeringPolicy />
<TimeBasedTriggeringPolicy interval="1" modulate="true" />
</Policies>
</RollingFile>
<!-- LOGGERS -->
<Loggers>
<Logger name="com.project.application" additivity="true" level="warn">
<AppenderRef ref="RollingFile" />
</Logger>
<Root level="info"> <!-- @TODO disable in production -->
<AppenderRef ref="Console" />
</Root>
</Loggers>
</Configuration>
Thank you!
Use a filter, e.g. ThreadContextMapFilter
:
<Console name="Console" target="SYSTEM_OUT" immediateFlush="true">
<ThreadContextMapFilter onMatch="DENY" onMismatch="NEUTRAL">
<KeyValuePair key="is-production" value="1"/><!-- skip on production -->
</ThreadContextMapFilter>
<PatternLayout>
<pattern>${consolePattern}</pattern>
</PatternLayout>
</Console>
The initialization of the ThreadContext
entry can be perfomed in a ServletContextListener
, e.g.:
@WebListener
public class Log4jThreadContextInitializer implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
String isProduction = isProduction() ? "1" : "0";
sce.getServletContext().log("Setting 'is-production' flag for Log4j to " + isProduction);
org.apache.logging.log4j.ThreadContext.put("is-production", isProduction);
}
private boolean isProduction() {
// TODO: production detection
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
}
}