最近在写往公司产品里添加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参数就可以了。
新闻热点
疑难解答