程序源代码Log4J 日志分割

Posted 程序源代码

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了程序源代码Log4J 日志分割相关的知识,希望对你有一定的参考价值。

 关键字:通过log4j实现日志文件按照日期和文件大小进行自动分割保存,实现日志备份和日志文件合理管理。



今天给大家讲一讲log4j


其实大家对log4j并不陌生,它在好多项目中都会用到这个框架,它的主要使用是一个比较优秀的日志管理框架,很方便集成到实际项目中使用。Log4j是Apache下的一款开源的日志框架,能够满足我们在项目中对于日志记录的需求。Log4j提供了简单的API调用,强大的日志格式定义以及灵活的扩展性。我们可以自己定义Appender来满足我们对于日志输出的需求。


最近就有个项目需要整合log4j框架,但实际应用中分现因为系统出现问题,需要将日志按照日期和大小进行分割保存。


01

自定义工具类


class:log4j日志支持按照日期和大小进行切割

package

import java.io.File;
import java.io.IOException;
import java.io.Writer;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;
import org.apache.log4j.FileAppender;
import org.apache.log4j.Layout;
import org.apache.log4j.helpers.CountingQuietWriter;
import org.apache.log4j.helpers.LogLog;
import org.apache.log4j.helpers.OptionConverter;
import org.apache.log4j.spi.LoggingEvent;

/**
* class:log4j日志支持按照日期和大小进行切割
* @date 2020-04-20
*/
public class Log4JDateAndSizeSplit extends FileAppender {

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;
protected long maxFileSize = 10 * 1024 * 1024;
protected int maxBackupIndex = 1;
private String datePattern = "'.'yyyy-MM-dd";
private String scheduledFilename;
private long nextCheck = System.currentTimeMillis() - 1;
Date now = new Date();
SimpleDateFormat sdf;
RollingCalendar rc = new RollingCalendar();
int checkPeriod = TOP_OF_TROUBLE;
static final TimeZone gmtTimeZone = TimeZone.getTimeZone("GMT");
public Log4JDateAndSizeSplit() {
}
public Log4JDateAndSizeSplit(Layout layout, String filename,String datePattern) throws IOException {
super(layout, filename, true);
this.datePattern = datePattern;
activateOptions();
}
public long getMaximumFileSize() {
return maxFileSize;
}
public void setMaximumFileSize(long maxFileSize) {
this.maxFileSize = maxFileSize;
}
public void setMaxFileSize(String value) {
maxFileSize = OptionConverter.toFileSize(value, maxFileSize + 1);
}
public int getMaxBackupIndex() {
return maxBackupIndex;
}
public void setMaxBackupIndex(int maxBackups) {
this.maxBackupIndex = maxBackups;
}
public void setDatePattern(String pattern) {
datePattern = pattern;
}
public String getDatePattern() {
return datePattern;
}

@Override
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);
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 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 + "].");
}
}

int computeCheckPeriod() {
RollingCalendar rollingCalendar = new RollingCalendar(gmtTimeZone,Locale.ENGLISH);
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);
String r0 = simpleDateFormat.format(epoch);
rollingCalendar.setType(i);
Date next = new Date(rollingCalendar.getNextCheckMillis(epoch));
String r1 = simpleDateFormat.format(next);
if (r0 != null && r1 != null && !r0.equals(r1)) {
return i;
}
}
}
return TOP_OF_TROUBLE; 
}


public void sizeRollOver() {
File target;
File file;
LogLog.debug("rolling over count="+ ((CountingQuietWriter) qw).getCount());
LogLog.debug("maxBackupIndex=" + maxBackupIndex);
String datedFilename = fileName + sdf.format(now);
if (maxBackupIndex > 0) {
file = new File(datedFilename + '.' + maxBackupIndex);
if (file.exists())
file.delete();
for (int i = maxBackupIndex - 1; i >= 1; i--) {
file = new File(datedFilename + "." + i);
if (file.exists()) {
target = new File(datedFilename + '.' + (i + 1));
LogLog.debug("Renaming file " + file + " to " + target);
file.renameTo(target);
}
}
target = new File(datedFilename + "." + 1);
this.closeFile(); 
file = new File(fileName);
LogLog.debug("Renaming file " + file + " to " + target);
file.renameTo(target);
} else if (maxBackupIndex < 0) { 
for (int i = 1; i < Integer.MAX_VALUE; i++) {
target = new File(datedFilename + "." + i);
if (!target.exists()) {
this.closeFile();
file = new File(fileName);
file.renameTo(target);
LogLog.debug("Renaming file " + file + " to " + target);
break;
}
}
}
try {
this.setFile(fileName, false, bufferedIO, bufferSize);
} catch (IOException e) {
LogLog.error("setFile(" + fileName + ", false) call failed.", e);
}
scheduledFilename = datedFilename;
}
@Override
public synchronized void setFile(String fileName, boolean append,
boolean bufferedIO, int bufferSize) throws IOException {
super.setFile(fileName, append, this.bufferedIO, this.bufferSize);
if (append) {
File f = new File(fileName);
((CountingQuietWriter) qw).setCount(f.length());
}
}
@Override
protected void setQWForFiles(Writer writer) {
this.qw = new CountingQuietWriter(writer, errorHandler);
}
void timeRollOver() throws IOException {
if (datePattern == null) {
errorHandler.error("Missing DatePattern option in rollOver().");
return;
}
String datedFilename = fileName + sdf.format(now);
if (scheduledFilename.equals(datedFilename)) {
return;
}
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 {
super.setFile(fileName, false, this.bufferedIO, this.bufferSize);
} catch (IOException e) {
errorHandler.error("setFile(" + fileName + ", false) call failed.");
}
scheduledFilename = datedFilename;
}

@Override
protected void subAppend(LoggingEvent event) {
long n = System.currentTimeMillis();
if (n >= nextCheck) {
now.setTime(n);
nextCheck = rc.getNextCheckMillis(now);
try {
timeRollOver();
} catch (IOException ioe) {
LogLog.error("rollOver() failed.", ioe);
}
} else if ((fileName != null)
&& ((CountingQuietWriter) qw).getCount() >= maxFileSize) {
sizeRollOver();
}
super.subAppend(event);
}
}


02

package com.jh.jcs.log4jT;

import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Locale;
import java.util.TimeZone;


class RollingCalendar extends GregorianCalendar
{
   private static final long serialVersionUID = -3560331770601814177L;
   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;
   int type = 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 TOP_OF_MINUTE:
           this.set(Calendar.SECOND, 0);
           this.set(Calendar.MILLISECOND, 0);
           this.add(Calendar.MINUTE, 1);
           break;
       case 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 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 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 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, 1);
           break;
       case 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, 1);
           break;
       default:
           throw new IllegalStateException("Unknown periodicity type.");
      }
       return getTime();
  }
}

02

log4j配置文件

log4j.appender.RollingFile.MaxFileSize 每个文件大小 log4j.appender.RollingFile.File 文件保存目录log4j.appender.RollingFile=com.jh.jcs.log4jT.Log4JDateAndSizeSplit

#TEST
log4j.appender.RollingFile=com.jh.jcs.log4jT.Log4JDateAndSizeSplit
log4j.appender.RollingFile.File=d:/app/jc6.log
log4j.appender.RollingFile.DatePattern='_'yyyy-MM-dd'.log'
log4j.appender.RollingFile.layout=org.apache.log4j.PatternLayout
log4j.appender.RollingFile.layout.ConversionPattern= %d{yyyy-MM-dd HH:mm:ss} [%5p] - %c -%F(%L) -%m%n
log4j.appender.RollingFile.MaxFileSize=102400KB
log4j.appender.RollingFile.MaxBackupIndex=-1
log4j.appender.RollingFile.Append=true
log4j.appender.RollingFile.Threshold=INFO
log4j.appender.RollingFile.ImmediateFlush=true


03


源码获取方法


为了方便大家下载和获取源码,已将源码上传到百度云盘或者码云直接下载即可 。







微信ID:  andyquanhua     QQ: 315997972 

微信二维码, 扫一扫吧!




投稿邮箱】315997972@qq.com
【写作说明】以上内容分享给喜欢编程,有梦想的程序员,希望能帮助到你们。以上文章属于此公众号原创所有,如需转载请注明出处。
【免责申明】本公众平台不是广告商,也没有为其他三方网站或者个人做广告宣传。此分享的源代码和文章是小编在项目中、学习中整理的一些认为不错的项目。用户产生的一些自愿下载或者付费行为,与平台没有直接关系。

目前已有10000000+   优秀的程序员加入我们
【程序源代码】Log4J 日志分割       【程序源代码】Log4J 日志分割       【程序源代码】Log4J 日志分割       【程序源代码】Log4J 日志分割       【程序源代码】Log4J 日志分割       【程序源代码】Log4J 日志分割       【程序源代码】Log4J 日志分割
【程序源代码】Log4J 日志分割       【程序源代码】Log4J 日志分割       【程序源代码】Log4J 日志分割       【程序源代码】Log4J 日志分割       【程序源代码】Log4J 日志分割             

以上是关于程序源代码Log4J 日志分割的主要内容,如果未能解决你的问题,请参考以下文章

Java 标准日志工具 Log4j 的使用(附源代码)

Tomcat catalina.out日志使用log4j按天分割

使用Log4J进行日志操作

java中的日志组件-log4j

Java 使用Log4J进行日志操作

log4j.xml日志输出(如何按小时输出日志文件)