使用<rollingpolicy>和<triggeringpolicy> </triggeringpolicy> </rollingpolicy>的log4j.xml配置

时间:2011-01-16 14:43:50

标签: logging log4j

我尝试以这样的方式配置log4j.xml:文件将按文件大小滚动,并且滚动文件的名称将是:“C:/ temp / test / test_log4j-%d {yyyy-MM-dd -HH_mm_ss}的.log” 我跟着这个讨论:http://web.archiveorange.com/archive/v/NUYyjJipzkDOS3reRiMz

最后,只有当我添加时,它才对我有用:

try {
   Thread.sleep(1);
  } catch (InterruptedException e) {
   e.printStackTrace();
  }

方法:

public boolean isTriggeringEvent(Appender appender, LoggingEvent event,
            String filename, long fileLength)  

使它有效。

问题是,是否有更好的方法使其发挥作用? 因为这种方法会多次调用并减慢我​​的程序。

以下是代码:

package com.mypack.rolling;

import org.apache.log4j.rolling.RollingPolicy;
import org.apache.log4j.rolling.RolloverDescription;
import org.apache.log4j.rolling.TimeBasedRollingPolicy;

/**
 * Same as org.apache.log4j.rolling.TimeBasedRollingPolicy but acts only as
 * RollingPolicy and NOT as TriggeringPolicy.
 *
 * This allows us to combine this class with a size-based triggering policy
 * (decision to roll based on size, name of rolled files based on time)
 *
 */
public class CustomTimeBasedRollingPolicy implements RollingPolicy {

 TimeBasedRollingPolicy timeBasedRollingPolicy = new TimeBasedRollingPolicy();

 /**
  * Set file name pattern.
  * @param fnp file name pattern.
  */
 public void setFileNamePattern(String fnp) {
  timeBasedRollingPolicy.setFileNamePattern(fnp);
 }
 /*
 public void setActiveFileName(String fnp) {
  timeBasedRollingPolicy.setActiveFileName(fnp);
 }*/

 /**
  * Get file name pattern.
  * @return file name pattern.
  */
 public String getFileNamePattern() {
  return timeBasedRollingPolicy.getFileNamePattern();
 }

 public RolloverDescription initialize(String file, boolean append) throws SecurityException {
  return timeBasedRollingPolicy.initialize(file, append);
 }

 public RolloverDescription rollover(String activeFile) throws SecurityException {
  return timeBasedRollingPolicy.rollover(activeFile);
 }

 public void activateOptions() {
  timeBasedRollingPolicy.activateOptions();
 }
}



package com.mypack.rolling;

import org.apache.log4j.helpers.OptionConverter;
import org.apache.log4j.Appender;
import org.apache.log4j.rolling.TriggeringPolicy;
import org.apache.log4j.spi.LoggingEvent;
import org.apache.log4j.spi.OptionHandler;

/**
 * Copy of org.apache.log4j.rolling.SizeBasedTriggeringPolicy but able to accept
 * a human-friendly value for maximumFileSize, eg. "10MB"
 * 
 * Note that sub-classing SizeBasedTriggeringPolicy is not possible because that
 * class is final
 */
public class CustomSizeBasedTriggeringPolicy implements TriggeringPolicy, OptionHandler {

 /**
  * Rollover threshold size in bytes.
  */
 private long maximumFileSize = 10 * 1024 * 1024; // let 10 MB the default max size

 /**
  * Set the maximum size that the output file is allowed to reach before
  * being rolled over to backup files.
  * 
  * <p>
  * In configuration files, the <b>MaxFileSize</b> option takes an long
  * integer in the range 0 - 2^63. You can specify the value with the
  * suffixes "KB", "MB" or "GB" so that the integer is interpreted being
  * expressed respectively in kilobytes, megabytes or gigabytes. For example,
  * the value "10KB" will be interpreted as 10240.
  * 
  * @param value
  *            the maximum size that the output file is allowed to reach
  */
 public void setMaxFileSize(String value) {
  maximumFileSize = OptionConverter.toFileSize(value, maximumFileSize + 1);
 }

 public long getMaximumFileSize() {
  return maximumFileSize;
 }

 public void setMaximumFileSize(long maximumFileSize) {
  this.maximumFileSize = maximumFileSize;
 }

 public void activateOptions() {
 }

 public boolean isTriggeringEvent(Appender appender, LoggingEvent event,
            String filename, long fileLength) {
  try {
   Thread.sleep(1);
  } catch (InterruptedException e) {
   e.printStackTrace();
  }

  boolean result = (fileLength >= maximumFileSize);

  return result;
 }

}

和log4j.xml:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">

<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" debug="true">
 <appender name="console" class="org.apache.log4j.ConsoleAppender">
  <param name="Target" value="System.out" />
  <layout class="org.apache.log4j.PatternLayout">
   <param name="ConversionPattern" value="%d [%t] %-5p %c -> %m%n" />
  </layout>
 </appender>

 <appender name="FILE" class="org.apache.log4j.rolling.RollingFileAppender">
  <param name="file" value="C:/temp/test/test_log4j.log" />
  <rollingPolicy class="com.mypack.rolling.CustomTimeBasedRollingPolicy">
   <param name="fileNamePattern" value="C:/temp/test/test_log4j-%d{yyyy-MM-dd-HH_mm_ss}.log" />
  </rollingPolicy>
  <triggeringPolicy class="com.mypack.rolling.CustomSizeBasedTriggeringPolicy">
   <param name="MaxFileSize" value="200KB" />
  </triggeringPolicy>
  <layout class="org.apache.log4j.PatternLayout">
   <param name="ConversionPattern" value="%d [%t] %-5p %c -> %m%n" />
  </layout>
 </appender>

 <logger name="com.mypack.myrun" additivity="false">
  <level value="debug" />
  <appender-ref ref="FILE" />
 </logger>

 <root>
  <priority value="debug" />
  <appender-ref ref="console" />
 </root>

</log4j:configuration>

2 个答案:

答案 0 :(得分:0)

如果向该方法添加调试输出,您将看到该方法经常被调用,即使触发器已经触发,但文件大小仍然大于最大文件大小。

我假设滚动行为有某种缓冲区,它在实际(同步?)翻转发生之前被清空。

我认为它与com.mypack.rolling.CustomTimeBasedRollingPolicy中的fileNamePattern有关。只要文件名中的“第二个”没有改变,就会连续调用CustomSizeBasedTriggeringPolicy.isTriggeringEvent方法,其数量大于最大文件大小。

答案 1 :(得分:0)

感谢您的回答。

我做了2次更改:
1)I为文件名模式添加毫秒:

<param name="fileNamePattern" value="C:/temp/test/test_log4j-%d{yyyy-MM-dd-HH_mm_ss_SSS}.log" />  

2)我改变了

com.mypack.rolling.CustomSizeBasedTriggeringPolicy.isTriggeringEvent

public boolean isTriggeringEvent(Appender appender, LoggingEvent event,
                                                String filename, long fileLength) {

        boolean result = (fileLength >= maximumFileSize);

        if (result) {
            try {
                Thread.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        return result;
    }

现在,只有在创建(滚动)新文件时才会调用Thread.sleep(1)。