你的位置:首页 > Java教程

[Java教程]自定义日志阅读器——包括了一个load取Tomcat日志的分析器


 最近在写往公司产品里添加Tomcat适配器,以支持Tomcat。有一些功能需要摘取到Tomcat的部分日志。没有合适的工具,也不想去网上找了,就自己写了一个。

 简单的画了一下设计方案:

 

下面直接上代码了:

日志阅读器:

 1 package com.fjn.tools.log.reader; 2  3 import java.io.File; 4 import java.util.LinkedList; 5 import java.util.List; 6 import java.util.Scanner; 7  8 import com.fjn.tools.log.reader.parser.CatalinaSimpleFormatterParser; 9  10 public class LogReader { 11   private String logFile; 12   private List<LogFilter> logFilterChain = new LinkedList<LogFilter>(); 13   private final ContinueRead continueRead = new ContinueRead(); 14   private LogParser parser; 15   private final boolean doFilter(LogRecord record) { 16     for (LogFilter filter : logFilterChain) { 17       if (!filter.accept(record)) { 18         return false; 19       } 20     } 21     return true; 22   } 23  24   public void addFilter(LogFilter filter) { 25     if(filter!=null){ 26       logFilterChain.add(filter); 27     } 28   } 29  30   public final String readLogRecords(String startTime, String endTime) { 31     if (parser == null) { 32       return null; 33     } 34     StringBuilder buff = new StringBuilder(); 35     Scanner scanner = null; 36      37     try { 38       scanner = new Scanner(new File(logFile)); 39        40  41       NewLine newLine = null; 42       if (startTime != null) { 43         StartTimeFilter filter = new StartTimeFilter(); 44         filter.startTime = startTime; 45         addFilter(filter); 46       } 47       if (endTime != null) { 48         EndTimeFilter filter = new EndTimeFilter(); 49         filter.endTime = endTime; 50         filter.continueRead = this.continueRead; 51         addFilter(filter); 52       } 53       while (scanner.hasNextLine() && continueRead.value) { 54         LogRecord record = null; 55         if (newLine == null) { 56           newLine = new NewLine(); 57         } 58         if (!newLine.hasGetNewLine) { 59           newLine.line = scanner.nextLine(); 60           newLine.hasGetNewLine = true; 61         } 62         record = parser.getLogRecord(scanner, newLine, continueRead); 63         if (record != null) { 64           if (doFilter(record)) { 65             buff.append(record.toString()); 66           } 67         } 68       } 69     } catch (Exception ex) { 70       // Ignore it 71     } finally { 72       if (scanner != null) { 73         scanner.close(); 74       } 75     } 76     return buff.toString(); 77   } 78  79   public static interface LogParser { 80     public LogRecord getLogRecord(Scanner scanner, NewLine newLine, 81         ContinueRead continueRead); 82   } 83  84   public static interface LogFilter { 85     public boolean accept(LogRecord record); 86   } 87  88   public static abstract class LogRecord { 89     public String prefix; 90     public String message; 91     public String threadStack; 92     public String datetime; 93   } 94  95   public static class NewLine { 96     public boolean hasGetNewLine = false; 97     public String line = ""; 98   } 99 100   public static class ContinueRead {101     public boolean value = true;102   }103 104   private class StartTimeFilter implements LogFilter {105     private String startTime;106 107     @Override108     public boolean accept(LogRecord record) {109       if (startTime == null) {110         return true;111       }112 113       if (startTime.compareTo(record.datetime) <= 0) {114         return true;115       }116       return false;117     }118   }119 120   private class EndTimeFilter implements LogFilter {121     private String endTime = "";122     private ContinueRead continueRead;123 124     @Override125     public boolean accept(LogRecord record) {126       if (endTime == null || endTime.isEmpty()) {127         return true;128       }129       if (endTime.compareTo(record.datetime) < 0) {130         if (continueRead.value) {131           continueRead.value = false;132         }133         return false;134       }135       return true;136     }137   }138   139   140   public String getLogFile() {141     return logFile;142   }143 144   public void setLogFile(String logFile) {145     this.logFile = logFile;146   }147   148 149   public LogParser getParser() {150     return parser;151   }152 153   public void setParser(LogParser parser) {154     this.parser = parser;155   }156 157   public static void main(String[] args) {158     LogReader logReader=new LogReader();159     logReader.setLogFile("E:\\Program Files\\apache/tomcat/apache-tomcat-6.0.41/logs/catalina.2015-05-12.log");160     logReader.setParser(new CatalinaSimpleFormatterParser());161     System.out.println(logReader.readLogRecords("2015-10-12 01:53:10", null));162   }163 }

LogReader

接下来是一个Tomcat日志分析器:

package com.fjn.tools.log.reader.parser;import java.util.LinkedList;import java.util.List;import java.util.Scanner;import java.util.StringTokenizer;import com.fjn.tools.log.reader.LogReader.ContinueRead;import com.fjn.tools.log.reader.LogReader.LogParser;import com.fjn.tools.log.reader.LogReader.LogRecord;import com.fjn.tools.log.reader.LogReader.NewLine;public class CatalinaSimpleFormatterParser implements LogParser {  @Override  public LogRecord getLogRecord(Scanner scanner, NewLine newLine,      ContinueRead continueRead) {    String line1 = newLine.line;    if (!line1.matches(SimpleFormatterLogRecord.prefixPattern)) {      newLine.hasGetNewLine = false;      return null;    }    boolean toNextRecord = false;    String nextLine = null;    List<String> messageLines = new LinkedList<String>();    while (!toNextRecord) {      if (scanner.hasNextLine()) {        nextLine = scanner.nextLine();        if (!nextLine.matches(SimpleFormatterLogRecord.prefixPattern)) {          messageLines.add(nextLine);        } else {          toNextRecord = true;          newLine.hasGetNewLine = true;          newLine.line = nextLine;          break;        }      } else {        break;      }    }    SimpleFormatterLogRecord record = new SimpleFormatterLogRecord();    record.prefix = line1 + "\n";    StringBuilder messageBuilder = new StringBuilder();    StringBuilder threadStackBuilder = new StringBuilder();    boolean toThreadStack = false;    for (String lineN : messageLines) {      if (!toThreadStack          && lineN.matches(SimpleFormatterLogRecord.threadStackStartPattern)) {        toThreadStack = true;      }      if (toThreadStack) {        threadStackBuilder.append(lineN).append("\n");      } else {        messageBuilder.append(lineN).append("\n");      }    }    record.message = messageBuilder.toString();    record.threadStack = threadStackBuilder.toString();    StringTokenizer stk = new StringTokenizer(record.prefix);    String date = stk.nextToken();    String time = stk.nextToken();    record.datetime = dateTimeFormat(date + " " + time);        return record;  }  private class SimpleFormatterLogRecord extends LogRecord {    private static final String prefixPattern = "^(\\d{4}-\\d{1,2}-\\d{1,2} \\d{1,2}:\\d{1,2}:\\d{1,2} ).*";    private static final String threadStackStartPattern = "^((\\w+\\.)*\\w*Exception: ).*";    public String toString() {      return this.prefix + this.message + this.threadStack;    }  }    private static String dateTimeFormat(String datetime){    StringTokenizer stk = new StringTokenizer(datetime, "- :");    int i = 0;    StringBuilder dateTimeBuilder = new StringBuilder();    while (stk.hasMoreTokens()) {      i++;      String token = stk.nextToken();      if (i < 7 && token.length() < 2) {        token = "0" + token;      }      if (i < 3) {        token += "-";      } else if (i < 4) {        token += " ";      } else if (i < 6) {        token += ":";      }      dateTimeBuilder.append(token);    }    return dateTimeBuilder.toString();  }  public static void main(String[] args) {    System.out.println(dateTimeFormat("2015-5-12 1:53:10 "));  }}

CatalinaSimpleFormatterLogParser

 

1) 如果想要分析其它格式的日志,只需要做相应的扩展LogParser就行了。

2) 如果想要只找包含某些关键字的日志,只需要扩展LogFilter就可以了。

3) 如果想要取得某个时间段的日志,只需要指定相应的startTime,endTime参数就可以了。