自定义日志阅读器——包括了一个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 ...
随机推荐
- Linux环境下安装Tigase XMPP Server
Tigase是一种XMPP服务器,可以作为采用XMPP协议的各种IM(Instant Messeging)工具(如Pandion.Spark等)的服务器. 在Linux环境下安装Tigase的步骤如下 ...
- python 学习笔记6(函数)
函数 定义: 函数是指将一组语句的集合通过一个名字(函数名)封装起来,要想执行这个函数,只需调用其函数名即可 特性: 1.减少代码重复 2.保持代码的一致性 3.方便修改,可扩展性 函数的创建 #简单 ...
- Nginx负载均衡配置实例详解
负载均衡是我们大流量网站要做的一个东西,下面我来给大家介绍在Nginx服务器上进行负载均衡配置方法,希望对有需要的同学有所帮助哦. 负载均衡 先来简单了解一下什么是负载均衡,单从字面上的意思来理解就可 ...
- mongoDB简介
概述 MongoDB 是一款跨平台.面向文档的数据库.用它创建的数据库可以实现高性能.高可用性,并且能够轻松扩展.MongoDB 的运行方式主要基于两个概念:集合(collection)与文档(doc ...
- C# AOP框架入门
AOP面向切面编程(Aspect Oriented Programming),是通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术.Spring框架用的核心技术就是AOP,是函数式编程的一 ...
- Wrangle – 响应式的,触摸友好的多选插件
Wrangle 是一个响应式,触摸友好的选择插件,支持 jQuery 以及 Zepto.Wrangle 为多项选择提供了一个独特的方法:通过画一条贯穿项目的线条来选择项目.它给你的应用程序的一种新的方 ...
- javascript 函数初探 (六)--- 闭包初探#4
循环中的闭包: 让我们来看一下一个会循环三次的操作,她在每次迭代中都会创建一个返回当前序列号的新函数,该函数会被添加到一个数组中,并最终返回: function F(){ var arr = [], ...
- Shiro简介
1.简介 Apache Shiro是一个功能强大且易于使用的Java安全框架,进行身份验证,授权,加密和会话管理,可用于保护任何应用程序 - 从命令行应用程序,移动应用程序到大型的Web应用和企业应用 ...
- 【C语言】C语言局部变量和全局变量
目录: [局部变量] · 定义 · 作用域 · 生命周期 · 用static修饰局部变量 [全局变量] · 定义 · 作用域 · 生命周期 1.局部变量 · 定义 在函数(代码块)内部定义的变量称为局 ...
- 苹果IPSW文件提取软件
ipsw文件 提取系统文件 方法总结 由于修改运营商文件造成我的有锁4S无法使用移动卡了,在网上苦寻一番还是没有结果,最后萌生了从固件中提取文件的想法,于是便开始在网上搜集资料,最后文件终于提取成功并 ...