自定义日志阅读器——包括了一个load取Tomcat日志的分析器
最近在写往公司产品里添加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日志的分析器的更多相关文章
- 使用chrome控制台作为日志查看器
很多时候,我们需要查看日志的实时输出,这个时候往往只能选择控制台.我这里的日志框架是serilog,它有一个好处是控制台输出时可以高亮的形式显示其参数结构信息,如下图所示 但也存在许多不方便的地方: ...
- Python日志产生器
Python日志产生器 写在前面 有的时候,可能就是我们做实时数据收集的时候,会有一个头疼的问题就是,你会发现,你可能一下子,没有日志的数据源.所以,我们可以简单使用python脚本来实现产生实时的数 ...
- 10.AutoMapper 之自定义值解析器(Custom Value Resolvers)
https://www.jianshu.com/p/3e7cf1d1f17d 自定义值解析器(Custom Value Resolvers) 虽然AutoMapper涵盖了相当多的目标成员映射方案,但 ...
- Foxit Reader(福昕PDF阅读器) v4.3.1.218 绿色专业版
软件名称:Foxit Reader(福昕PDF阅读器) v4.3.1.218 绿色专业版 软件语言: 简体中文 授权方式: 免费软件 运行环境: Win 32位/64位 软件大小: 4.40MB 图片 ...
- android rss阅读器开发一点小技巧
这几天一直在学习开发Rss阅读器,遇到一个很坑的问题,InputSource这里总是出错.弄了好久,终于让我找到一个解决方法----看代码: new Thread(){ @Override publi ...
- rsyslog日志收集器
rsyslog详解(思维导图) 1. 日志收集概述 1.1 日志记录 时间 事件 1.2 日志收集器 syslog rsyslog elk stack 1.3 日志文件 文件记录的日志格式 其他日志文 ...
- Tomcat日志文件的输出在Linux和Windows下的差异
前言 最近老大发现Tomcat的日志文件catalina.out里存在着大量的和公司项目相关的log信息,因为一般都是会使用日志框架并另外将log信息输出到另外的文件里的,catalina.out文件 ...
- 4:ELK分析tomcat日志
五.ELK分析tomcat日志 1.配置FIlebeat搜集tomcat日志 2.配置Logstash从filebeat输入tomcat日志 3.查看索引 4.创建索引
- 提示29. 怎样避免延迟加载或Load()阅读器问题
提示29. 怎样避免延迟加载或Load()阅读器问题 如果你有如下这样的代码: 1 var results = from c in ctx.Customers 2 where c.SalesPerso ...
随机推荐
- MEF入门之不求甚解,但力求简单能讲明白(五)
我们已经成功的达到了目标,大量减少了if else. 不过在园子里面的文章大多,用的是Import.ImportMany.So,修改主函数. using IPart; using System; us ...
- 调优Java virtual machine常见问题汇总整理
数据类型 Java虚拟机中,数据类型可以分为两类:基本类型和引用类型.基本类型的变量保存原始值,即:他代表的值就是数值本身:而引用类型的变量保存引用值.“引用值”代表了某个对象的引用,而不是对象本身, ...
- Android中的checkbox和RadioButton的区别
1.单个RadioButton在选中后,通过点击无法变为未选中 单个CheckBox在选中后,通过点击可以变为未选中 2.一组RadioButton,只能同时选中一个 一组Che ...
- 探秘Java中的String、StringBuilder以及StringBuffer
探秘Java中String.StringBuilder以及StringBuffer 相信String这个类是Java中使用得最频繁的类之一,并且又是各大公司面试喜欢问 到的地方,今天就来和大家一起学习 ...
- Visual Studio Code 使用 Typings 实现智能提示功能
前言 我们知道在IDE中代码的智能提示几乎都是标配,虽然一些文本编辑器也有一些简单的提示,但这是通过代码片段提供的.功能上远不能和IDE相比.不过最近兴起的文本编辑器的新锐 Visual Studio ...
- Javascript到PHP加密通讯的简单实现
其实内容主要来源于上一篇博文,只是重新组织了语言,并做了原理性的阐述,更容易理解:P ----------------------------------------- 华丽的分割线 -------- ...
- Arcgis Engine 切割图斑(ITool)
public override void OnMouseDown(int Button, int Shift, int X, int Y) { // TODO: Add Cut.OnMouseDown ...
- Hibernate3注解[转]
Hibernate3注解 收藏 1.@Entity(name="EntityName") 必须,name为可选,对应数据库中一的个表 2.@Table(name="&qu ...
- Android Animation学习(四) ApiDemos解析:多属性动画
Android Animation学习(四) ApiDemos解析:多属性动画 如果想同时改变多个属性,根据前面所学的,比较显而易见的一种思路是构造多个对象Animator , ( Animator可 ...
- Android线程优先级设置方法技巧
对于Android平台上的线程优先级设置来说可以处理很多并发线程的阻塞问题, 比如很多无关紧要的线程会占用大量的CPU时间,虽然通过了MultiThread来解决慢速I/O但是合理分配优先级对于并发编 ...