views:

169

answers:

2

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/'&gt;    

    <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>
    </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>
A: 

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.

Jeremy T
You definitely need to use the Log4JStopWatch and you need to manually call start() although the examples shows otherwise. However I've noticed that it appears when you take a time measurement larger than your specified time slice, i.e. you take a 5 minute measurement and have a 10 sec time slice defined, the measurement never makes it to the log.
Jeremy T
A: 

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).

alex
yeah I mentioned that already below, but the tutorial for developers on the site is outdated because they indicate the opposite of this. Also just using the Log4JStopWatch doesn't make it log to a separate file either, it appears to default to the root logger and not the one specified.
Jeremy T