最近在寫往公司產品里添加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 "));    }}CatalinaSimpleFormatterLogParser1) 如果想要分析其它格式的日志,只需要做相應的擴展LogParser就行了。
2) 如果想要只找包含某些關鍵字的日志,只需要擴展LogFilter就可以了。
3) 如果想要取得某個時間段的日志,只需要指定相應的startTime,endTime參數就可以了。
新聞熱點
疑難解答