log4j2 environment variable substitution not working for filename attribute - log4j2

I am trying to configure my daily rolling log file with a filename that contains server port number because this is a multi server application and each server will generate it's own log.
I have the following configuration
<Configuration status="WARN">
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout
pattern="[%d{ISO8601}:$${env:SERVER_PORT}-L1] [th:%t] [%c] [%level] [%logger{36}] - %n[%d{ISO8601}:$${env:SERVER_PORT}-L2]%msg%n"/>
</Console>
<RollingFile name="dailyLog" immediateFlush="false" append="true">
<FileName>logs/rCOI.${env:SERVER_PORT:8090}.log</FileName>
<FilePattern>logs/rCOI.${env:SERVER_PORT:8090}.%d{yyyy-MM-dd}.log.zip</FilePattern>
<PatternLayout
pattern="[%d{ISO8601}:$${env:SERVER_PORT}-L1] [th:%t] [%c] [%level] [%logger{36}] - %n[%d{ISO8601}:$${env:SERVER_PORT}-L2]%msg%n"/>
<Policies>
<TimeBasedTriggeringPolicy interval="1" modulate="true" />
</Policies>
<DefaultRolloverStrategy max="5" />
</RollingFile>
</Appenders>
<Loggers>
<Root level="debug">
<AppenderRef ref="dailyLog"/>
</Root>
</Loggers>
</Configuration>
This produces a log called
logs/rCOI.${env:SERVER_PORT:8090}.log
so it's not even using the default. I am sure that SERVER_PORT is defined and exported because I use it in the application with no issues.
I have tried $${env:SERVER_PORT:8090} and just ${SERVER_PORT} as well. Nothing is working.
It would be nice to be able to use an environment variable for the logs/ directory as well.

Related

log4j2 (2.6.2) configuration not deleting old log files

I have the following log4j2 xml configuration that I'm using to log TRACE and DEBUG level messages.
<Configuration status="WARN" packages="" monitorInterval="300">
<Properties>
<Property name="log-path">/logs/webapp</Property>
</Properties>
<Appenders>
<RollingFile name="TRACE" append="true" immediateFlush="true" fileName="${log-path}/trace.log" filePattern="${log-path}/trace.log.%d{MM-dd-yyyy}">
<PatternLayout>
<pattern>%d{DEFAULT}: %-20C{1} : %m%n</pattern>
</PatternLayout>
<Policies>
<TimeBasedTriggeringPolicy />
</Policies>
<DefaultRolloverStrategy>
<Delete basePath="${log-path}" maxDepth="1">
<IfFileName glob="*/trace.log.*" />
<IfLastModified age="14d" />
</Delete>
</DefaultRolloverStrategy>
</RollingFile>
<RollingFile name="DETAIL" append="true" immediateFlush="true" fileName="${log-path}/detail.log" filePattern="${log-path}/detail.log.%d{MM-dd-yyyy}">
<PatternLayout>
<pattern>%d{DEFAULT}: %-20C{1} : %m%n</pattern>
</PatternLayout>
<Policies>
<TimeBasedTriggeringPolicy />
</Policies>
<DefaultRolloverStrategy max="15"/>
</RollingFile>
</Appenders>
<Loggers>
<Root level="trace">
<AppenderRef ref="TRACE" level="trace"/>
<AppenderRef ref="DETAIL" level="debug"/>
</Root>
</Loggers>
</Configuration>
The intention for this configuration is that the trace log files 14 days and older would be deleted but this is not the case. I have much older trace log files on my system still, the oldest being trace.log.11-02-2016
I'm aware of file deletion issues in log4j2 up to version 2.5 and 2.5 introduced the Delete configuration element but I am using 2.6.2.
Has anyone come across this and been able to get it to work either via an implementation version update or a configuration change?

Can I keep rolling file in log4j2 even though the log is empty

I have a program in java to write log using log4j2 that configured in xml configuration file.
Can I keep rolling file in log4j2 even though the log is empty. I need to use the archived log generated by log4j2. Now the archived log is only created if the log is not empty, if there is no log then the archived is not created. But I want log4j2 to keep generated the log even there is empty log. Any advice?
Here is my code:
<?xml version="1.0" encoding="UTF-8"?>
<Appenders>
<RollingFile
fileName="logs/app-%d{yyyyMMdd}.log"
filePattern="logs/$${date:yyyy-MM-dd}/app-%d{yyyyMMdd}-%i.log.gz"
name="app_file">
<PatternLayout>
<Pattern>%d %p %m %ex%n
</Pattern>
</PatternLayout>
<Policies>
<OnStartupTriggeringPolicy />
<TimeBasedTriggeringPolicy />
<SizeBasedTriggeringPolicy
size="100 MB" />
</Policies>
<DefaultRolloverStrategy max="20" />
</RollingFile>
<Console name="stdout" target="SYSTEM_OUT">
<PatternLayout pattern="%d{HH:mm:ss.SSS} %highlight{%class{1.}:%L} [%c] [%p] %m%n" />
</Console>
</Appenders>
<Loggers>
<Logger additivity="false" includeLocation="true"
name="app">
<AppenderRef ref="app_file" level="trace"/>
<AppenderRef ref="stdout" level="trace"/>
</Logger>
<Logger level="error" name="com.ulisesbocchio.jasyptspringboot">
</Logger>
<Logger level="error" name="org.springframework">
</Logger>
<Root includeLocation="true">
<AppenderRef ref="stdout" />
</Root>
</Loggers>
I also added some code below in my java code
System.setProperty("Log4jContextSelector",
"org.apache.logging.log4j.core.async.AsyncLoggerContextSelector");
Seems that the file only roll over when something is written into the file. I think that basically you should do some customization, here are 2 options:
Set a timer, log empty string periodic to trigger the roll over.
Override the RollingFile and roll over file whatever you want.

Log4j2 Different appender for different level

I have a little problem and canĀ“t find a solution. I want to set pattern layout for level info another than for level warn. If I have a log in level INFO everything is OK, but if the log is levelWARN it is written out into console two times (as level info and as level warn). Simply all logs at a specific level is written out us log at that level and the level below.
I want to logs in level INFO write out to console like: "%-5level %d{dd-MM-yyyy HH:mm:ss} %msg%n" and level WARN like "%-5level %d{dd-MM-yyyy HH:mm:ss} [%l] %msg%n".
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="INFO">
<Appenders>
<Console name="ConsoleInfo" target="SYSTEM_OUT">
<ThresholdFilter level="INFO" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout pattern="%-5level %d{dd-MM-yyyy HH:mm:ss} %msg%n"/>
</Console>
<Console name="ConsoleWarning" target="SYSTEM_OUT">
<ThresholdFilter level="WARN" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout pattern="%-5level %d{dd-MM-yyyy HH:mm:ss} [%l] %msg%n"/>
</Console>
<File name="File" fileName="logs/cli.log">
<PatternLayout pattern="%-5level %d{dd-MM-yyyy HH:mm:ss} [%l] %msg%n"/>
</File>
</Appenders>
<Loggers>
<Root level="ALL">
<AppenderRef ref="ConsoleInfo"/>
<AppenderRef ref="ConsoleWarning"/>
<AppenderRef ref="File"/>
</Root>
</Loggers>
</Configuration>
As I understand it you want to have log events with a level of WARN or higher (WARN,ERROR,FATAL) go to the "ConsoleWarning" appender only rather than going to both "ConsoleWarning" and "ConsoleInfo".
The simplest way to do this would be to modify your filter configuration in your "ConsoleInfo" appender to basically do the opposite approach like this:
<Console name="ConsoleInfo" target="SYSTEM_OUT">
<ThresholdFilter level="WARN" onMatch="DENY" onMismatch="ACCEPT"/>
<PatternLayout pattern="%-5level %d{dd-MM-yyyy HH:mm:ss} %msg%n"/>
</Console>
This works because as the log4j2 manual states:
This filter returns the onMatch result if the level in the LogEvent is the same or more specific than the configured level and the onMismatch value otherwise. For example, if the ThresholdFilter is configured with Level ERROR and the LogEvent contains Level DEBUG then the onMismatch value will be returned since ERROR events are more specific than DEBUG.
This will cause the appender to accept only events that have a level less than WARN.
Another possible solution would be to use a RoutingAppender to specify the destination for each level. If you do it this way then you don't need the ThresholdFilters at all. Also note that you can ignore events of specific levels by not providing a default route and not providing a route for that level. For example, if you remove <Route ref="ConsoleInfo" key="DEBUG" /> from the configuration below then all DEBUG events will be ignored by the routing appender and will not be printed to console. Here is the configuration:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="INFO">
<Appenders>
<Console name="ConsoleInfo" target="SYSTEM_OUT">
<PatternLayout pattern="%-5level %d{dd-MM-yyyy HH:mm:ss} %msg%n"/>
</Console>
<Console name="ConsoleWarning" target="SYSTEM_OUT">
<PatternLayout pattern="%-5level %d{dd-MM-yyyy HH:mm:ss} [%l] %msg%n"/>
</Console>
<File name="File" fileName="logs/cli.log">
<PatternLayout pattern="%-5level %d{dd-MM-yyyy HH:mm:ss} [%l] %msg%n"/>
</File>
<Routing name="Routing">
<Routes>
<Script name="RoutingInit" language="JavaScript"><![CDATA[
logEvent.getLevel();]]>
</Script>
<Route ref="ConsoleInfo" key="TRACE" />
<Route ref="ConsoleInfo" key="DEBUG" />
<Route ref="ConsoleInfo" key="INFO" />
<Route ref="ConsoleWarning" key="WARN" />
<Route ref="ConsoleWarning" key="ERROR" />
<Route ref="ConsoleWarning" key="FATAL" />
</Routes>
</Routing>
</Appenders>
<Loggers>
<Root level="ALL">
<AppenderRef ref="Routing"/>
<AppenderRef ref="File"/>
</Root>
</Loggers>
</Configuration>
Hope this helps!

Log4j2 RollingFile appenders clashing

Log4j2 RollingFile appenders clashing
Below is a simplified debug version of our log4j2 configuration file (We rollover nightly not every minute!).This configuration, instead of it creating a Rollover file each minute (as per theTimeBasedTriggeringPolicy) will create one rollover file (non-tarred), containing JSON formatted logging, which will be overwritten every 20KB(although it will end up being slightly greater than 20KB (See Screenshot).We also get the following errors (abbreviated with "..."):-
2016-10-07 08:47:34,433 default-workqueue-4 ERROR Unable to copy file /.../logs/logFile-2016-10-07-08:47:11.log to /.../logs/logFile-2016-10-07-08:47:11.log: java.nio.file.NoSuchFileException /.../logs/logFile-2016-10-07-08:47:11.log
If we switch the order of the timeBasedRollingFileJsonLayout appender and the sizeBasedRollingFilePatternLayoutWithZippedArchive appender then no rollover occurs at all.
If we remove the sizeBasedRollingFilePatternLayoutWithZippedArchive appender then the timeBasedRollingFileJsonLayout appender works as expected.
We have the two different appenders for different environments, where the logs may or may not be hooked up to ELK.In our real log4j2 config file we use properties to select the appropriate appender for the environment.I have removed the properties from this file for clarity and to rule them out as a possible cause of the problem.
We are using log4j 2.6.2.
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %logger{36} - %msg %n" />
</Console>
<RollingFile name="timeBasedRollingFileJsonLayout" append="true" fileName="logs/logFile.log" filePattern="logs/logFile-%d{yyyy-MM-dd-HH:mm}.log">
<JSONLayout properties="true" compact="true" eventEol="true" />
<Policies>
<TimeBasedTriggeringPolicy />
</Policies>
</RollingFile>
<RollingFile name="sizeBasedRollingFilePatternLayoutWithZippedArchive" append="true" fileName="logs/logFile.log" filePattern="logs/logFile-%d{yyyy-MM-dd}-%i.log.gz">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %logger{36} - %msg %n" />
<Policies>
<SizeBasedTriggeringPolicy size="20KB" />
</Policies>
</RollingFile>
</Appenders>
<Loggers>
<logger name="logger.one" level="info" additivity="false">
<AppenderRef ref="timeBasedRollingFileJsonLayout" />
</logger>
<Logger name="logger.two" level="info" additivity="false">
<AppenderRef ref="timeBasedRollingFileJsonLayout" />
</Logger>
<Logger name="logger.three" level="info" additivity="false">
<AppenderRef ref="timeBasedRollingFileJsonLayout" />
</Logger>
<Root level="info">
<AppenderRef ref="timeBasedRollingFileJsonLayout" level="all" />
</Root>
</Loggers>
</Configuration>
I am at a loss to understand why you think this should work. You have two appenders trying to write to the same file trying to rollover based on different criteria and rollover to files with different names. It is no surprise that you are getting the file is in use error since two things have it open at once.

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.

Resources