Log4j parsing error adding triggeringPolicy on SMTPAppender - java

On my SpringMVC project I enabled email logging starting from INFO massage (default behaviour is starting from ERROR message).
This is my appender configuration in log4j.xml:
<appender name="SMTP" class="org.apache.log4j.net.SMTPAppender">
<param name="SMTPDebug" value="true"/>
<param name="SMTPProtocol" value="smtps"/>
<param name="SMTPUsername" value="*"/>
<param name="SMTPPassword" value="*"/>
<param name="SMTPHost" value="*"/>
<param name="SMTPPort" value="*"/>
<param name="Subject" value="*"/>
<param name="To" value="*"/>
<param name="From" value="*"/>
<param name="BufferSize" value="5"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d{MM/dd/yyyy HH:mm:ss} [%M] %-5p %C - %m%n" />
</layout>
<triggeringPolicy class="org.apache.log4j.rolling.FilterBasedTriggeringPolicy">
<filter class="org.apache.log4j.filter.LevelRangeFilter">
<param name="levelMin" value="INFO" />
</filter>
</triggeringPolicy>
</appender>
It works on runtime but I get the same xml parser error and warning launching the project:
log4j:WARN The content of element type "appender" must match "(errorHandler?,param,rollingPolicy?,triggeringPolicy?,connectionSource?,layout?,filter*,appender-ref*)".*
What's wrong?
I'm using log4j-1.2.16.

I believe the reason to be that the order of the children in the XML <appender> element must follow the order declared in the DTD that the warning message shows. Quoting W3Schools about DTD elements:
When children are declared in a sequence separated by commas, the children must appear in the same sequence in the document.
Put your <layout> element after the <triggeringPolicy> element and the warning will likely disappear.

Related

Logging different levels using same object to different files

My simple question is : If I have two statements like logger.info() and logger.error() in Java (using log4j), I want the results of these two lines to be printed in two separate files. That is, logger.info(...) should print to a file say myLog.info and logger.error(...) should print to myLog.error file. I am using rolling file appender for this task. Also I want just one logger object to do the task. Someone might suggest two or more different loggers one for each file, but that's not the case.
I tried searching a solution for the problem. One of the links Creating multiple log files of different content with log4j says about "threshold" and I even tried to add threshold in my xml configuration file. But what it actually is doing that : info log is being printed in myLog.info file but error log gets printed in both the files. Can it be done through xml configuration file alone or a separate properties file is needed? If xml file is sufficient, then what needs to be done?
I am preferring xml file over properties file. If there is a working solution using only xml configuration file, that would be sufficient. Thanks in advance.
You could use filters to deny any messages except those of the level you want. Here is an example of how to do this:
First a class to test our efforts:
package test;
import org.apache.log4j.Logger;
public class Main {
private static final Logger logger = Logger.getLogger(Main.class);
public static void main(String[] args) {
logger.debug("here's some debug");
logger.info("here's some info");
logger.warn("here's some warn");
logger.error("here's some error");
logger.fatal("here's some fatal");
}
}
Next a log4j.xml config file to set up the appenders and loggers:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j='http://jakarta.apache.org/log4j/'>
<appender name="consoleAppender" class="org.apache.log4j.ConsoleAppender">
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d %-5p [%c{1}] %m %n" />
</layout>
</appender>
<appender name="debugLog" class="org.apache.log4j.RollingFileAppender">
<param name="File" value="logs/debug.log" />
<param name="Append" value="true" />
<param name="MaxFileSize" value="5000KB" />
<param name="maxBackupIndex" value="5" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss} [%t] %-5p - %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>
<appender name="infoLog" class="org.apache.log4j.RollingFileAppender">
<param name="File" value="logs/info.log" />
<param name="Append" value="true" />
<param name="MaxFileSize" value="5000KB" />
<param name="maxBackupIndex" value="5" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss} [%t] %-5p - %m%n" />
</layout>
<filter class="org.apache.log4j.varia.LevelMatchFilter">
<param name="LevelToMatch" value="INFO" />
<param name="AcceptOnMatch" value="true" />
</filter>
<filter class="org.apache.log4j.varia.DenyAllFilter" />
</appender>
<logger name="test" additivity="false">
<level value="DEBUG" />
<appender-ref ref="consoleAppender" />
<appender-ref ref="debugLog" />
<appender-ref ref="infoLog" />
</logger>
</log4j:configuration>
This pattern will allow you to generate a separate log for each log level, just repeat the configuration that I have provided for either debug or info logging. Note that the console appender will accept all levels.
I was able to gain some insight from this post so I thought I should give credit.

log4j smtp appender overriding gives unexpected behavior?

I have overridden log4j smtp appender for some purpose. The problem is if i keep <param name="Threshold" value="INFO"/> Then it would send mails properly. But if i keep <param name="Threshold" value="ERROR"/> Then no mails are sent. What is the problem? Please find my code.
public class MyAppender extends SMTPAppender{
#Override
protected void sendBuffer() {
//Some code to format email body
}
}
log4j.xml
<!-- Appenders -->
<appender name="mail" class="com.service.MyAppender">
<param name="BufferSize" value="2"/>
<param name="BufferedIO" value="true"/>
<param name="Threshold" value="ERROR"/>
<param name="SMTPHost" value="myhost"/>
<param name="From" value="abc#co.com"/>
<param name="To" value="def#ld.com"/>
<param name="Subject" value="Testing Testing"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern"
value="%d{yyyy-MM-dd HH:mm:ss} %-5p %c{2}:%L - %m%n"/>
</layout>
</appender>
<appender name="ASYNC" class="org.apache.log4j.AsyncAppender">
<param name="BufferSize" value="500"/>
<appender-ref ref="mail"/>
</appender>
<root>
<level value="ERROR" />
<appender-ref ref="ASYNC" />
</root>
I looked into SMTPAppender source code and i believe below lines are the problem.
if(evaluator.isTriggeringEvent(event)) {
sendBuffer();
}
According to log4j documentation, all log events with value lower than Treshold will be filtered out (i.e. not sent).
It's possible that changing Treshold to more restrictive filters out all messages that are logged in your case.
Make sure that you actually have events with log level ERROR (or higher - FATAL).

BufferSize location in log4j xml configuration

I have the following in my log4j.xml configuration:
<appender name="FileAppender" class="org.apache.log4j.DailyRollingFileAppender">
<param name="File" value="${MDCapture.logfile.dir}/${APP_NAME}.log"/>
<param name="BufferedIO" value="false"/>
<param name="DatePattern" value="'.'yyyy-MMM-dd"/>
<layout class="org.apache.log4j.TTCCLayout">
<param name="DateFormat" value="ISO8601"/>
</layout>
</appender>
<appender name="AsyncAppenders" class="org.apache.log4j.AsyncAppender">
<appender-ref ref="FileAppender"/>
<param name="BufferSize" value="1000" />
</appender>
When I run it, I get the following warning:
08-Apr-2013 14:22:15
log4j:WARN Continuable parsing error 18 and column 13
log4j:WARN The content of element type "appender" must match "(errorHandler?,param*,rollingPolicy?,triggeringPolicy?,connectionSource?,layout?,filter*,appender-ref*)".
Do I need to move as follows:
<appender name="FileAppender" class="org.apache.log4j.DailyRollingFileAppender">
<param name="File" value="${MDCapture.logfile.dir}/${APP_NAME}.log"/>
<param name="BufferedIO" value="false"/>
<param name="DatePattern" value="'.'yyyy-MMM-dd"/>
<!-- HERE -->
<param name="BufferSize" value="1000" />
<!-- END HERE -->
<layout class="org.apache.log4j.TTCCLayout">
<param name="DateFormat" value="ISO8601"/>
</layout>
</appender>
Well, I only see 13 lines of code, but
<appender name="AsyncAppenders" class="org.apache.log4j.AsyncAppender">
<appender-ref ref="FileAppender"/>
<param name="BufferSize" value="1000" />
</appender>
has <appender-ref> and <param> tags in the wrong order.
WARN The content of element type "appender" must match "(errorHandler?,param*,rollingPolicy?,triggeringPolicy?,connectionSource?,layout?,filter*,appender-ref*)".
to use BufferSize, you must have log4j v1.2.17 at least. Please check the jar version that you are using.

jboss 6.x: sending e-Mails if specific type of Exception is thrown

We use jBoss logging and got it finally working - now we have the problem that we dont want to send an e-Mail everytime an ERROR accures. We just want to send an e-Mail if defined Exceptions are thrown. e.g. com.myproject.exceptions.fatal.ProjectFatalException
The default definition in the "jboss-logging.xml" looks like this:
<log4j-appender name="SMTP" class="org.apache.log4j.net.SMTPAppender">
<error-manager>
<only-once/>
</error-manager>
<level name="ERROR"/>
<properties>
<property name="to">admin#myhost.domain.com</property>
<property name="from">nobody#myhost.domain.com</property>
<property name="subject">JBoss Sever Errors</property>
<property name="SMTPHost">localhost</property>
<property name="bufferSize">10</property>
</properties>
<formatter>
<pattern-formatter pattern="%d %-5p [%c] (%t) %m%n"/>
</formatter>
</log4j-appender>
Although this answer is almost 3 months late, hopefully this still helps you and others in the future. You can use the StringMatchFilter to limit the email to a certain error.
You can solve this problem with a combination of SMTPAppender and filters. Add the following in your jboss-log4j.xml:-
<!-- add the SMTPAppender -->
<appender name="SMTP" class="org.apache.log4j.net.SMTPAppender">
<errorHandler class="org.jboss.logging.util.OnlyOnceErrorHandler"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d %-5p [%c] (%t) %m%n"/>
</layout>
<param name="Threshold" value="ERROR"/>
<param name="To" value="someone#somewhere.com"/>
<param name="From" value="someone#somewhere.com"/>
<param name="Subject" value="JBoss Alert: ProjectFatalException"/>
<param name="SMTPHost" value="some.smtp.host"/>
<param name="BufferSize" value="512"/>
<filter class="org.apache.log4j.varia.LevelRangeFilter">
<param name="LevelMin" value="error" />
<param name="LevelMax" value="fatal" />
</filter>
<filter class="org.apache.log4j.varia.StringMatchFilter">
<param name="StringToMatch" value="ProjectFatalException" />
<param name="AcceptOnMatch" value="true" />
</filter>
<filter class="org.apache.log4j.varia.DenyAllFilter"/>
</appender>
<!-- add the SMTP appender to your project package category -->
<category name="com.myproject">
<priority value="ERROR"/>
<appender-ref ref="SMTP"/>
</category>
As a side note, generally it is a good idea to add slow appenders like SMTP as ASYNC. By default it is synchronous.

with SMTPAppender I receive only ERROR and not INFO type of log items

I've configured an SMTPAppender into my Java app.
<appender name="AdministratorEmail" class="org.apache.log4j.net.SMTPAppender">
<param name="Threshold" value="info" />
<param name="BufferSize" value="512" />
<param name="SMTPHost" value="smtp.sss.intranet" />
<param name="From" value="adminEbookMaker#sss.intranet" />
<param name="To" value="user#sss.it" />
<param name="Subject" value="errors" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="[%d{ISO8601}]%n%n%-5p%n%n%c%n%n%m%n%n" />
</layout>
<filter class="org.apache.log4j.varia.LevelRangeFilter">
<param name="LevelMin" value="info" />
<param name="LevelMax" value="fatal" />
</filter>
</appender>
I receive only the ERROR log type and not the INFO type! I changed the LevelMin but nothing, I inserted the Thresold, but nothing!
Does someone have any kind of suggestion?
The SMTPAppender by design only logs ERROR and above messages. This level cannot be affected by properties. The documentation for the appended states:
By default, an email message will be sent when an ERROR or higher severity message is appended. The triggering criteria can be modified by setting the evaluatorClass property with the name of a class implementing TriggeringEventEvaluator, setting the evaluator property with an instance of TriggeringEventEvaluator or nesting a triggeringPolicy element where the specified class implements TriggeringEventEvaluator
See: Class SMTPAppender
The fact that you are seeing INFO messages only after the first ERROR is due to the bufferSize property which shows the 'n' most recent log lines before the error to give context to the error.
Further research on this shows that there is an implementation of the required interface for TriggerEventEvaluator in the 'extras companion'
This can be downloaded from: Apache Download Mirrors
If you include this in your project you can then add the following to your SMTPAppender definition in log4j.xml (note the properties format is not supported!)
<appender name="SMTP" class="org.apache.log4j.net.SMTPAppender">
...
<triggeringPolicy class="org.apache.log4j.rolling.FilterBasedTriggeringPolicy">
<filter class="org.apache.log4j.filter.LevelRangeFilter">
<param name="levelMin" value="INFO" />
</filter>
</triggeringPolicy>
...
</appender>

Categories

Resources