深入Log4J源码之Appender
Appender负责定义日志输出的目的地,它可以是控制台(ConsoleAppender)、文件(FileAppender)、JMS服务器(JmsLogAppender)、以Email的形式发送出去(SMTPAppender)等。Appender是一个命名的实体,另外它还包含了对Layout、ErrorHandler、Filter等引用:
1 public inte易做图ce Appender {
2 void addFilter(Filter newFilter);
3 public Filter getFilter();
4 public void clearFilters();
5 public void close();
6 public void doAppend(LoggingEvent event);
7 public String getName();
8 public void setErrorHandler(ErrorHandler errorHandler);
9 public ErrorHandler getErrorHandler();
10 public void setLayout(Layout layout);
11 public Layout getLayout();
12 public void setName(String name);
13 public boolean requiresLayout();
14 }
简单的,在配置文件中,Appender会注册到Logger中,Logger在写日志时,通过继承机制遍历所有注册到它本身和其父节点的Appender(在additivity为true的情况下),调用doAppend()方法,实现日志的写入。在doAppend方法中,若当前Appender注册了Filter,则doAppend还会判断当前日志时候通过了Filter的过滤,通过了Filter的过滤后,如果当前Appender继承自SkeletonAppender,还会检查当前日志级别时候要比当前Appender本身的日志级别阀门要打,所有这些都通过后,才会将LoggingEvent实例传递给Layout实例以格式化成一行日志信息,最后写入相应的目的地,在这些操作中,任何出现的错误都由ErrorHandler字段来处理。
Log4J中的Appender类图结构:
在Log4J Core一小节中已经简单的介绍过了AppenderSkeleton、WriterAppender、ConsoleAppender以及 Filter,因小节将直接介绍具体的几个常用的Appender。
FileAppender类
FileAppender继承自WriterAppender,它将日志写入文件。主要的日志写入逻辑已经在WriterAppender中处理,FileAppender主要处理的逻辑主要在于将设置日志输出文件名,并通过设置的文件构建WriterAppender中的QuiteWriter字段实例。如果Log文件的目录没有创建,在setFile()方法中会先创建目录,再设置日志文件。另外,所有FileAppender字段在调用activateOptions()方法中生效。
1 protected boolean fileAppend = true;
2 protected String fileName = null;
3 protected boolean bufferedIO = false;
4 protected int bufferSize = 8 * 1024;
5
6 public void activateOptions() {
7 if (fileName != null) {
8 try {
9 setFile(fileName, fileAppend, bufferedIO, bufferSize);
10 } catch (java.io.IOException e) {
11 errorHandler.error("setFile(" + fileName + "," + fileAppend
12 + ") call failed.", e, ErrorCode.FILE_OPEN_FAILURE);
13 }
14 } else {
15 LogLog.warn("File option not set for appender [" + name + "].");
16 LogLog.warn("Are you using FileAppender instead of ConsoleAppender?");
17 }
18 }
19
20 public synchronized void setFile(String fileName, boolean append,
21 boolean bufferedIO, int bufferSize) throws IOException {
22 LogLog.debug("setFile called: " + fileName + ", " + append);
23 if (bufferedIO) {
24 setImmediateFlush(false);
25 }
26 reset();
27 FileOutputStream ostream = null;
28 try {
29 ostream = new FileOutputStream(fileName, append);
30 } catch (FileNotFoundException ex) {
31 String parentName = new File(fileName).getParent();
32 if (parentName != null) {
33 File parentDir = new File(parentName);
34 if (!parentDir.exists() && parentDir.mkdirs()) {
35 ostream = new FileOutputStream(fileName, append);
36 } else {
37 throw ex;
38 }
39 } else {
40 throw ex;
41 }
42 }
43 Writer fw = createWriter(ostream);
44 if (bufferedIO) {
45 fw = new BufferedWriter(fw, bufferSize);
46 }
47 this.setQWForFiles(fw);
48 this.fileName = fileName;
49 this.fileAppend = append;
50 this.bufferedIO = bufferedIO;
51 this.bufferSize = bufferSize;
52 writeHeader();
53 LogLog.debug("setFile ended");
54 }
DailyRollingFileAppender类
DailyRollingFileAppender继承自FileAppender,不过这个名字感觉有点不靠谱,事实上,DailyRollingFileAppender会在每隔一段时间可以生成一个新的日志文件,不过这个时间间隔是可以设置的,不仅仅只是每隔一天。时间间隔通过setDatePattern()方法设置,datePattern必须遵循SimpleDateFormat中的格式。支持的时间间隔有:
1.
补充:软件开发 , Java ,