2

I am trying to log some user data to log file whenever a request arrive with log4j in Play! Framework 1.2.5. I need to have 2 separated log file which will be used by different methods and classes. I would like to have my customized log files formatted as :

date with time - request running time and some string

First question : Could you please show me a helpful tutorial or an answer? Because whatever I have done so far was useless.

The second question : How can I configure log4j to log for each level such as only log ERROR message on one file, while only print INFO and WARN message on other file. My log4j.properties file is below. I know the previleges of message. But even I defined threshold why ERROR, FATAL or WARN messages also are written to info file?

log4j.rootLogger = ERROR, JUSTINFO, JUSTERROR
log4j.logger = INFO

log4j.appender.JUSTINFO = org.apache.log4j.RollingFileAppender
log4j.appender.JUSTINFO.layout = org.apache.log4j.PatternLayout
log4j.appender.JUSTINFO.layout.ConversionPattern = %d{dd/MM/yyyy HH:mm:ss} - [%X{processTime}] - %m%n
log4j.appender.JUSTINFO.File = log/info.log
log4j.appender.JUSTINFO.Threshold = INFO

log4j.appender.JUSTERROR = org.apache.log4j.RollingFileAppender
log4j.appender.JUSTERROR.layout = org.apache.log4j.PatternLayout
log4j.appender.JUSTERROR.layout.ConversionPattern = %d{dd/MM/yyyy HH:mm:ss} - [%X{processTime}] - %m%n
log4j.appender.JUSTERROR.File =log/warn.log
log4j.appender.JUSTERROR.Threshold = ERROR
Wayan Wiprayoga
  • 4,472
  • 4
  • 20
  • 30
Emilla
  • 484
  • 1
  • 10
  • 23

1 Answers1

3

You may use NDC (Nested Diagnostic Context) or MDC (Mapped Diagnostic Context). Below is an example calling the Logger on controller :

public static StopWatch sw = new StopWatch();

public static void request001() {
    sw.start(); // start timer
    // logic of processing the request
    ...
    sw.stop(); // stop timer
    // using MDC to put elapsed time in milisecond
    MDC.put("processTime", sw.getElapsedTime());
    Logger.info("this is request001"); 
}    

And the log4j.properties example file should be like follow (using console appender):

log4j.rootLogger = INFO, loggerName
log4j.appender.loggerName = org.apache.log4j.ConsoleAppender
log4j.appender.loggerName.layout = org.apache.log4j.PatternLayout
log4j.appender.loggerName.layout.ConversionPattern = %d{dd MMM yyyy HH:mm:ss,SSS} - [%X{processTime}] - %m

%d{dd MMM yyyy HH:mm:ss,SSS} is used to output the date while%X{processTime} is used to get the processTime value stored in MDC.

You can check the references here :

  1. Log4j 1.2 Manual
  2. PatternLayout JavaDoc
  3. What is the difference between Log4j's NDC and MDC facilities?

Update

Threshold properties is represents the minimum Level/Priority accepted, not an absolute Level/Priority. So, your JUSTINFO logger should log logger that have priority starting from INFO or higher.

If you want to separate the logging message to exactly match the level (absolute level range filter), I think you should consider to replace the log4j.properties to log4j.xml (configuration using xml). I give you example :

<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
   <!-- JUSTINFO logging -->
   <appender name="JUSTINFO" class="org.apache.log4j.FileAppender">
      <param name="File" value="./info.log" />
      <param name="Threshold" value="INFO" />
      <layout class="org.apache.log4j.PatternLayout">
         <param name="ConversionPattern" value="%-5p %t - %m%n"/>
      </layout>
      <filter class="org.apache.log4j.varia.LevelRangeFilter">
         <param name="LevelMin" value="INFO" />
         <param name="LevelMax" value="INFO" />
       </filter>
    </appender>

    <!-- JUSTERROR logging -->
    <appender name="JUSTERROR" class="org.apache.log4j.FileAppender">
       <param name="File" value="./error.log" />
       <layout class="org.apache.log4j.PatternLayout">
          <param name="ConversionPattern" value="%-5p %t - %m%n"/>
       </layout>
       <filter class="org.apache.log4j.varia.LevelRangeFilter">
          <param name="LevelMin" value="ERROR" />
          <param name="LevelMax" value="ERROR" />
       </filter>
    </appender>

    <!-- define root logger priority to ERROR -->
    <root>
       <level value="ERROR"/>
       <appender-ref ref="JUSTINFO"/>
       <appender-ref ref="JUSTERROR"/>
    </root>
</log4j:configuration>

Here also a good reference for you :

  1. Why chose XML over properties files for Log4J configuration?
  2. How to set filter in the log4j.xml
Community
  • 1
  • 1
Wayan Wiprayoga
  • 4,472
  • 4
  • 20
  • 30
  • thank you for your answer. It worked. But it could not cover whole my problem. I need to write info message to a log file just for info and warn or any error message to another log file. I found an example of custom appender and when I put it in log4j.properties, I got classNotFound exception – Emilla May 07 '13 at 18:12
  • Please see my updated answer. Hope it useful for you, friend. ;) – Wayan Wiprayoga May 08 '13 at 04:19
  • I am getting this warning when using log4j.xml. should I user a new appender and root for JUSTINFO as well?log4j:WARN Continuable parsing error 16 and column 12 log4j:WARN The content of element type "appender" must match "(errorHandler?,par am*,rollingPolicy?,triggeringPolicy?,connectionSource?,layout?,filter*,appender- ref*)". – Emilla May 08 '13 at 19:32
  • I have updated my answer. I have tested it myself. Hope make you better understand. Good luck, friend ;) – Wayan Wiprayoga May 09 '13 at 01:38
  • 1
    Ahh . thank you my brother. you were too usefull for the logging process of my project :) thanks again. – Emilla May 09 '13 at 08:04