Log4j2 disable console on production - log4j2

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) {
}
}

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

Related

log4j2 DynamicThresholdFilter not picking up property value

Trying to set different printing levels for console and file.
Goal is: when debug=true, print debug level (console & file), else only print error level (console).
Change it programatically like this:
#Override
public void contextInitialized(ServletContextEvent sce) {
ThreadContext.put("debugMode", "true");
}
This is my log4j2 configuration:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="debug">
<Properties>
<Property name="logPath">${sys:catalina.home}</Property>
<Property name="rollingFileName">vsTenant</Property>
</Properties>
<Appenders>
<Console name="console" target="SYSTEM_OUT">
<filters>>
<DynamicThresholdFilter key="debugMode" defaultThreshold="ERROR" onMatch="ACCEPT" onMismatch="NEUTRAL">
<KeyValuePair key="true" value="DEBUG"/>
<KeyValuePair key="false" value="ERROR"/>
</DynamicThresholdFilter>
</filters>
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%thread] %-5level [vsTenant] %logger{36} - %msg\n%n" />
</Console>
<RollingFile name="rollingFile" fileName="${logPath}/logs/vsTenant.log" filePattern="${logPath}/logs/vsTenant_%d{dd-MM-yyyy}.log">
<filters>>
<DynamicThresholdFilter key="debugMode" onMatch="ACCEPT" onMismatch="DENY">
<KeyValuePair key="true" value="DEBUG"/>
</DynamicThresholdFilter>
</filters>
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%thread] %-5level [vsTenant] %logger{36} - %msg\n%n" />
<Policies>
<SizeBasedTriggeringPolicy size="50 MB" />
</Policies>
<DefaultRolloverStrategy max="5"/>
</RollingFile>
</Appenders>
<Loggers>
<Root level="ERROR" additivity="false">
<AppenderRef ref="console" />
<AppenderRef ref="rollingFile" />
</Root>
</Loggers>
</Configuration>
It is always printing ERROR level. Help is appreciated.
You were close, only a few small changes are needed to achieve what you want.
Change the first onMismatch from NEUTRAL to DENY
Add a second KeyValuePair to the second filter: <KeyValuePair key="false" value="OFF"/>
Change the Root log level from ERROR to TRACE
Here's the modified configuration:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn">
<Properties>
<Property name="logPath">${sys:catalina.home}</Property>
<Property name="rollingFileName">vsTenant</Property>
</Properties>
<Appenders>
<Console name="console" target="SYSTEM_OUT">
<filters>
<DynamicThresholdFilter key="debugMode" defaultThreshold="ERROR" onMatch="ACCEPT" onMismatch="DENY">
<KeyValuePair key="true" value="DEBUG"/>
<KeyValuePair key="false" value="ERROR"/>
</DynamicThresholdFilter>
</filters>
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%thread] %-5level [vsTenant] %logger{36} - %msg\n%n" />
</Console>
<RollingFile name="rollingFile" fileName="${logPath}/logs/vsTenant.log" filePattern="${logPath}/logs/vsTenant_%d{dd-MM-yyyy}.log">
<filters>
<DynamicThresholdFilter key="debugMode" onMatch="ACCEPT" onMismatch="DENY">
<KeyValuePair key="true" value="DEBUG"/>
<KeyValuePair key="false" value="OFF"/>
</DynamicThresholdFilter>
</filters>
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%thread] %-5level [vsTenant] %logger{36} - %msg\n%n" />
<Policies>
<SizeBasedTriggeringPolicy size="50 MB" />
</Policies>
<DefaultRolloverStrategy max="5"/>
</RollingFile>
</Appenders>
<Loggers>
<Root level="TRACE" additivity="false">
<AppenderRef ref="console" />
<AppenderRef ref="rollingFile" />
</Root>
</Loggers>
</Configuration>
Here is some java code to test it with:
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.ThreadContext;
public class SomeClass {
private static final Logger log = LogManager.getLogger();
public static void main(String[] args){
ThreadContext.put("debugMode", "false");
log.info("Info should not show anywhere");
log.debug("This shouldn't show anywhere");
ThreadContext.put("debugMode", "true");
log.debug("This should show in the log and console");
log.info("This should also show in both");
ThreadContext.put("debugMode", "false");
log.info("This should not show anywhere");
log.error("This error should show only in console.");
}
}
Running the above will output the following to console:
21:16:40.716 [main] DEBUG [vsTenant] example.SomeClass - This should show in the log and console
21:16:40.718 [main] INFO [vsTenant] example.SomeClass - This should also show in both
21:16:40.718 [main] ERROR [vsTenant] example.SomeClass - This error should show only in console.
and output the following to the log file:
21:16:40.716 [main] DEBUG [vsTenant] example.SomeClass - This should show in the log and console
21:16:40.718 [main] INFO [vsTenant] example.SomeClass - This should also show in both

log4j 2 - collor logs for intelij console

I try to config log4j to appends loggs in diffrent color per log type (INFO, ERROR, DEBUG etc.)
Here is my log4j2.xml:
<Configuration monitorInterval="60">
<Properties>
<Property name="log-path">applogs</Property>
</Properties>
<Appenders>
<Console name="Console-Appender" target="SYSTEM_OUT">
<PatternLayout>
<pattern>
%highlight{%d{HH:mm:ss.SSS} %-5level %logger{36}.%M() [%L] - %msg%n}{FATAL=red, ERROR=red, WARN=yellow, INFO=green}
</pattern>
</PatternLayout>
</Console>
<someMoreAppenders>
</Appenders>
<Loggers>
<Logger name="RepositoriesController" level="info" additivity="false">
<AppenderRef ref="Console-Appender"/>
</Logger>
<Root level="error" additivity="false">
<AppenderRef ref="Console-Appender"/>
</Root>
</Loggers>
</Configuration>
And in class RepositoriesController, i create logger in this way:
private static final Logger logger = LogManager.getLogger("RepositoriesController");
logger.info("Hello, World!");
My log4j.properties are empty. Output seems to be formatted used by my pattern but font color is still white:
Intelij console
i tried to add this properties:
spring.main.banner-mode=off
spring.output.ansi.enabled=ALWAYS
and modify pattern but without succesed, any advices?
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t]
%highlight{%level}{FATAL=bg_red, ERROR=red, WARN=yellow, INFO=green, DEBUG=blue} - %msg%n" />
</Console>
%highlight{%level} - using this you can highlight colors for different levels of logs.
This will generate output as:

log4j2 RollingFile with 3 policies

I am using log4j2 version 2.7 with sprint-boot 1.5:
my configuration file (log4j2.xml) is:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN" monitorInterval="60">
<Properties>
<Property name="LOG_PATH">./log</Property>
<Property name="FILE_LOG_PATTERN">%date{yyyy-MM-dd'T'HH:mm:ss.SSSZ}{UTC}}, %5p, %X{component:-SERVICE}, %X{event:-EVENT}, ${PID:-???}, [%t], %40.40logger{40}, FCID=%X{FCID:-N/A}, %msg%n</Property>
<Property name="MAX_HISTORY">7</Property>
<Property name="MAX_FILE_SIZE">100MB</Property>
</Properties>
<Appenders>
<RollingFile name="FILE"
fileName="${LOG_PATH}/tests.log"
filePattern="${LOG_PATH}/tests.%d{yyyy-MM-dd}.%i.log.gz">
<PatternLayout>
<Pattern>${FILE_LOG_PATTERN}</Pattern>
</PatternLayout>
<Policies>
<OnStartupTriggeringPolicy/>
<TimeBasedTriggeringPolicy />
<SizeBasedTriggeringPolicy size="${MAX_FILE_SIZE}"/>
</Policies>
<DefaultRolloverStrategy max="${MAX_HISTORY}"/>
</RollingFile>
</Appenders>
<Loggers>
<logger name="org.springframework" level="INFO"/>
<logger name="org.springframework.security.oauth2" level="INFO"/>
<logger name="org.springframework.http" level="ERROR"/>
<Logger name="org.springframework.boot" level="info"/>
<Logger name="org.springframework.boot.context.embedded.jetty" level="info"/>
<Root level="error">
<AppenderRef ref="FILE"/>
</Root>
</Loggers>
when I start the application I get this error:
ERROR Unable to invoke factory method in class class org.apache.logging.log4j.core.appender.RollingFileAppender for element RollingFile. java.lang.IllegalStateException: No factory method found for class org.apache.logging.log4j.core.appender.RollingFileAppender
If I remove one of the policies this error not showing. What is the problem?

Two patterns in same log file is not working in log4j2

I'd like to configure log4j 2 with two different patterns in same appender. i.e., Whenever there is an error, a specific pattern should be present in the log file. I am not trying two different log files, but two different pattern in same log file. Whenever there is an error, I would see "MYDOMAINDOTCOM_SUPPORT_NEEDED" and this string will trigger an automatic email to support team.
I have the below configuration which prints error message in "RollingFile" appender only and "RollingFileError" appender is ignored. What am I missing ?
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="DEBUG">
<Properties>
<Property name="log-path">/documents/log</Property>
</Properties>
<Appenders>
<RollingFile name="RollingFile" fileName="${log-path}/myexample.log"
filePattern="${log-path}/$${date:yyyy-MM}/myexample-%d{yyyy-MM-dd}-%i.log"
immediateFlush="true">
<PatternLayout>
<pattern>%d{yyyy-MM-dd HH:mm:ss} [%t] %-5p %c{1}:%L - %X{packetRefId} - %msg%n</pattern>
<!-- %d{dd/MMM/yyyy HH:mm:ss,SSS}- %c{1}: %m%n -->
</PatternLayout>
<Policies>
<SizeBasedTriggeringPolicy size="100 KB" />
</Policies>
<DefaultRolloverStrategy max="4" />
</RollingFile>
<RollingFile name="RollingFileError" fileName="${log-path}/myexample.log"
filePattern="${log-path}/$${date:yyyy-MM}/myexample-%d{yyyy-MM-dd}-%i.log"
immediateFlush="true">
<param name="threshold" value="error" />
<PatternLayout>
<pattern>MYDOMAINDOTCOM_SUPPORT_NEEDED %d{yyyy-MM-dd HH:mm:ss} [%t] %-5p %c{1}:%L - %X{packetRefId} - %msg%n</pattern>
<!-- %d{dd/MMM/yyyy HH:mm:ss,SSS}- %c{1}: %m%n -->
</PatternLayout>
<Policies>
<SizeBasedTriggeringPolicy size="100 KB" />
</Policies>
<DefaultRolloverStrategy max="4" />
</RollingFile>
</Appenders>
<Loggers>
<Logger name="org.springframework.beans.factory" level="info" additivity="false">
<AppenderRef ref="Console"/>
</Logger>
<Logger name="root" level="debug" additivity="false">
<appender-ref ref="RollingFile" level="debug" />
<appender-ref ref="RollingFileError" level="error" />
</Logger>
<Root level="debug" additivity="false">
<AppenderRef ref="RollingFile" />
</Root>
</Loggers>
</Configuration>
You should never configure two appenders to write to the same file. Having two rolling file appenders that both use the same file and roll over to the same file pattern is never going to work correctly.
Also, your configuration would end up with all error messages being logged twice; once with the RollingFile appender due to its debug level, and once on the RollingFileError appender due to its error level.
Instead, you should have a single rolling file appender and use a PatternSelector to decide which pattern to use. See http://logging.apache.org/log4j/2.x/manual/layouts.html#Pattern_Selectors for documentation on pattern selectors.

log4j 2 configuration Issue

in the config file how to separate the package in different appaender using asynch
i have two different package and using different appender i want separate log output
first two appender is different package and third appender is different one
and i need all appender connect to asynch...
pls help me to solve this
here my config file..
<?xml version="1.0" encoding="UTF-8"?>
<configuration strict="true" status="WARN">
<appenders>
<Console name="CONSOLE" target="SYSTEM_OUT">
<PatternLayout pattern="%d %-5p [%t] %C{2} (%F:%L) - %m%n" />
</Console>
<File name="MyFile" fileName="Logger/knight.log">
<PatternLayout pattern="%d %-5p [%t] %C{2} (%F:%L) - %m%n" />
</File>
<File name="Except" fileName="log1/Execption9.log">
<PatternLayout pattern="%d %-5p [%t] %C{2} (%F:%L) - %m%n" />
</File>
<Async name="Async">
<appender-ref ref="CONSOLE" />
<appender-ref ref="MyFile" />
<appender-ref ref="Except" />
</Async>
</appenders>
<loggers>
<root level="all">
<appender-ref ref="Async" />
</root>
</loggers>
</configuration>
You could configure three separate AsyncAppenders, one for each of the File appenders, and one for console, then configure root as:
<root>
<appender-ref ref="async-console" level="info" />
<appender-ref ref="async-file1" level="trace" />
<appender-ref ref="async-file2" level="error" />
</root>
But this solution gives you three threads. Why not use AsyncLoggers (using the selector command line option, see the docs for AsyncLoggers)?
That way you only have one logging thread, and it is probably a lot faster too...

Resources