Perf4j Not Logging Correctly
I setup some stop watch calls in my code to measure some code blocks and all the messages are going into my primary log and not into the timing log. The perfStats.log file gets created just fine but all the messages go to the root log which I didn't think was supposed to happen according to the docs I've read. Is there something obvious I'm missing here?
perf4j tutorial link
Example code
import org.apache.log4j.Logger;
import org.perf4j.LoggingStopWatch;
import org.perf4j.StopWatch;
public class PerfLogger {
/**
* @param args
*/
public static void main(String[] args)
{
Logger logger = Logger.getLogger(PerfLogger.class.getName());
logger.info("Starting perf log test");
StopWatch stopWatch = new LoggingStopWatch("test time");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
stopWatch.stop();
}
}
Example log4j.xml
<log4j:configuration xmlns:log4j='http://jakarta.apache.org/log4j/'>
<appender name="STDOUT-DEBUG" class="org.apache.log4j.ConsoleAppender">
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d %-5p [%t]%x %M (%F:%L) - %m%n"/>
</layout>
&开发者_开发知识库lt;/appender>
<!-- Perf4J appenders -->
<!--
This AsyncCoalescingStatisticsAppender groups StopWatch log messages
into GroupedTimingStatistics messages which it sends on the
file appender defined below
-->
<appender name="CoalescingStatistics"
class="org.perf4j.log4j.AsyncCoalescingStatisticsAppender">
<!--
The TimeSlice option is used to determine the time window for which
all received StopWatch logs are aggregated to create a single
GroupedTimingStatistics log. Here we set it to 10 seconds, overriding
the default of 30000 ms
-->
<param name="TimeSlice" value="10000"/>
<appender-ref ref="fileAppender"/>
</appender>
<!-- This file appender is used to output aggregated performance statistics -->
<appender name="fileAppender" class="org.apache.log4j.FileAppender">
<param name="File" value="perfStats.log"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%m%n"/>
</layout>
</appender>
<!-- Loggers -->
<!--
The Perf4J logger. Note that org.perf4j.TimingLogger is the value of the
org.perf4j.StopWatch.DEFAULT_LOGGER_NAME constant. Also, note that
additivity is set to false, which is usually what is desired - this means
that timing statements will only be sent to this logger and NOT to
upstream loggers.
-->
<logger name="org.perf4j.TimingLogger" additivity="false">
<level value="INFO"/>
<appender-ref ref="CoalescingStatistics"/>
</logger>
<root>
<priority value="info"/>
<appender-ref ref="STDOUT-DEBUG"/>
</root>
</log4j:configuration>
I checked the jar and there is no class named TimingLogger in the perf4j jar, this can also be seen here by searching their code repository, which would explain the messages not going to the file you would expect them to. If you use the default LoggingStopWatch class they show in the example it looks like the only thing it will ever do is print to std err which you can see here . I tried changing the logger in my code to use their Log4JStopWatch class instead and changed the logger in the xml file to be org.perf4j.log4j.Log4JStopWatch but the messages go stdout instead of the file, which is probably because it isn't using the configs specified in the log4j.xml I'm guessing. I'll try and follow up with the team maintaining the project to see if they have an updated example or bug fix.
The issue is that you are using a LoggingStopWatch, which by default sends all of its output to stderr. You want to be using a Log4JStopWatch. Each of the direct subclasses of LoggingStopWatch is designed for a different framework (see http://perf4j.codehaus.org/apidocs/org/perf4j/LoggingStopWatch.html).
org.log4j.TimingLogger is not a class name but the default logger name used by Perf4j. If you are using Log4j you should use the org.perf4j.log4j.Log4JStopWatch class and don't forget to use the proper tag when creating it as stats will be grouped by that.
Following your example:
import org.apache.log4j.Logger;
import org.perf4j.LoggingStopWatch;
import org.perf4j.StopWatch;
public class PerfLogger {
/**
* @param args
*/
public static void main(String[] args)
{
StopWatch stopWatch = new LoggingStopWatch("main(..)");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
stopWatch.stop();
}
}
With that implementation and your same configuration file you get an output like the following:
Performance Statistics 2012-07-03 22:13:20 - 2012-07-03 22:13:30
Tag Avg(ms) Min Max Std Dev Count
main(..) 999.0 999 999 0.0 1
Hope this clarifies this problem.
精彩评论