package study.log;
import java.io.File;
import java.io.IOException;
import java.io.Writer;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;
import java.util.regex.Pattern;
import org.apache.log4j.FileAppender;
import org.apache.log4j.helpers.CountingQuietWriter;
import org.apache.log4j.spi.LoggingEvent;
public class MyAppender extends FileAppender
{
/** 文件名的模式,只能由字母、数字、下划线组成,且长度不超过32 */
private static final String FILE_NAME_PATTERN = "^\\w{1,32}$";
/** 日志文件默认的前缀名称*/
private String fileNamePrefix = "Rum";
/** 日志文件默认的后缀名称*/
private String fileNameSuffix = "log";
/** 文件大小*/
private long maxFileSize;
/** 日志文件存放的路径*/
private String logPath = "D://log/run/";
/**
* 文件翻转。先关闭当前日志文件,再新建下个日志文件。
* 生成文件名,然后调用this.setFile方法翻转文件。
*/
public void rollOver()
{
fileName = createFileName();
try
{
this.setFile(fileName, false, bufferedIO, bufferSize);
}
catch (IOException e)
{
}
}
/**
* 产生文件名。
* 根据配置的文件名前缀、后缀加上路径,规则如下:
* 路径 + 文件名前缀 + "_" + 时间(yyyyMMddHHmmss)+ "." + 文件名后缀
* @return
* @author w37000
* @date 2006-2-18 16:55:02
*/
public String createFileName()
{
//如果日志目录不存在,创建目录
File dir = new File(logPath);
if (!dir.exists())
{
boolean isMkdirOk = dir.mkdirs();
if (!isMkdirOk)
{
}
}
//获得系统当前的时间
SimpleDateFormat date = new SimpleDateFormat("yyyyMMddHHmmss");
String time = null;
if ("utc".equalsIgnoreCase(System.getProperty("umlog")))
{
long offtime = TimeZone.getDefault().getOffset(new Date().getTime());
time = date.format(new Date(System.currentTimeMillis()-offtime));
}
else
{
time = date.format(new Date());
}
//String time = date.format(new Date());
//构造日志文件名称
StringBuffer sb = new StringBuffer();
sb.append(logPath).append(fileNamePrefix).append('_');
sb.append(time).append('.').append(fileNameSuffix);
return sb.toString();
}
/**
* 覆盖父类的activateOptions方法。log4j在初使化完毕(通过反射加载各配置属性)之后会
* 调用activateOptions方法,该方法将新建以fileName命名的文件,MyAppender必须覆盖
* 这个方法,先根据配置的文件名前缀、后缀等生成文件名,在调用super.activateOptions()。
* @see org.apache.log4j.FileAppender#activateOptions()
*/
public void activateOptions()
{
fileName = createFileName();
super.activateOptions();
}
/**
* 判断当前日期是否改变。
* 比较文件名中的日期是否和系统日期为同一天,若不是则新建文件。此功能可能在acc日志
* 上有用,保证一个acc日志中不包含两天的内容,OMC根据文件名称把acc日志入库到每一天的
* 表中,供portal按日期统计。
* @param fileName 文件名
* @return
* @author w37000
* @date 2006-2-18 17:25:20
*/
public boolean isDateChanged(String fileName)
{
//文件名为路径名加文件名../log/run/Rum_20040820170818.log
//1、找到文件后缀名分隔符"."
int index = fileName.lastIndexOf(".");
if(1 == 2)
{
//2、"."号前面第14~6位为日期(20040820)
String dateOfFileName = fileName.substring(index - 14, index - 4);
SimpleDateFormat date = new SimpleDateFormat("yyyyMMddHH");
String sysDate = date.format(new Date());
return !dateOfFileName.equals(sysDate);
}
else
{
//2、"."号前面第14~6位为日期(20040820)
String dateOfFileName = fileName.substring(index - 14, index - 6);
SimpleDateFormat date = new SimpleDateFormat("yyyyMMdd");
String sysDate = date.format(new Date());
return !dateOfFileName.equals(sysDate);
}
}
/**
* 覆盖父类的方法,写日志之前先判断是否已达到翻转条件,有两个翻转条件:
* 1、日期已改变
* 2、文件大小加上将要写的这条记录的大小大于maxFileSize
* 二者满足其一即关闭当前文件,写到新文件中
* @see org.apache.log4j.WriterAppender#subAppend(org.apache.log4j.spi.LoggingEvent)
*/
protected void subAppend(LoggingEvent event)
{
if (isDateChanged(fileName)
|| ((CountingQuietWriter)qw).getCount() + event.getRenderedMessage().length() >= maxFileSize)
{
this.rollOver();
}
super.subAppend(event);
}
/**
* 翻转文件。如果文件是以append的方式打开,则CountingQuietWriter要加上文件的大小
* @param fileName 文件名
* @param append 是否以增加的形式打开文件
* @param bufferedIO 是否缓存输出
* @param bufferSize 缓存大小
*/
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());
}
}
/**
* 重载父类方法,把writer设置为可以记录当前写的字节数的CountingQuietWriter。windows
* 操作系统并非实时更新文件的大小属性,因此在判断文件大小的翻转条件时不能调用File.length方法
* 来判断当前文件大小是否大于maxFileSize,在writer中用一个变量来记录当前文件中已写入的文件大小,
* 因此在设置writer时需把writer包装为可记录当前写字节数的CountingQuietWriter。
* @param writer The writer to set.
*/
protected void setQWForFiles(Writer writer)
{
this.qw = new CountingQuietWriter(writer, errorHandler);
}
/**
* @return Returns the fileNamePrefix.
*/
public String getFileNamePrefix()
{
return fileNamePrefix;
}
/**
* 只允许字母、数字、下划线,且长度不能超过32,否则采用默认值Rum
* @param fileNamePrefix The fileNamePrefix to set.
*/
public void setFileNamePrefix(String fileNamePrefix)
{
Pattern p = Pattern.compile(FILE_NAME_PATTERN);
if (p.matcher(fileNamePrefix).matches())
{
this.fileNamePrefix = fileNamePrefix;
}
}
/**
* @return Returns the fileNameSuffix.
*/
public String getFileNameSuffix()
{
return fileNameSuffix;
}
/**
* 只允许字母、数字、下划线,且长度不能超过32,否则采用默认值log
* @param fileNameSuffix The fileNameSuffix to set.
*/
public void setFileNameSuffix(String fileNameSuffix)
{
Pattern p = Pattern.compile(FILE_NAME_PATTERN);
if (p.matcher(fileNameSuffix).matches())
{
this.fileNameSuffix = fileNameSuffix;
}
}
/**
* @return Returns the maxFileSize.
*/
public long getMaxFileSize()
{
return maxFileSize;
}
/**
* 配置文件中的单位是KB,要转换为Byte
* @param maxFileSize The maxFileSize to set.
*/
public void setMaxFileSize(long maxFileSize)
{
this.maxFileSize = maxFileSize * 1024;
}
/**
* @return Returns the logPath.
*/
public String getLogPath()
{
return logPath;
}
/**
* @param logPath The logPath to set.
*/
public void setLogPath(String logPath)
{
this.logPath = logPath;
}
}
配置自己的FileFileAppender
最新推荐文章于 2023-04-03 01:40:18 发布