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

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

下面直接上代码了:

日志阅读器:

 package com.fjn.tools.log.reader;

 import java.io.File;
import java.util.LinkedList;
import java.util.List;
import java.util.Scanner; import com.fjn.tools.log.reader.parser.CatalinaSimpleFormatterParser; public class LogReader {
private String logFile;
private List<LogFilter> logFilterChain = new LinkedList<LogFilter>();
private final ContinueRead continueRead = new ContinueRead();
private LogParser parser;
private final boolean doFilter(LogRecord record) {
for (LogFilter filter : logFilterChain) {
if (!filter.accept(record)) {
return false;
}
}
return true;
} public void addFilter(LogFilter filter) {
if(filter!=null){
logFilterChain.add(filter);
}
} public final String readLogRecords(String startTime, String endTime) {
if (parser == null) {
return null;
}
StringBuilder buff = new StringBuilder();
Scanner scanner = null; try {
scanner = new Scanner(new File(logFile)); NewLine newLine = null;
if (startTime != null) {
StartTimeFilter filter = new StartTimeFilter();
filter.startTime = startTime;
addFilter(filter);
}
if (endTime != null) {
EndTimeFilter filter = new EndTimeFilter();
filter.endTime = endTime;
filter.continueRead = this.continueRead;
addFilter(filter);
}
while (scanner.hasNextLine() && continueRead.value) {
LogRecord record = null;
if (newLine == null) {
newLine = new NewLine();
}
if (!newLine.hasGetNewLine) {
newLine.line = scanner.nextLine();
newLine.hasGetNewLine = true;
}
record = parser.getLogRecord(scanner, newLine, continueRead);
if (record != null) {
if (doFilter(record)) {
buff.append(record.toString());
}
}
}
} catch (Exception ex) {
// Ignore it
} finally {
if (scanner != null) {
scanner.close();
}
}
return buff.toString();
} public static interface LogParser {
public LogRecord getLogRecord(Scanner scanner, NewLine newLine,
ContinueRead continueRead);
} public static interface LogFilter {
public boolean accept(LogRecord record);
} public static abstract class LogRecord {
public String prefix;
public String message;
public String threadStack;
public String datetime;
} public static class NewLine {
public boolean hasGetNewLine = false;
public String line = "";
} public static class ContinueRead {
public boolean value = true;
} private class StartTimeFilter implements LogFilter {
private String startTime; @Override
public boolean accept(LogRecord record) {
if (startTime == null) {
return true;
} if (startTime.compareTo(record.datetime) <= 0) {
return true;
}
return false;
}
} private class EndTimeFilter implements LogFilter {
private String endTime = "";
private ContinueRead continueRead; @Override
public boolean accept(LogRecord record) {
if (endTime == null || endTime.isEmpty()) {
return true;
}
if (endTime.compareTo(record.datetime) < 0) {
if (continueRead.value) {
continueRead.value = false;
}
return false;
}
return true;
}
} public String getLogFile() {
return logFile;
} public void setLogFile(String logFile) {
this.logFile = logFile;
} public LogParser getParser() {
return parser;
} public void setParser(LogParser parser) {
this.parser = parser;
} public static void main(String[] args) {
LogReader logReader=new LogReader();
logReader.setLogFile("E:\\Program Files\\apache/tomcat/apache-tomcat-6.0.41/logs/catalina.2015-05-12.log");
logReader.setParser(new CatalinaSimpleFormatterParser());
System.out.println(logReader.readLogRecords("2015-10-12 01:53:10", null));
}
}

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参数就可以了。

自定义日志阅读器——包括了一个load取Tomcat日志的分析器的更多相关文章

  1. 使用chrome控制台作为日志查看器

    很多时候,我们需要查看日志的实时输出,这个时候往往只能选择控制台.我这里的日志框架是serilog,它有一个好处是控制台输出时可以高亮的形式显示其参数结构信息,如下图所示 但也存在许多不方便的地方: ...

  2. Python日志产生器

    Python日志产生器 写在前面 有的时候,可能就是我们做实时数据收集的时候,会有一个头疼的问题就是,你会发现,你可能一下子,没有日志的数据源.所以,我们可以简单使用python脚本来实现产生实时的数 ...

  3. 10.AutoMapper 之自定义值解析器(Custom Value Resolvers)

    https://www.jianshu.com/p/3e7cf1d1f17d 自定义值解析器(Custom Value Resolvers) 虽然AutoMapper涵盖了相当多的目标成员映射方案,但 ...

  4. Foxit Reader(福昕PDF阅读器) v4.3.1.218 绿色专业版

    软件名称:Foxit Reader(福昕PDF阅读器) v4.3.1.218 绿色专业版 软件语言: 简体中文 授权方式: 免费软件 运行环境: Win 32位/64位 软件大小: 4.40MB 图片 ...

  5. android rss阅读器开发一点小技巧

    这几天一直在学习开发Rss阅读器,遇到一个很坑的问题,InputSource这里总是出错.弄了好久,终于让我找到一个解决方法----看代码: new Thread(){ @Override publi ...

  6. rsyslog日志收集器

    rsyslog详解(思维导图) 1. 日志收集概述 1.1 日志记录 时间 事件 1.2 日志收集器 syslog rsyslog elk stack 1.3 日志文件 文件记录的日志格式 其他日志文 ...

  7. Tomcat日志文件的输出在Linux和Windows下的差异

    前言 最近老大发现Tomcat的日志文件catalina.out里存在着大量的和公司项目相关的log信息,因为一般都是会使用日志框架并另外将log信息输出到另外的文件里的,catalina.out文件 ...

  8. 4:ELK分析tomcat日志

    五.ELK分析tomcat日志 1.配置FIlebeat搜集tomcat日志 2.配置Logstash从filebeat输入tomcat日志 3.查看索引 4.创建索引

  9. 提示29. 怎样避免延迟加载或Load()阅读器问题

    提示29. 怎样避免延迟加载或Load()阅读器问题 如果你有如下这样的代码: 1 var results = from c in ctx.Customers 2 where c.SalesPerso ...

随机推荐

  1. 【C#进阶系列】19 可空值类型

    可空值类型,正如字面意义上的,是可以为NULL的值类型. 这个东西存在的意义可以解决比如数据库的的Int可以为NUll的情况,使得处理数据库数据更简单. 实际上可空值类型就是Nullable<T ...

  2. 完善ext.grid.panel中的查询功能(紧接上一篇)

    今天的代码主要是实现,Ext.grid.panel中的查询,其实我也是一名extjs新手,开始想的实现方式是另外再创建一个新的grid类来存放查询出的数据(就是有几个分类查询就创建几个grid类),这 ...

  3. HDU 1141---Brackets Sequence(区间DP)

    题目链接 http://poj.org/problem?id=1141 Description Let us define a regular brackets sequence in the fol ...

  4. linux kernel: possible SYN flooding on port 8080. Sending cookie

    possible SYN flooding on port 7244. Sending cookie

  5. AWS CloudFront CDN直接全站加速折腾记The request could not be satisfied. Bad request

    ERROR The request could not be satisfied. Bad request. Generated by cloudfront (CloudFront) Request ...

  6. ZeroClipboard 复制到剪贴板

    使用 ZeroClipboard 可以简单的将内容复制到剪贴板,通过 Adobe Flash 和 JavaScript 来实现.“Zero” 意义为这个类库没有界面,界面需要由你来建立. 版本: Ze ...

  7. C#实现类似"hello $world"的格式化字符串方法

    C#自带的string.Format可以格式化字符串,但是还是不太好用,由于格式的字符占位符都是数字,当数目较多时容易混淆.其实可以扩展string的方法,让C#的字符串具备其他的方法,下面介绍一个实 ...

  8. Captain Icon – 350+ 有趣的矢量图标免费下载

    Captain Icon 是一套一个惊人的免费图标集,包含350+有趣的矢量图标,可以缩放到任意大小而不会降低质量.图标的类别很丰富,有设计,体育,社会,天气等很多类别.提供 EPS.PSD.PNG. ...

  9. CSS基础知识之文本属性二三事

    line-height 可以给某个元素指定一个不带单位的缩放因子,这样它的后代元素就会继承这个缩放因子,再根据自身的字号大小来计算自己的行高(line-height)值, body { font-si ...

  10. iOS Assigning to 'id<XXXDelegate>' from incompatible type 'BViewController *__strong'

    在使用代理的时候, BViewController *BVC = [[BViewController alloc]init]; self.delegate = BVC; 出现这样的警告Assignin ...