log4j之DailyRollingFileAppender源码 重写文件名后缀

原创 2013年12月03日 10:08:31

DailyRollingFileAppende每天(yyyy-MM-dd)生成一个日志文件,但是当天的文件没有日期后缀。试着重写了一下他的方法。

主要注意这个方法public synchronized void setFile(String fileName, boolean append, boolean bufferedIO, int bufferSize)  throws IOException

还有这个void rollOver() throws IOException

【注】有个问题没有解决,当服务器将时间调向过去,日志不会写到那天的日志文件里,而是会写到最新的日志文件里;系统时间调向将来,没有问题。

/**
 * Copyright (C) The Apache Software Foundation. All rights reserved.
 *
 * This software is published under the terms of the Apache Software
 * License version 1.1, a copy of which has been included with this
 * distribution in the LICENSE.txt file.  */



package com.kong.trinet.util;

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 com.kong.trinet.util.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ülcü */
public class DailyRollingFileAppender 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 HALF_DAY      = 2;
  static final int TOP_OF_DAY    = 3;
  static final int TOP_OF_WEEK   = 4;
  static final int TOP_OF_MONTH  = 5;


  /***
     The date pattern. By default, the pattern is set to
     "'.'yyyy-MM-dd" meaning daily rollover.
   */
  private String datePattern = "'.'yyyy-MM-dd";

  /***
     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 DailyRollingFileAppender() {
  }

  /***
    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 DailyRollingFileAppender (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);
      File file = new File(fileName);
//      String name0=sdf.format(new Date());
//      String name1=DateUtil.getSpecifiedDayBefore(simpleDateFormat.format(new Date()));
//      if(fileName.endsWith(name0)||fileName.endsWith(name1)){
    	  scheduledFilename = fileName;
//      }else{
//    	  scheduledFilename = fileName+simpleDateFormat.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 minute.");
      break;
    case TOP_OF_HOUR:
      LogLog.debug("Appender ["+name
		   +"] to be rolled on top of every hour.");
      break;
    case HALF_DAY:
      LogLog.debug("Appender ["+name
		   +"] to be rolled at midday and midnight.");
      break;
    case TOP_OF_DAY:
      LogLog.debug("Appender ["+name
		   +"] to be rolled at midnight.");
      break;
    case TOP_OF_WEEK:
      LogLog.debug("Appender ["+name
		   +"] to be rolled at start of week.");
      break;
    case TOP_OF_MONTH:
      LogLog.debug("Appender ["+name
		   +"] to be rolled at start of every month.");
      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;
    String str=sdf.format(now);
    this.scheduledFilename=scheduledFilename.substring(0, scheduledFilename.lastIndexOf("."))+str;
    // 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();
      String s=null;
    }
//注意这里!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//    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);
   }
}

/***
 *  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 {

  int type = DailyRollingFileAppender.TOP_OF_TROUBLE;

  RollingCalendar() {
    super();
  }  

  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 DailyRollingFileAppender.TOP_OF_MINUTE:
	this.set(Calendar.SECOND, 0);
	this.set(Calendar.MILLISECOND, 0);
	this.add(Calendar.MINUTE, 1);
	break;
    case DailyRollingFileAppender.TOP_OF_HOUR:
	this.set(Calendar.MINUTE, 0);
	this.set(Calendar.SECOND, 0);
	this.set(Calendar.MILLISECOND, 0);
	this.add(Calendar.HOUR_OF_DAY, 1);
	break;
    case DailyRollingFileAppender.HALF_DAY:
	this.set(Calendar.MINUTE, 0);
	this.set(Calendar.SECOND, 0);
	this.set(Calendar.MILLISECOND, 0);
	int hour = get(Calendar.HOUR_OF_DAY);
	if(hour < 12) {
	  this.set(Calendar.HOUR_OF_DAY, 12);
	} else {
	  this.set(Calendar.HOUR_OF_DAY, 0);
	  this.add(Calendar.DAY_OF_MONTH, 1);
	}
	break;
    case DailyRollingFileAppender.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, 1);
	break;
    case DailyRollingFileAppender.TOP_OF_WEEK:
	this.set(Calendar.DAY_OF_WEEK, getFirstDayOfWeek());
	this.set(Calendar.HOUR_OF_DAY, 0);
	this.set(Calendar.SECOND, 0);
	this.set(Calendar.MILLISECOND, 0);
	this.add(Calendar.WEEK_OF_YEAR, 1);
	break;
    case DailyRollingFileAppender.TOP_OF_MONTH:
	this.set(Calendar.DATE, 1);
	this.set(Calendar.HOUR_OF_DAY, 0);
	this.set(Calendar.SECOND, 0);
	this.set(Calendar.MILLISECOND, 0);
	this.add(Calendar.MONTH, 1);
	break;
    default:
	throw new IllegalStateException("Unknown periodicity type.");
    }
    return getTime();
  }
}
/**
 * Copyright (C) The Apache Software Foundation. All rights reserved.
 *
 * This software is published under the terms of the Apache Software
 * License version 1.1, a copy of which has been included with this
 * distribution in the LICENSE.txt file.  */

package com.kong.trinet.util;

import java.io.BufferedWriter;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.Writer;
import java.util.Date;

import org.apache.log4j.ConsoleAppender;
import org.apache.log4j.Layout;
import org.apache.log4j.RollingFileAppender;
import org.apache.log4j.WriterAppender;
import org.apache.log4j.helpers.LogLog;
import org.apache.log4j.helpers.QuietWriter;
import org.apache.log4j.spi.ErrorCode;

// Contibutors: Jens Uwe Pipka <jens.pipka@gmx.de>
//              Ben Sandee

/***
 *  FileAppender appends log events to a file.
 *
 *  <p>Support for <code>java.io.Writer</code> and console appending
 *  has been deprecated and then removed. See the replacement
 *  solutions: {@link WriterAppender} and {@link ConsoleAppender}.
 *
 * @author Ceki Gülcü 
 * */
public class FileAppender extends WriterAppender {

  /*** Append to or truncate the file? The default value for this
      variable is <code>true</code>, meaning that by default a
      <code>FileAppender</code> will append to an existing file and
      not truncate it.

      <p>This option is meaningful only if the FileAppender opens the
      file.
  */
  protected boolean fileAppend = true;

  /***
     The name of the log file. */
  protected String fileName = null;

  /***
     Do we do bufferedIO? */
  protected boolean bufferedIO = false;

  /***
     How big should the IO buffer be? Default is 8K. */
  protected int bufferSize = 8*1024;

  protected static java.text.SimpleDateFormat simpleDateFormat = new java.text.SimpleDateFormat("yyyy-MM-dd");

  
  /***
     The default constructor does not do anything.
  */
  public
  FileAppender() {
  }

  /***
    Instantiate a <code>FileAppender</code> and open the file
    designated by <code>filename</code>. The opened filename will
    become the output destination for this appender.

    <p>If the <code>append</code> parameter is true, the file will be
    appended to. Otherwise, the file designated by
    <code>filename</code> will be truncated before being opened.

    <p>If the <code>bufferedIO</code> parameter is <code>true</code>,
    then buffered IO will be used to write to the output file.

  */
  public
  FileAppender(Layout layout, String filename, boolean append, boolean bufferedIO,
	       int bufferSize) throws IOException {
    this.layout = layout;
    filename=filename+"."+simpleDateFormat.format(new Date());
    this.setFile(filename, append, bufferedIO, bufferSize);
  }

  /***
    Instantiate a FileAppender and open the file designated by
    <code>filename</code>. The opened filename will become the output
    destination for this appender.

    <p>If the <code>append</code> parameter is true, the file will be
    appended to. Otherwise, the file designated by
    <code>filename</code> will be truncated before being opened.
  */
  public
  FileAppender(Layout layout, String filename, boolean append)
                                                             throws IOException {
	this.layout = layout;
    this.setFile(filename, append, false, bufferSize);
  }

  /***
     Instantiate a FileAppender and open the file designated by
    <code>filename</code>. The opened filename will become the output
    destination for this appender.

    <p>The file will be appended to.  */
  public
  FileAppender(Layout layout, String filename) throws IOException {
    this(layout, filename, true);
  }

  /***
     The <b>File</b> property takes a string value which should be the
     name of the file to append to.

     <p><font color="#DD0044"><b>Note that the special values
     "System.out" or "System.err" are no longer honored.</b></font>

     <p>Note: Actual opening of the file is made when {@link
     #activateOptions} is called, not when the options are set.  */
  public void setFile(String file) {
    // Trim spaces from both ends. The users probably does not want
    // trailing spaces in file names.
    String val = file.trim();
    fileName = val;
  }

  /***
      Returns the value of the <b>Append</b> option.
   */
  public
  boolean getAppend() {
    return fileAppend;
  }


  /*** Returns the value of the <b>File</b> option. */
  public
  String getFile() {
    return fileName;
  }

  /***
     If the value of <b>File</b> is not <code>null</code>, then {@link
     #setFile} is called with the values of <b>File</b>  and
     <b>Append</b> properties.

     @since 0.8.1 */
  public
  void activateOptions() {
    if(fileName != null) {
      try {
	setFile(fileName, fileAppend, bufferedIO, bufferSize);
      }
      catch(java.io.IOException e) {
	errorHandler.error("setFile("+fileName+","+fileAppend+") call failed.",
			   e, ErrorCode.FILE_OPEN_FAILURE);
      }
    } else {
      //LogLog.error("File option not set for appender ["+name+"].");
      LogLog.warn("File option not set for appender ["+name+"].");
      LogLog.warn("Are you using FileAppender instead of ConsoleAppender?");
    }
  }

 /***
     Closes the previously opened file.
  */
  protected
  void closeFile() {
    if(this.qw != null) {
      try {
	this.qw.close();
      }
      catch(java.io.IOException e) {
	// Exceptionally, it does not make sense to delegate to an
	// ErrorHandler. Since a closed appender is basically dead.
	LogLog.error("Could not close " + qw, e);
      }
    }
  }

  /***
     Get the value of the <b>BufferedIO</b> option.

     <p>BufferedIO will significatnly increase performance on heavily
     loaded systems.

  */
  public
  boolean getBufferedIO() {
    return this.bufferedIO;
  }


  /***
     Get the size of the IO buffer.
  */
  public
  int getBufferSize() {
    return this.bufferSize;
  }



  /***
     The <b>Append</b> option takes a boolean value. It is set to
     <code>true</code> by default. If true, then <code>File</code>
     will be opened in append mode by {@link #setFile setFile} (see
     above). Otherwise, {@link #setFile setFile} will open
     <code>File</code> in truncate mode.

     <p>Note: Actual opening of the file is made when {@link
     #activateOptions} is called, not when the options are set.
   */
  public
  void setAppend(boolean flag) {
    fileAppend = flag;
  }

  /***
     The <b>BufferedIO</b> option takes a boolean value. It is set to
     <code>false</code> by default. If true, then <code>File</code>
     will be opened and the resulting {@link java.io.Writer} wrapped
     around a {@link BufferedWriter}.

     BufferedIO will significatnly increase performance on heavily
     loaded systems.

  */
  public
  void setBufferedIO(boolean bufferedIO) {
    this.bufferedIO = bufferedIO;
    if(bufferedIO) {
      immediateFlush = false;
    }
  }


  /***
     Set the size of the IO buffer.
  */
  public
  void setBufferSize(int bufferSize) {
    this.bufferSize = bufferSize;
  }

  /***
    <p>Sets and <i>opens</i> the file where the log output will
    go. The specified file must be writable.

    <p>If there was already an opened file, then the previous file
    is closed first.

    <p><b>Do not use this method directly. To configure a FileAppender
    or one of its subclasses, set its properties one by one and then
    call activateOptions.</b>

    @param fileName The path to the log file.
    @param append   If true will append to fileName. Otherwise will
        truncate fileName.  */
  public
  synchronized
  void setFile(String fileName, boolean append, boolean bufferedIO, int bufferSize)
                                                            throws IOException {
    LogLog.debug("setFile called: "+fileName+", "+append);

    // It does not make sense to have immediate flush and bufferedIO.
    if(bufferedIO) {
      setImmediateFlush(false);
    }
//注意这里。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
    reset();
    String suffix=simpleDateFormat.format(new Date());
    if(fileName.contains(".")){
	    String str=fileName.substring(0, fileName.lastIndexOf("."));
	    if(str.contains(".")){
	    	this.fileName=str.substring(0, str.lastIndexOf("."))+"."+suffix;
	    	fileName=str.substring(0, str.lastIndexOf("."))+"."+suffix;
	    }
	    else{
	    	this.fileName=str+"."+suffix;
	    	fileName=str+"."+suffix;
	    }
    }else{
    	this.fileName=fileName+"."+suffix;
    	fileName=fileName+"."+suffix;
    	
    }
    Writer fw = createWriter(new FileOutputStream(fileName, append));
    if(bufferedIO) {
      fw = new BufferedWriter(fw, bufferSize);
    }
    this.setQWForFiles(fw);
    this.fileName = fileName;
    this.fileAppend = append;
    this.bufferedIO = bufferedIO;
    this.bufferSize = bufferSize;
    writeHeader();
    LogLog.debug("setFile ended");
  }


  /***
     Sets the quiet writer being used.

     This method is overriden by {@link RollingFileAppender}.
   */
  protected
  void setQWForFiles(Writer writer) {
     this.qw = new QuietWriter(writer, errorHandler);
  }


  /***
     Close any previously opened file and call the parent's
     <code>reset</code>.  */
  protected
  void reset() {
    closeFile();
    this.fileName = null;
    super.reset();
  }
}



版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

Log4j中DailyRollingFileAppender日志文件清理策略

log4j作为使用最广的日志框架,他的简单易用高效一直深受同行们的喜爱!但他的清理策略却十分缺乏,只有在RollingFileAppender中可以通过设置maxBackupIndex属性指定要保留的...

配置log4j和logback将日志记录到syslog

1. log4j配置内容如下 log4j.appender.syslog=org.apache.log4j.net.SyslogAppender log4j.appender.syslog.S...

log4cplus使用DailyRollingFileAppender不在半夜0点切换文件的问题

由于新项目使用了log4cplus作为日志组件,但上生产后才发现配置了daily按天切换文件,实际切换文件都发生在早上8点钟,也就是每天都有0点到8点共8个小时的日志在以前一天命名的日志文件尾端,虽然...

DailyRollingFileAppender的使用

DailyRollingFileAppender是日志记录软件包Log4J中的一个Appender,它能够按一定的频度滚动日志记录文件。 如果您不熟悉Log4J,那我们建议您阅读一下 使用Log...

扩展log4j系列[一]DailyRollingFileAppender的按分钟生成日志修改为按n分钟生成日志

复制DailyRollingFileAppender里面的源码,放在新命名的类public class MinuteRollingFileAppender extends FileAppender的里...

SLFJ简介与使用教程

SLF4J SLF4J(SimpleLogging Facade for Java) 是一个通用的日志框架,相当于日志框架中的一套规范,有时候我们希望在开发的时候不理会具体的框架,而在程序部署的时候...

Netty高性能大容量Socket并发(二):Netty简介

Netty随着最近几年的发展,特别是跟着云计算、大数据的流行,很多开源分布式框架都使用了Netty作为通讯框架,如:Hadoop、Storm、Spark、Facebook、Twitter、阿里巴巴都在...

扩展log4j系列[一]为DailyRollingFileAppender加上maxBackupIndex属性

在log4j的大多数appender中,都有maxBackupIndex属性,但是这个DailyRollingFileAppender没有,也就是说它会每天滚一个文件,却没有办法控制文件总个数。这绝对...
  • d8111
  • d8111
  • 2015-04-24 17:51
  • 1659

4.log4j.properties例子:DailyRollingFileAppender

package com.v512.log4j; import org.apache.log4j.Logger; public class HelloLog4J { // 构造记录器,形参是记录器...

org.apache.log4j.Logger详解

Normal 0 7.8 磅 0 2
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)