Reputation: 2730
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!
Upvotes: 1
Views: 3165
Reputation: 3399
Spring-lookup made my life easier. My appender is like this:
<Appenders>
<Console name="console-local" target="SYSTEM_OUT">
<PatternLayout
pattern="%d{yyyy-MM-dd HH:mm:ss:SSS} [%thread] %-5level %logger{2}:%L - %msg%n" />
</Console>
</Appenders>
I have added a property like this:
<Properties>
<Property name="console-appender">console-${spring:profiles.active}</Property>
</Properties>
And the logger is like this:
<Loggers>
<root level="info">
<appender-ref ref="${console-appender}"/>
</root>
</Loggers>
If my active profile is local, thus console-appender will be set to console-local, and the log will be shown in the console, as ref will find console-local.
Again, suppose, my active profile is prod, then console-appender will be set to console-prod, and the log will not be shown in the console, as ref will not find console-prod. Because Console's appender name is still console-local.
My log4j version is 2.14.1
Upvotes: 1
Reputation: 4496
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) {
}
}
Upvotes: 2