How to configure log4j2's additivity to respect parent's level? - java

I think this code explains well enough what I'm trying to do
package us.benanderson;
public class MyClass {
private static final Logger LOG = LogManager.getLogger(MyClass.class);
...
// within a method
LOG.debug("only output to appFile");
LOG.error("output to both appFile and errorFile");
This is what I'd guess should be my config
<Loggers>
<Logger name="us.benanderson" level="debug" additivity="true">
<AppenderRef ref="appFile" />
</Logger>
<Root level="error">
<AppenderRef ref="errorFile" />
</Root>
</Loggers>
However, I'm finding that when additivity="true", debug messages are also output to errorFile. When additivity="false" nothing is output to errorFile. Is there any way to do what I'm trying to do?

I think the simplest way to achieve what you want is to put a level directly on the appender-ref. This eliminates the need to have a named logger in your config, simplifying the configuration a little.
Named loggers are still useful if you want to redirect log events for a certain package to a separate appender.
<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
<Appenders>
<File name="appFile" fileName="logs/appFile.log" append="true">
<PatternLayout pattern="%-5p %d{ABSOLUTE} [%t] %c - %m%n" />
</File>
<File name="errorFile" fileName="logs/errorFile.log" append="true">
<PatternLayout pattern="%-5p %d{ABSOLUTE} [%t] %c - %m%n" />
</File>
</Appenders>
<Loggers>
<Root level="trace">
<AppenderRef ref="appFile" level="debug" />
<AppenderRef ref="errorFile" level="error" />
</Root>
</Loggers>
</Configuration>
Threshold filters and filter combinations can be especially useful if you want to do more unusual filtering. For example, if you want to send only INFO and WARN level events to a certain appender, excluding TRACE/DEBUG, and also excluding ERROR and FATAL level events(!), you could do this:
<Console name="only-info-warn">
<PatternLayout pattern="%-5p %c %message %n" />
<Filters>
<!-- First deny error and fatal messages -->
<ThresholdFilter level="error" onMatch="DENY" onMismatch="NEUTRAL"/>
<ThresholdFilter level="fatal" onMatch="DENY" onMismatch="NEUTRAL"/>
<!-- Then accept info, warn, error, fatal and deny debug/trace -->
<ThresholdFilter level="warn" onMatch="ACCEPT" onMismatch="NEUTRAL"/>
<ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY"/>
</Filters>
</Console>

Use a filter.
Here's a configuration that outputs everything to C:/Logs/Log.log, and additionally outputs debug only to C:/Logs/Debug.log:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" debug="true">
<appender name="general-out" class="org.apache.log4j.FileAppender">
<param name="File" value="C:/Logs/Log.log"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d{ABSOLUTE} %-5p %c{1} : %m%n"/>
</layout>
</appender>
<appender name="debug-out" class="org.apache.log4j.FileAppender">
<param name="File" value="C:/Logs/Debug.log"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d{ABSOLUTE} %-5p %c{1} : %m%n"/>
</layout>
<filter class="org.apache.log4j.varia.LevelMatchFilter">
<param name="LevelToMatch" value="debug"/>
<param name="AcceptOnMatch" value="true"/>
</filter>
<filter class="org.apache.log4j.varia.DenyAllFilter"/>
</appender>
<root>
<appender-ref ref="debug-out" />
<appender-ref ref="general-out" />
</root>
</log4j:configuration>
The key part here is this:
<filter class="org.apache.log4j.varia.LevelMatchFilter">
<param name="LevelToMatch" value="debug"/>
<param name="AcceptOnMatch" value="true"/>
</filter>
<filter class="org.apache.log4j.varia.DenyAllFilter"/>
This allows things logged with debug, and then denies anything else.
Source: http://wiki.apache.org/logging-log4j/LogByLevel

Since you are using Log4j 2, you may want to use a ThresholdFilter. Using this filter, your configuration file can be as follows:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
<Appenders>
<File name="appFile" fileName="logs/appFile.log" append="true">
<PatternLayout pattern="%d %-5p (%c.java:%L).%M - %m%n" />
<ThresholdFilter level="DEBUG" />
</File>
<File name="errorFile" fileName="logs/errorFile.log" append="true">
<PatternLayout pattern="%d %-5p (%c.java:%L).%M - %m%n" />
<ThresholdFilter level="ERROR" />
</File>
</Appenders>
<Loggers>
<Logger name="us.benanderson" level="debug">
<AppenderRef ref="appFile" />
</Logger>
<Root level="error">
<AppenderRef ref="errorFile" />
</Root>
</Loggers>
</Configuration>

Based on your requirements; shouldn't the configuration be as below(with comments):-
<Loggers>
<!-- Do not trickle down 'debug' logs to parent logger using additivity as false; keeping them only in appFile -->
<Logger name="us.benanderson" level="debug" additivity="false">
<AppenderRef ref="appFile" />
</Logger>
<!-- Error messages by default go to both appfile and errorFile -->
<Root level="error">
<AppenderRef ref="errorFile" />
<AppenderRef ref="appFile" />
</Root>
</Loggers>
If you are specifically worried about error logs from "us.benanderson" package; you could try having a separate logger for 'error' level. So the configuration would look like :-
<Loggers>
<Logger name="us.benanderson" level="debug" additivity="false">
<AppenderRef ref="appFile" />
</Logger>
<!-- Not specifying additivity here would default to 'true'; hence the error logs would also be relayed to the root/errorFile -->
<Logger name="us.benanderson" level="error">
<AppenderRef ref="appFile" />
</Logger>
<Root level="error">
<AppenderRef ref="errorFile" />
</Root>
</Loggers>

Related

Migrating Log4j1 to Log4j2 for Spring 3 + Java8 App, but some logs are only printing on Console instead of Log file, what is missing

I have to migrate an old Java 8 app from Log4j 1.x to Log4j2 due to vulnerability, application is running fine without issues but logs are not appearing properly in log file.
This is the old log4j.xml file.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" debug="false">
<appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
<param name="Threshold" value="ERROR" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d %-5p [%t] [%c] %m%n" />
</layout>
</appender>
<appender name="APPLOG" class="org.apache.log4j.RollingFileAppender">
<param name="File" value="#LOG_DIR#/#LOG_FILE_NAME#" />
<param name="Append" value="true" />
<param name="MaxFileSize" value="15MB" />
<param name="MaxBackupIndex" value="10" />
<param name="Threshold" value="#THRESHOLD#" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d %-5p [%t] [%c] %m%n" />
</layout>
</appender>
<appender name="AUDITLOG" class="org.apache.log4j.DailyRollingFileAppender">
<param name="File" value="#AUDIT_LOG_DIR#/#AUDIT_LOG_FILE_NAME#"/>
<param name="Append" value="true"/>
<param name="Threshold" value="INFO"/>
<param name="DatePattern" value="'.'yyyy-MM-dd-HH" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="[%t] %m%n"/>
</layout>
</appender>
<category name="com.abc" additivity="false">
<priority value="#THRESHOLD#" />
<appender-ref ref="APPLOG" />
</category>
<category name="org.httpclient" additivity="false">
<priority value="INFO" />
<appender-ref ref="APPLOG" />
</category>
<category name="org.springframework" additivity="false">
<priority value="INFO" />
<appender-ref ref="APPLOG" />
</category>
<category name="com.mchange.v2" additivity="false">
<priority value="INFO" />
<appender-ref ref="APPLOG" />
</category>
<category name="org.mortbay" additivity="false">
<priority value="INFO" />
<appender-ref ref="APPLOG" />
</category>
<category name="org.apache" additivity="false">
<priority value="INFO" />
<appender-ref ref="APPLOG" />
</category>
<category name="AUDIT_LOGGER" additivity="false">
<priority value="INFO" />
<appender-ref ref="AUDITLOG"/>
</category>
<!-- Setup the Root category -->
<root>
<priority value="#THRESHOLD#" />
<appender-ref ref="APPLOG" />
</root>
</log4j:configuration>
This is converted log4j2.xml file
<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
<!--<Properties>
<Property name="logPath">target/cucumber-logs</Property>
<Property name="rollingFileName">cucumber</Property>
</Properties>-->
<Appenders>
<Console name="CONSOLE" target="SYSTEM_OUT">
<PatternLayout pattern="%d %-5p [%t] [%c] %m%n"/>
<ThresholdFilter level="ERROR"/>
</Console>
<RollingFile name="APPLOG" append="true"
fileName="#LOG_DIR#/#LOG_FILE_NAME#"
filePattern="#LOG_DIR#/#LOG_FILE_NAME#.%d{yyyy-MM-dd-HH}">
<PatternLayout pattern="%d %-5p [%t] [%c] %m%n"/>
<ThresholdFilter level="#THRESHOLD#"/>
<SizeBasedTriggeringPolicy size="15 MB"/>
<DefaultRolloverStrategy max="10"/>
</RollingFile>
<RollingFile name="AUDITLOG" append="true"
fileName="#AUDIT_LOG_DIR#/#AUDIT_LOG_FILE_NAME#"
filePattern="#AUDIT_LOG_DIR#/#AUDIT_LOG_FILE_NAME#.%d{yyyy-MM-dd-HH}">
<PatternLayout pattern="[%t] %m%n"/>
<ThresholdFilter level="INFO"/>
<!-- Causes a rollover once the date/time pattern no longer applies to the active file -->
<TimeBasedTriggeringPolicy modulate="true"/>
</RollingFile>
</Appenders>
<Loggers>
<!-- Category definitions -->
<Logger name="com.abc" level="#THRESHOLD#" additivity="false">
<AppenderRef ref="APPLOG"/>
</Logger>
<Logger name="org.httpclient" level="INFO" additivity="false">
<AppenderRef ref="APPLOG"/>
</Logger>
<Logger name="org.springframework" level="INFO" additivity="false">
<AppenderRef ref="APPLOG"/>
</Logger>
<Logger name="com.mchange.v2" level="INFO" additivity="false">
<AppenderRef ref="APPLOG"/>
</Logger>
<Logger name="org.mortbay" level="INFO" additivity="false">
<AppenderRef ref="APPLOG"/>
</Logger>
<Logger name="org.apache" level="INFO" additivity="false">
<AppenderRef ref="APPLOG"/>
</Logger>
<Logger name="AUDIT_LOGGER" level="INFO" additivity="false">
<AppenderRef ref="AUDITLOG"/>
</Logger>
<!-- Setup the Root category -->
<Root level="DEBUG">
<AppenderRef ref="APPLOG" level="#THRESHOLD#"/>
</Root>
</Loggers>
</Configuration>
Not sure what is missing/wrong in the log4j2 file but some logs only appear in Console and not in log file even though I am expecting exactly opposite.I have configured Console for only Error messages, and log file to contain messages like Info,Debug.
I am clueless, can someone help here?
Note: #LOG_DIR#/#LOG_FILE_NAME# - These variable values are replaced during build time.

Log4J2 -How to set referince to my new loggers

I have this xml config file for log4j2 but the loggers don't work. If I set the referince for root logger as "Errors" of "Info" (my new appenders) when I run the program the logger works and writes the data to logger files but if I set thouse appenders to my new loggers ("Information" and "ErrorLog") the logger doesn't write any data to my log files.
Here is my configuration xml file:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
<Appenders>
<Console name="Console">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
</Console>
<File name="Info" fileName="logs/info.log">
<PatternLayout>
<Pattern>%d %p %c{1.} [%t] %m%n</Pattern>
</PatternLayout>
</File>
<File name="Errors" fileName="logs/errors.log">
<PatternLayout>
<Pattern>%d %p %c{1.} [%t] %m%n</Pattern>
</PatternLayout>
</File>
</Appenders>
<Loggers>
<Logger name="Information" level="debug">
<AppenderRef ref="Info"/>
</Logger>
<Logger name="ErrorLog" level="error">
<AppenderRef ref="Errors"/>
</Logger>
<Root level="debug">
<AppenderRef ref="Console"/>
</Root>
</Loggers>
</Configuration>
Solved!
I modified the Loggers section and I deleted those 2 Loggers.
<Loggers>
<Root level="debug">
<level value="DEBUG" />
<appender-ref ref="Console" />
<appender-ref ref="Info" />
<appender-ref ref="Errors" />
</Root>
</Loggers>

Log4j2 Delete on Rollover is not working as expected, in Pingfederate

In Pingfederate, which internally uses log4j2 to log events. I am trying to rollover and delete older logs. While rollover functionality works, and the log is rolled over, but the deletion functionality doesn't seem to work. What do i don't understand ? Kindly explain and help me fix this.
Also, I am trying to log log4j2 itself, but for some reason it is not getting logged in the console logs.
Thanks a bunch.
If you need more information, kindly comment.
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="trace">
<Appenders>
<Console name="CONSOLE" target="SYSTEM_OUT">
<PatternLayout>
<charset>UTF-8</charset>
<pattern>%d %p %c{1.} [%t] %m%n</pattern>
</PatternLayout>
</Console>
<!-- Main log : A size based file rolling appender -->
<RollingFile name="FILE" fileName="${sys:pf.log.dir}/server_${sys:pf.ip}.log" filePattern="${sys:pf.log.dir}/server_${sys:pf.ip}.log.%i" ignoreExceptions="false">
<PatternLayout>
<charset>UTF-8</charset>
<pattern>%d %X{trackingid} %-5p [%c] %enc{%m}%n</pattern>
</PatternLayout>
<Policies>
<SizeBasedTriggeringPolicy size="10000 KB" />
</Policies>
<DefaultRolloverStrategy max="5" />
</RollingFile>
<!-- Security Audit log : A time/date based rolling appender -->
<RollingFile name="SecurityAudit2File" fileName="${sys:pf.log.dir}/audit_${sys:pf.ip}.log" filePattern="${sys:pf.log.dir}/audit_${sys:pf.ip}.%d{yyyy-MM-dd:HH:mm}.log" ignoreExceptions="false">
<PatternLayout>
<Pattern>%d %p %c{1.} [%t] %m%n</Pattern>
</PatternLayout>
<Policies>
<TimeBasedTriggeringPolicy interval="1"/>
</Policies>
<DefaultRolloverStrategy>
<Delete basePath="${sys:pf.log.dir}" maxDepth="1">
<IfFileName glob="audit*.log" />
<IfLastModified age="2m" />
</Delete>
</DefaultRolloverStrategy>
</RollingFile>
<!-- Admin Audit log : A time/date based rolling appender -->
<!--
<RollingFile name="AdminAudit" fileName="${sys:pf.log.dir}/admin.log" filePattern="${sys:pf.log.dir}/admin.%d{yyyy-MM-dd}.log" ignoreExceptions="false">
<PatternLayout>
<charset>UTF-8</charset>
<pattern>%d|%X{user}|%X{roles}|%X{event}|%m%n</pattern>
</PatternLayout>
<Policies>
<TimeBasedTriggeringPolicy />
</Policies>
</RollingFile>
-->
<!-- Admin API Audit log : A time/date based rolling appender -->
<!--
<RollingFile name="AdminApiAudit" fileName="${sys:pf.log.dir}/admin-api.log" filePattern="${sys:pf.log.dir}/admin-api.%d{yyyy-MM-dd}.log" ignoreExceptions="false">
<PatternLayout>
<charset>UTF-8</charset>
<pattern>%d|%X{api.user}|%X{api.authtype}|%X{api.clientip}|%X{api.httpmethod}|%X{api.url}|%X{api.status}%n</pattern>
</PatternLayout>
<Policies>
<TimeBasedTriggeringPolicy />
</Policies>
</RollingFile>
-->
<!-- Runtime API Audit log : A time/date based rolling appender -->
<RollingFile name="RuntimeApiAudit" fileName="${sys:pf.log.dir}/runtime-api.log" filePattern="${sys:pf.log.dir}/runtime-api.%d{yyyy-MM-dd}.log" ignoreExceptions="false">
<PatternLayout>
<charset>UTF-8</charset>
<pattern>%d|%enc{%X{api.user}}|%X{api.authtype}|%X{api.clientip}|%X{api.httpmethod}|%X{api.url}|%X{api.status}%n</pattern>
</PatternLayout>
<Policies>
<TimeBasedTriggeringPolicy />
</Policies>
</RollingFile>
</Appenders>
<Loggers>
<Logger name="httpclient.wire.content" level="WARN" />
<!-- Adjust the priority value to DEBUG to get additional logging to help troubleshoot XML Signature problems -->
<Logger name="org.sourceid.common.dsig" level="WARN" />
<!-- set to DEBUG to see inbound and outbound protocol messages -->
<Logger name="org.sourceid.saml20.bindings.LoggingInterceptor" level="WARN"/>
<Logger name="org.eclipse.jetty" level="WARN" />
<Logger name="org.eclipse.jetty.io.nio" level="WARN" />
<Logger name="org.apache.logging.log4j" level="TRACE">
<appender-ref ref="CONSOLE" />
</Logger>
<Logger name="org.sourceid.websso.profiles.sp.SpAuditLogger" level="INFO" additivity="false">
<appender-ref ref="SecurityAudit2File" />
</Logger>
<Logger name="org.sourceid.websso.profiles.idp.IdpAuditLogger" level="INFO" additivity="false">
<appender-ref ref="SecurityAudit2File" />
</Logger>
<Logger name="org.sourceid.websso.profiles.idp.AsAuditLogger" level="INFO" additivity="false">
<appender-ref ref="SecurityAudit2File" />
</Logger>
<Logger name="org.sourceid.wstrust.log.STSAuditLogger" level="INFO" additivity="false">
<appender-ref ref="SecurityAudit2File" />
</Logger>
<!--
<Logger name="AuditLogger" level="INFO" additivity="false">
<appender-ref ref="AdminAudit" />
</Logger>
<Logger name="AdminApiAuditLogger" level="INFO" additivity="false" includeLocation="false">
<appender-ref ref="AdminApiAudit" />
</Logger>
-->
<Logger name="RuntimeApiAuditLogger" level="INFO" additivity="false" includeLocation="false">
<appender-ref ref="RuntimeApiAudit" />
</Logger>
<Root level="TRACE">
<AppenderRef ref="CONSOLE" />
</Root>
</Loggers>
</Configuration>

Log4j2 logs into user home folder

I'm trying to save log4j2 logs into user home folder because the user has not right to write where the application is installed.
This is the relevant part of my log4j settings. Unfortunately it doesn't resolve user.home and so it creates the folder $user.home where the application is running.
<?xml version="1.0" encoding="UTF-8"?>
<configuration name="defaultConfiguration" status="warn" strict="true" monitorInterval="270">
<properties>
<property name="patternlayout">%d{dd/MM/yyyy HH:mm:ss} %5p %c{1}:%L - %m%n
</property>
<property name="filename">${user.home}/niro/logs/niroDesk.log</property>
<property name="filenamePattern">${user.home}/niro/logs/niroDesk.log-%d{yyyy-MM-dd}.log.gz
</property>
</properties>
<appenders>
<appender name="Console" type="Console" target="SYSTEM_OUT">
<layout type="PatternLayout" pattern="${patternlayout}" />
</appender>
<!-- Log su file ogni giorno, e mantenimento degli ultimi 5 files -->
<RollingFile name="File" fileName="${filename}" filePattern="${filenamePattern}" bufferedIO="true" immediateFlush="true" append="true">
<PatternLayout pattern="${patternlayout}" />
<Policies>
<TimeBasedTriggeringPolicy />
</Policies>
<DefaultRolloverStrategy>
<Delete basePath="${user.home}/niro/logs" maxDepth="2">
<IfFileName glob="niroDesk*.log.gz" />
<IfLastModified age="7d" />
</Delete>
</DefaultRolloverStrategy>
</RollingFile>
<appender name="AsyncFile" type="async" blocking="true" bufferSize="128">
<appender-ref ref="File" />
</appender>
</appenders>
<loggers>
<root level="error">
<appender-ref ref="Console" />
<appender-ref ref="AsyncFile" />
</root>
<logger level="warn" name="org.springframework" additivity="false">
<appender-ref ref="Console" />
<appender-ref ref="AsyncFile" />
</logger>
</loggers>
</configuration>
%d{dd/MM/yyyy HH:mm:ss} %5p %c{1}:%L - %m%n
${user.home}/niro/logs/niroDesk.log
${user.home}/niro/logs/niroDesk.log-%d{yyyy-MM-dd}.log.gz
<appenders>
<appender name="Console" type="Console" target="SYSTEM_OUT">
<layout type="PatternLayout" pattern="${patternlayout}" />
</appender>
<!-- Log su file ogni giorno, e mantenimento degli ultimi 5 files -->
<RollingFile name="File" fileName="${filename}" filePattern="${filenamePattern}" bufferedIO="true" immediateFlush="true" append="true">
<PatternLayout pattern="${patternlayout}" />
<Policies>
<TimeBasedTriggeringPolicy />
</Policies>
<DefaultRolloverStrategy>
<Delete basePath="${user.home}/niro/logs" maxDepth="2">
<IfFileName glob="niroDesk*.log.gz" />
<IfLastModified age="7d" />
</Delete>
</DefaultRolloverStrategy>
</RollingFile>
<appender name="AsyncFile" type="async" blocking="true" bufferSize="128">
<appender-ref ref="File" />
</appender>
</appenders>
<loggers>
<root level="error">
<appender-ref ref="Console" />
<appender-ref ref="AsyncFile" />
</root>
<logger level="warn" name="org.springframework" additivity="false">
<appender-ref ref="Console" />
<appender-ref ref="AsyncFile" />
</logger>
</loggers>
There is a way to solve this issue?
I solved the issue. You sould use ${sys:user.home} instead of ${user.home}.

Log4j2: Suppress only DEBUG messages

I am getting a lot of DEBUG messages in my logs. I want to suppress these, while preserving the INFO and ERROR messages. Here is my log4j2.xml:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
<!-- Author: Crunchify.com -->
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d [%t] %5p %c - %m%n" />
</Console>
<RollingFile name="RollingFile" filename="test.log"
filepattern="${LOG_PATH}${LOG_NAME}Log.%d{yyyyMMdd}.log.gz">
<PatternLayout pattern="%d [%t] %5p %c - %m%n" />
<Policies>
<SizeBasedTriggeringPolicy size="100 MB" />
</Policies>
<DefaultRolloverStrategy max="20" />
</RollingFile>
<NoSql name="elasticAppender">
<Elasticsearch cluster="test" host="test" port="test" index="test" type="log4j2"/>
</NoSql>
</Appenders>
<Loggers>
<Root level="debug">
<AppenderRef ref="NoSql" />
<AppenderRef ref="RollingFile" />
</Root>
<Logger name="test" level="info" additivity="false">
<AppenderRef ref="RollingFile" />
</Logger>
<Logger name="test" level="info">
</Logger>
<Logger name="test" level="INFO">
</Logger>
<Logger name="com.datastax.driver.core" level="INFO">
</Logger>
</Loggers>
</Configuration>
Does anyone know what change needs to be made here?
According to the Log4j manual, you might want to change <Root level="debug"> to <Root level="info">.

Categories

Resources