I'm having problem with configuring log4j.properties when filtering with StringMatchFilter.
I'm trying to separate specific logs to new file using StringMatchFilter but haven't got anything written in that new file. My app is using Spring 4.1.7. with slf4j 1.7.12. and log4j 1.2.17. and is having following configuration in my log4j.properties file:
log4j.rootLogger=ALL, file, priceImportFile, DB, console
# file
log4j.appender.file=org.apache.log4j.DailyRollingFileAppender
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{HH:mm:ss,SSS} %-5p {%t} [%C] %m%n
log4j.appender.file.File=${catalina.home}/logs/file.log
log4j.appender.file.DatePattern='-'yyyy-MM-dd'.log'
# importFile
log4j.appender.priceImportFile=org.apache.log4j.DailyRollingFileAppender
log4j.appender.priceImportFile.layout=org.apache.log4j.PatternLayout
log4j.appender.priceImportFile.layout.ConversionPattern=%d{HH:mm:ss,SSS} %-5p {%t} [%C] %m%n
log4j.appender.priceImportFile.File=${catalina.home}/logs/import-file.log
log4j.appender.priceImportFile.DatePattern='-'yyyy-MM-dd'.log'
log4j.appender.priceImportFile.filter.1=org.apache.log4j.varia.StringMatchFilter
log4j.appender.priceImportFile.filter.1.StringToMatch=row is duplicated
log4j.appender.priceImportFile.filter.1.AcceptOnMatch=true
# Setting threshold for specific packages
log4j.logger.org.springframework=DEBUG
log4j.logger.org.springframework.web.servlet.view.ContentNegotiatingViewResolver=TRACE
log4j.logger.org.apache=WARN
log4j.logger.com.mchange=WARN
log4j.logger.org.hibernate=INFO
log4j.logger.com.product=ALL
log4j.logger.com.product.service.www_admin.http=WARN
Would appreciate your help.
According to the Javadocs, Log4j filters return one of 3 values after checking the log message:
If the value DENY is returned, then the log event is dropped immediately without consulting with the remaining filters. If the value NEUTRAL is returned, then the next filter in the chain is consulted. If there are no more filters in the chain, then the log event is logged. Thus, in the presence of no filters, the default behaviour is to log all logging events. If the value ACCEPT is returned, then the log event is logged without consulting the remaining filters.
Meanwhile, the StringMatchFilter
Javadocs have this to say:
The filter admits two options StringToMatch and AcceptOnMatch. If there is a match between the value of the StringToMatch option and the message of the LoggingEvent, then the decide(LoggingEvent) method returns Filter.ACCEPT if the AcceptOnMatch option value is true, if it is false then Filter.DENY is returned. If there is no match, Filter.NEUTRAL is returned.
Log4j will check each filter in turn. If a filter returns NEUTRAL, then it moves onto the next filter. If a filter returns either DENY or ACCEPT then then no further filters are checked and the log message is either discarded or accepted and logged. If the last filter returns NEUTRAL then the message is accepted.
So the problem is that when the message doesn't match your filter string, the StringMatchFilter returns NEUTRAL. Since there are no more filters the log message is accepted and written out. To change this behaviour you need to add a DenyAllFilter
filter as the second filter:
log4j.appender.priceImportFile.filter.2=org.apache.log4j.varia.DenyAllFilter