【问题标题】:How to configure a log4j file appender which rolls the log file every 15 minutes如何配置每 15 分钟滚动一次日志文件的 log4j 文件附加程序
【发布时间】:2011-06-18 23:38:40
【问题描述】:

我知道我可以使用 DailyRollingFileAppender 每月、每天、每半天、每小时或每分钟滚动日志文件。但是如何配置 log4j 以每 15 分钟滚动一次日志文件。

如果通过配置无法做到这一点,请建议/指导我如何扩展 log4j 的文件附加程序来实现这一点。

感谢和问候。

【问题讨论】:

    标签: java log4j


    【解决方案1】:

    Log4J 中DailyRollingFileAppender 的Javadoc 表明基于时间的滚动只发生在基于单位的滚动(日、周、月等)上。这意味着您可以使用该模式获得的最接近的是'.'yyyy-MM-dd-HH-mm,它会每分钟滚动一次。

    我的建议是执行以下操作之一:

    • 由于您以固定间隔运行,因此请编写一个自定义 FileAppender,使用从 DailyRollingFileAppender 借用的逻辑进行计算
    • 如果您有一定的灵活性,请从 Log4J 切换到 LOGBack,并使用从 LOGBack 时间计算中借用的逻辑编写自定义 RollingPolicy(这将与 Log4J 中的逻辑非常相似)

    顺便说一句,如果您选择后者,我建议您考虑编码到SLF4J API,并使用 LOGBack(或 Log4J)作为底层实现。

    【讨论】:

    • 关于第一个选项,我认为您可以编写自定义触发策略而不是编写新的附加程序。
    • 不幸的是,我没有使用 LogBack 的灵活性。所以是的,我将处理选项 1。顺便说一句,请就如何编写自定义触发策略提出建议。
    • 我正在通过扩展 DailyRollingFileAppender 来处理选项 1。会让你知道进展如何。
    • @CoolBeans:我认为TriggeringPolicy 是 LOGBack 的一部分,而不是 Log4J(至少我只能在 LOGBack 中找到它...)
    【解决方案2】:

    这是我用于每小时的代码。您可以每 15 分钟更改一次 - 请参阅方法 nextCalendar()。此代码基于DatedFileAppender

    package com.stackoverflow.log4j;
    
    import java.io.File;
    import java.util.Calendar;
    import java.util.Date;
    
    import org.apache.log4j.FileAppender;
    import org.apache.log4j.spi.LoggingEvent;
    
    /**
     * Based on biz.minaret.log4j.DatedFileAppender, 
     * decompiled with JAD,
     * revised to use optional hours.
     */
    public class DistinctDailyFileAppender extends FileAppender {
    
    public static final String DEFAULT_DIRECTORY = "logs";
    public static final String DEFAULT_SUFFIX = ".txt";
    public static final String DEFAULT_PREFIX = "";
    
    private String directory = DEFAULT_DIRECTORY;
    private String prefix = DEFAULT_PREFIX;
    private String suffix = DEFAULT_SUFFIX;
    private File currentPath = null;
    private Calendar currentCalendar = null;
    private long nextTime = 0l;
    private boolean hourly = false;
    
    /**
     * Constructor.
     */
    public DistinctDailyFileAppender() {}
    
    /**
     * This method is automatically called once by the system, 
     * immediately after all properties are set, prior to release.
     */
    public void activateOptions() {
    
        currentPath = new File(directory);
        if (!currentPath.isAbsolute()) {        
            errorHandler.error("Directory failure for appender [" + name + "] : " + directory);
            return;
        }
    
        currentPath.mkdirs();
    
        // We can write; initialize calendar
        if (currentPath.canWrite()) {
            currentCalendar = Calendar.getInstance();
        } else {
            errorHandler.error("Cannot write for appender [" + name + "] : " + directory);
            return;
        }       
    }
    
    /**
     * This is called, synchronized by parent.
     */
    public void append(LoggingEvent event) {
    
        if (layout == null) {
            errorHandler.error("No layout set for appender [" + name + "].");
            return;
        }
    
        if (currentCalendar == null) {
            errorHandler.error("Improper initialization for appender [" + name + "].");
            return;
        }
    
        long nowTime = System.currentTimeMillis();
        if (nowTime >= nextTime) {
            currentCalendar.setTime(new Date(nowTime));
            String timestamp = generateTimestamp(currentCalendar);
            nextCalendar(currentCalendar);
            nextTime = currentCalendar.getTime().getTime();
            File file = new File(currentPath, prefix + timestamp + suffix);
            fileName = file.getAbsolutePath();
            super.activateOptions();
        }
    
        if (super.qw == null) {
    
            errorHandler.error("No output stream or file set for the appender named [" + name + "].");
            return;
    
        } else {
    
            subAppend(event);
            return;
    
        }
    }
    
    protected String generateTimestamp(Calendar calendar) {
    
        int year = calendar.get(Calendar.YEAR);
        int month = calendar.get(Calendar.MONTH) + 1;
        int day = calendar.get(Calendar.DAY_OF_MONTH);
        int hour = calendar.get(Calendar.HOUR_OF_DAY);
        int minutes = calendar.get(Calendar.MINUTE);
        int seconds = calendar.get(Calendar.SECOND);
    
        StringBuffer buffer = new StringBuffer();
    
        if (year < 1000) {
            buffer.append('0');
            if (year < 100) {
                buffer.append('0');
                if (year < 10) {
                    buffer.append('0');
                }
            }
        }
        buffer.append(Integer.toString(year));
        buffer.append('-');
    
        if (month < 10) {
            buffer.append('0');
        }
        buffer.append(Integer.toString(month));
        buffer.append('-');
    
        if (day < 10) {
            buffer.append('0');
        }
        buffer.append(Integer.toString(day));
        buffer.append('_');
    
        if (hour < 10) {
            buffer.append('0');
        }
        buffer.append(Integer.toString(hour));
    
        if (minutes < 10) {
            buffer.append('0');
        }
        buffer.append(Integer.toString(minutes));
    
        if (seconds < 10) {
            buffer.append('0');
        }
        buffer.append(Integer.toString(seconds));
    
        return buffer.toString();
    }
    
    protected void nextCalendar(Calendar calendar) {
        int i = calendar.get(Calendar.YEAR);
        int j = calendar.get(Calendar.MONTH);
    
        if (hourly) { 
            int k = calendar.get(Calendar.DAY_OF_MONTH);
            int l = calendar.get(Calendar.HOUR_OF_DAY) + 1;
            calendar.clear();
            calendar.set(i, j, k, l, 0);
        } else {
            int k = calendar.get(Calendar.DAY_OF_MONTH) + 1;
            calendar.clear();
            calendar.set(i, j, k);
        }
    }
    
    public String getDirectory() {
        return directory;
    }
    
    public void setDirectory(String directory) {
        if (directory == null || directory.length() == 0) {
            this.directory = "."; // Set to here
        } else {
            this.directory = directory;
        }
    }
    
    public String getPrefix() {
        return prefix;
    }
    
    public void setPrefix(String prefix) {
        if (prefix == null) {
            this.prefix = DEFAULT_PREFIX; // Set to default
        } else {
            this.prefix = prefix;
        }
    }
    
    public String getSuffix() {
        return suffix;
    }
    
    public void setSuffix(String suffix) {
        if (suffix == null) {
            this.suffix = ""; // Set to empty, not default
        } else {
            this.suffix = suffix;
        }
    }
    
    public void setHourly(boolean hourly) {
        this.hourly = hourly;
    }
    
    public boolean isHourly() {
        return this.hourly;
    }
    }
    

    这是我的 appender XML sn-p:

    <appender name="PRIMARY_APPENDER" class="com.stackoverflow.log4j.DistinctDailyFileAppender">
      <param name="Threshold" value="DEBUG"/>
      <param name="Directory" value="X:\\apps\\logs\\cheese\\"/>
      <param name="Append" value="true"/>
      <param name="Hourly" value="true"/>
      <param name="Prefix" value="appname_log."/>
      <param name="Suffix" value=".txt"/>
    
      <layout class="org.apache.log4j.PatternLayout">
        <param name="ConversionPattern" value="%d{HH:mm:ss,SSS} %-5p [%.3t] %-14.14c{1} %m%n"/>
      </layout>
    </appender>
    

    【讨论】:

      【解决方案3】:

      我创建了这个附加程序。它是 DailyRollingFileAppender 的副本,只是进行了一些更改。首先,我删除类型 HALF_DAY(这里它没有任何意义)并添加一个变量 timeInterval。现在这个日志到文件中每 x 的东西取决于 datePatter。例如:

      此日志每 2 分钟一次

      log4j.appender.APP=path.to.class.CustomRollingFileAppender
      log4j.appender.APP.DatePattern=.yyyy-MM-dd-HH-mm
      log4j.appender.APP.TimeInterval=2
      

      此日志每 3 小时一次

      log4j.appender.APP=path.to.class.CustomRollingFileAppender
      log4j.appender.APP.DatePattern=.yyyy-MM-dd-HH
      log4j.appender.APP.TimeInterval=3
      

      CustomRollingFileAppender :

      /*
       * Licensed to the Apache Software Foundation (ASF) under one or more
       * contributor license agreements.  See the NOTICE file distributed with
       * this work for additional information regarding copyright ownership.
       * The ASF licenses this file to You under the Apache License, Version 2.0
       * (the "License"); you may not use this file except in compliance with
       * the License.  You may obtain a copy of the License at
       * 
       *      http://www.apache.org/licenses/LICENSE-2.0
       * 
       * Unless required by applicable law or agreed to in writing, software
       * distributed under the License is distributed on an "AS IS" BASIS,
       * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
       * See the License for the specific language governing permissions and
       * limitations under the License.
       */
      
      import java.io.File;
      import java.io.IOException;
      import java.text.SimpleDateFormat;
      import java.util.Calendar;
      import java.util.Date;
      import java.util.GregorianCalendar;
      import java.util.Locale;
      import java.util.TimeZone;
      
      import org.apache.log4j.FileAppender;
      import org.apache.log4j.Layout;
      import org.apache.log4j.helpers.LogLog;
      import org.apache.log4j.spi.LoggingEvent;
      
      /**
       * DailyRollingFileAppender extends {@link FileAppender} so that the underlying file is rolled over at a user chosen
       * frequency.
       * 
       * <p>
       * The rolling schedule is specified by the <b>DatePattern</b> option. This pattern should follow the
       * {@link SimpleDateFormat} conventions. In particular, you <em>must</em> escape literal text within a pair of single
       * quotes. A formatted version of the date pattern is used as the suffix for the rolled file name.
       * 
       * <p>
       * For example, if the <b>File</b> option is set to <code>/foo/bar.log</code> and the <b>DatePattern</b> set to
       * <code>'.'yyyy-MM-dd</code>, on 2001-02-16 at midnight, the logging file <code>/foo/bar.log</code> will be copied to
       * <code>/foo/bar.log.2001-02-16</code> and logging for 2001-02-17 will continue in <code>/foo/bar.log</code> until it
       * rolls over the next day.
       * 
       * <p>
       * Is is possible to specify monthly, weekly, half-daily, daily, hourly, or minutely rollover schedules.
       * 
       * <p>
       * <table border="1" cellpadding="2">
       * <tr>
       * <th>DatePattern</th>
       * <th>Rollover schedule</th>
       * <th>Example</th>
       * 
       * <tr>
       * <td><code>'.'yyyy-MM</code>
       * <td>Rollover at the beginning of each month</td>
       * 
       * <td>At midnight of May 31st, 2002 <code>/foo/bar.log</code> will be copied to <code>/foo/bar.log.2002-05</code>.
       * Logging for the month of June will be output to <code>/foo/bar.log</code> until it is also rolled over the next
       * month.
       * 
       * <tr>
       * <td><code>'.'yyyy-ww</code>
       * 
       * <td>Rollover at the first day of each week. The first day of the week depends on the locale.</td>
       * 
       * <td>Assuming the first day of the week is Sunday, on Saturday midnight, June 9th 2002, the file <i>/foo/bar.log</i>
       * will be copied to <i>/foo/bar.log.2002-23</i>. Logging for the 24th week of 2002 will be output to
       * <code>/foo/bar.log</code> until it is rolled over the next week.
       * 
       * <tr>
       * <td><code>'.'yyyy-MM-dd</code>
       * 
       * <td>Rollover at midnight each day.</td>
       * 
       * <td>At midnight, on March 8th, 2002, <code>/foo/bar.log</code> will be copied to <code>/foo/bar.log.2002-03-08</code>
       * . Logging for the 9th day of March will be output to <code>/foo/bar.log</code> until it is rolled over the next day.
       * 
       * <tr>
       * <td><code>'.'yyyy-MM-dd-a</code>
       * 
       * <td>Rollover at midnight and midday of each day.</td>
       * 
       * <td>At noon, on March 9th, 2002, <code>/foo/bar.log</code> will be copied to <code>/foo/bar.log.2002-03-09-AM</code>.
       * Logging for the afternoon of the 9th will be output to <code>/foo/bar.log</code> until it is rolled over at midnight.
       * 
       * <tr>
       * <td><code>'.'yyyy-MM-dd-HH</code>
       * 
       * <td>Rollover at the top of every hour.</td>
       * 
       * <td>At approximately 11:00.000 o'clock on March 9th, 2002, <code>/foo/bar.log</code> will be copied to
       * <code>/foo/bar.log.2002-03-09-10</code>. Logging for the 11th hour of the 9th of March will be output to
       * <code>/foo/bar.log</code> until it is rolled over at the beginning of the next hour.
       * 
       * 
       * <tr>
       * <td><code>'.'yyyy-MM-dd-HH-mm</code>
       * 
       * <td>Rollover at the beginning of every minute.</td>
       * 
       * <td>At approximately 11:23,000, on March 9th, 2001, <code>/foo/bar.log</code> will be copied to
       * <code>/foo/bar.log.2001-03-09-10-22</code>. Logging for the minute of 11:23 (9th of March) will be output to
       * <code>/foo/bar.log</code> until it is rolled over the next minute.
       * 
       * </table>
       * 
       * <p>
       * Do not use the colon ":" character in anywhere in the <b>DatePattern</b> option. The text before the colon is
       * interpeted as the protocol specificaion of a URL which is probably not what you want.
       * 
       * @author Eirik Lygre
       * @author Ceki G&uuml;lc&uuml;
       */
      public class CustomRollingFileAppender extends FileAppender {
      
          // The code assumes that the following constants are in a increasing
          // sequence.
          static final int TOP_OF_TROUBLE = -1;
          static final int TOP_OF_MINUTE = 0;
          static final int TOP_OF_HOUR = 1;
          static final int TOP_OF_DAY = 2;
          static final int TOP_OF_WEEK = 3;
          static final int TOP_OF_MONTH = 4;
      
          /**
           * The date pattern. By default, the pattern is set to "'.'yyyy-MM-dd" meaning daily rollover.
           */
          private String datePattern = "'.'yyyy-MM-dd";
      
          private int timeInterval = 1;
      
          /**
           * The log file will be renamed to the value of the scheduledFilename variable when the next interval is entered.
           * For example, if the rollover period is one hour, the log file will be renamed to the value of "scheduledFilename"
           * at the beginning of the next hour.
           * 
           * The precise time when a rollover occurs depends on logging activity.
           */
          private String scheduledFilename;
      
          /**
           * The next time we estimate a rollover should occur.
           */
          private long nextCheck = System.currentTimeMillis() - 1;
      
          Date now = new Date();
      
          SimpleDateFormat sdf;
      
          RollingCalendar rc = new RollingCalendar();
      
          int checkPeriod = TOP_OF_TROUBLE;
      
          // The gmtTimeZone is used only in computeCheckPeriod() method.
          static final TimeZone gmtTimeZone = TimeZone.getTimeZone("GMT");
      
          /**
           * The default constructor does nothing.
           */
          public CustomRollingFileAppender() {
          }
      
          /**
           * Instantiate a <code>DailyRollingFileAppender</code> and open the file designated by <code>filename</code>. The
           * opened filename will become the ouput destination for this appender.
           */
          public CustomRollingFileAppender(Layout layout, String filename, String datePattern) throws IOException {
              super(layout, filename, true);
              this.datePattern = datePattern;
              activateOptions();
          }
      
          /**
           * The <b>DatePattern</b> takes a string in the same format as expected by {@link SimpleDateFormat}. This options
           * determines the rollover schedule.
           */
          public void setDatePattern(String pattern) {
              datePattern = pattern;
          }
      
          /** Returns the value of the <b>DatePattern</b> option. */
          public String getDatePattern() {
              return datePattern;
          }
      
          public void activateOptions() {
              super.activateOptions();
              if (datePattern != null && fileName != null) {
                  now.setTime(System.currentTimeMillis());
                  sdf = new SimpleDateFormat(datePattern);
                  int type = computeCheckPeriod();
                  printPeriodicity(type);
                  rc.setType(type);
                  rc.setTimeInterval(timeInterval);
                  File file = new File(fileName);
                  scheduledFilename = fileName + sdf.format(new Date(file.lastModified()));
      
              } else {
                  LogLog.error("Either File or DatePattern options are not set for appender [" + name + "].");
              }
          }
      
          void printPeriodicity(int type) {
              switch (type) {
              case TOP_OF_MINUTE:
                  LogLog.debug("Appender [" + name + "] to be rolled every " + timeInterval + " minutes.");
                  break;
              case TOP_OF_HOUR:
                  LogLog.debug("Appender [" + name + "] to be rolled every " + timeInterval + " hours.");
                  break;
              case TOP_OF_DAY:
                  LogLog.debug("Appender [" + name + "] to be rolled every " + timeInterval + " days.");
                  break;
              case TOP_OF_WEEK:
                  LogLog.debug("Appender [" + name + "] to be rolled every " + timeInterval + " weeks.");
                  break;
              case TOP_OF_MONTH:
                  LogLog.debug("Appender [" + name + "] to be rolled every " + timeInterval + " months.");
                  break;
              default:
                  LogLog.warn("Unknown periodicity for appender [" + name + "].");
              }
          }
      
          // This method computes the roll over period by looping over the
          // periods, starting with the shortest, and stopping when the r0 is
          // different from from r1, where r0 is the epoch formatted according
          // the datePattern (supplied by the user) and r1 is the
          // epoch+nextMillis(i) formatted according to datePattern. All date
          // formatting is done in GMT and not local format because the test
          // logic is based on comparisons relative to 1970-01-01 00:00:00
          // GMT (the epoch).
      
          int computeCheckPeriod() {
              RollingCalendar rollingCalendar = new RollingCalendar(gmtTimeZone, Locale.ENGLISH);
              // set sate to 1970-01-01 00:00:00 GMT
              Date epoch = new Date(0);
              if (datePattern != null) {
                  for (int i = TOP_OF_MINUTE; i <= TOP_OF_MONTH; i++) {
                      SimpleDateFormat simpleDateFormat = new SimpleDateFormat(datePattern);
                      simpleDateFormat.setTimeZone(gmtTimeZone); // do all date formatting in GMT
                      String r0 = simpleDateFormat.format(epoch);
                      rollingCalendar.setType(i);
                      Date next = new Date(rollingCalendar.getNextCheckMillis(epoch));
                      String r1 = simpleDateFormat.format(next);
                      // System.out.println("Type = "+i+", r0 = "+r0+", r1 = "+r1);
                      if (r0 != null && r1 != null && !r0.equals(r1)) {
                          return i;
                      }
                  }
              }
              return TOP_OF_TROUBLE; // Deliberately head for trouble...
          }
      
          /**
           * Rollover the current file to a new file.
           */
          void rollOver() throws IOException {
      
              /* Compute filename, but only if datePattern is specified */
              if (datePattern == null) {
                  errorHandler.error("Missing DatePattern option in rollOver().");
                  return;
              }
      
              String datedFilename = fileName + sdf.format(now);
              // It is too early to roll over because we are still within the
              // bounds of the current interval. Rollover will occur once the
              // next interval is reached.
              if (scheduledFilename.equals(datedFilename)) {
                  return;
              }
      
              // close current file, and rename it to datedFilename
              this.closeFile();
      
              File target = new File(scheduledFilename);
              if (target.exists()) {
                  target.delete();
              }
      
              File file = new File(fileName);
              boolean result = file.renameTo(target);
              if (result) {
                  LogLog.debug(fileName + " -> " + scheduledFilename);
              } else {
                  LogLog.error("Failed to rename [" + fileName + "] to [" + scheduledFilename + "].");
              }
      
              try {
                  // This will also close the file. This is OK since multiple
                  // close operations are safe.
                  this.setFile(fileName, false, this.bufferedIO, this.bufferSize);
              } catch (IOException e) {
                  errorHandler.error("setFile(" + fileName + ", false) call failed.");
              }
              scheduledFilename = datedFilename;
          }
      
          /**
           * This method differentiates DailyRollingFileAppender from its super class.
           * 
           * <p>
           * Before actually logging, this method will check whether it is time to do a rollover. If it is, it will schedule
           * the next rollover time and then rollover.
           * */
          protected void subAppend(LoggingEvent event) {
              long n = System.currentTimeMillis();
              if (n >= nextCheck) {
                  now.setTime(n);
                  nextCheck = rc.getNextCheckMillis(now);
                  try {
                      rollOver();
                  } catch (IOException ioe) {
                      LogLog.error("rollOver() failed.", ioe);
                  }
              }
              super.subAppend(event);
          }
      
          public int getTimeInterval() {
              return timeInterval;
          }
      
          public void setTimeInterval(int timeInterval) {
              this.timeInterval = timeInterval;
          }
      }
      
      /**
       * RollingCalendar is a helper class to DailyRollingFileAppender. Given a periodicity type and the current time, it
       * computes the start of the next interval.
       * */
      class RollingCalendar extends GregorianCalendar {
          private static final long serialVersionUID = -3560331770601814177L;
      
          int type = CustomRollingFileAppender.TOP_OF_TROUBLE;
      
          int timeInterval = 1;
      
          RollingCalendar() {
              super();
          }
      
          public void setTimeInterval(int timeInterval) {
              this.timeInterval = timeInterval;
          }
      
          RollingCalendar(TimeZone tz, Locale locale) {
              super(tz, locale);
          }
      
          void setType(int type) {
              this.type = type;
          }
      
          public long getNextCheckMillis(Date now) {
              return getNextCheckDate(now).getTime();
          }
      
          public Date getNextCheckDate(Date now) {
              this.setTime(now);
      
              switch (type) {
              case CustomRollingFileAppender.TOP_OF_MINUTE:
                  this.set(Calendar.SECOND, 0);
                  this.set(Calendar.MILLISECOND, 0);
                  this.add(Calendar.MINUTE, timeInterval);
                  break;
              case CustomRollingFileAppender.TOP_OF_HOUR:
                  this.set(Calendar.MINUTE, 0);
                  this.set(Calendar.SECOND, 0);
                  this.set(Calendar.MILLISECOND, 0);
                  this.add(Calendar.HOUR_OF_DAY, timeInterval);
                  break;
              case CustomRollingFileAppender.TOP_OF_DAY:
                  this.set(Calendar.HOUR_OF_DAY, 0);
                  this.set(Calendar.MINUTE, 0);
                  this.set(Calendar.SECOND, 0);
                  this.set(Calendar.MILLISECOND, 0);
                  this.add(Calendar.DATE, timeInterval);
                  break;
              case CustomRollingFileAppender.TOP_OF_WEEK:
                  this.set(Calendar.DAY_OF_WEEK, getFirstDayOfWeek());
                  this.set(Calendar.HOUR_OF_DAY, 0);
                  this.set(Calendar.MINUTE, 0);
                  this.set(Calendar.SECOND, 0);
                  this.set(Calendar.MILLISECOND, 0);
                  this.add(Calendar.WEEK_OF_YEAR, timeInterval);
                  break;
              case CustomRollingFileAppender.TOP_OF_MONTH:
                  this.set(Calendar.DATE, 1);
                  this.set(Calendar.HOUR_OF_DAY, 0);
                  this.set(Calendar.MINUTE, 0);
                  this.set(Calendar.SECOND, 0);
                  this.set(Calendar.MILLISECOND, 0);
                  this.add(Calendar.MONTH, timeInterval);
                  break;
              default:
                  throw new IllegalStateException("Unknown periodicity type.");
              }
              return getTime();
          }
      }
      

      【讨论】:

      • 正是我想要的。工作正常。
      【解决方案4】:

      我知道回复晚了,但以下解决方案将帮助您和其他搜索相同问题并回到此线程的用户。

      我修改 DailyRollingFileAppender.java 以在文件滚动中包含时间间隔子句,这将允许用户设置必须完成滚动的分钟间隔

      从这里包含文件http://abheygupta.com/DailyRollingFileAppender.java

      并以这种方式配置,时间间隔可以具有 60 个因素 [1,2,3,4,5,6,10,12,15,20,30,60] 中的任何值 log4j.appender.mtlog_api11.DatePattern='.'mmHHMMddyyyy log4j.appender.mtlog_api11.TimeInterval=10

      它可以在上面指定的其他 DatePattern 中正常工作。

      【讨论】:

        【解决方案5】:

        使用 logback,您可以继承 RollingFileAppender。

        public class FifteenMinuteAppender<E> extends RollingFileAppender<E>
        {
           private static long start = System.currentTimeMillis(); // minutes
           private int rollOverTimeInMinutes = 15;
        
           @Override
           public void rollover()
           {
              long currentTime = System.currentTimeMillis();
              int maxIntervalSinceLastLoggingInMillis = rollOverTimeInMinutes * 60 * 1000;
        
              if ((currentTime - start) >= maxIntervalSinceLastLoggingInMillis)
              {
                 super.rollover();
                 start = System.currentTimeMillis();
              }
           }
        }
        

        然后使用该 appender 作为您的 appender 并使用滚动策略

        <appender class="com.your.package.FifteenMinuteAppender" name="YOUR_APPENDER">
          <file>yourfile.csv</file>
          <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- daily rollover -->
            <fileNamePattern>yourfile-%d{yyyyMMdd-HHmm}.csv</fileNamePattern>
          </rollingPolicy>
          <encoder>
            <pattern>%d{YYYYMMDD-HHmmSS-ZZ};${HOSTNAME};%thread;%msg%n</pattern>
          </encoder>
        </appender>
        

        更多详情here

        【讨论】:

        • 如果 log4j 类是 final 怎么办?
        猜你喜欢
        • 2013-05-19
        • 1970-01-01
        • 1970-01-01
        • 2016-09-28
        • 2017-03-07
        • 1970-01-01
        • 2015-06-02
        • 2015-03-20
        • 1970-01-01
        相关资源
        最近更新 更多