自定义日志阅读器——包括了一个load取Tomcat日志的分析器

 最近在写往公司产品里添加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         @Override
108         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         @Override
125         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 }

接下来是一个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 "));
    }
}

 

1) 如果想要分析其它格式的日志,只需要做相应的扩展LogParser就行了。

2) 如果想要只找包含某些关键字的日志,只需要扩展LogFilter就可以了。

3) 如果想要取得某个时间段的日志,只需要指定相应的startTime,endTime参数就可以了。

 

时间: 2024-07-28 13:47:41

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

用vc++或java每隔一段时间读取一个日志文件(这是一个电话语音接听日志文件,文件内容在随时的增加)后提取有效数据到数据库中

问题描述 用vc++或java每隔一段时间读取一个日志文件(这是一个电话语音接听日志文件,文件内容在随时的增加)后提取有效数据到数据库中,怎么做到从上次读取文件的位置,也就是行数,开始下次的读取.大家知道,java和vc++是通过while()循环来读取文件,我当时的做法是记录上次while()的循环次数,下次读取时先空循环上次记录的行数,然后开始真正的读取文件.看看大伙有没有更好的办法. 解决方案 解决方案二:randomaccessfile+上次读取位置解决方案三:引用1楼inhibitor

接口-我想制作一个电子阅读器用stm32f103rct6,求住制作流程,网上有一个,不是很懂求指教

问题描述 我想制作一个电子阅读器用stm32f103rct6,求住制作流程,网上有一个,不是很懂求指教 这是我从网上down的方法,有点不懂,关键就是编程还有MF RC522模块设计,求大虾指教,谢谢 1 硬件设计 1.1 硬件结构设计 RFID阅读器基于STM32单片机设计,芯片型号选择为STM32F103RBT6.该芯片为LQFP64封装, 内部有128 KB Flash和20 KB RAM,采用32位的ARM CortexTM-M3内核, 最高支持主频72 MHz,拥有2个SPI接口. 2

创建一个简单的web服务器(二):使用自定义的类加载器来替换URLClassLoader

在上一章中我们加载Servlet用的是URLClassLoader,在这一章中我们使用自定义的类加载器来替换URLClassLoader.关于类加载器的文章请参考这里:深入探讨 Java 类加载器.这篇文章写得很棒. 具体的代码如下: package com.zkn.imitate.tomcat.secondchapter.first; import com.zkn.imitate.tomcat.secondchapter.Request; import com.zkn.imitate.tomc

RSS客户端工具——网铃阅读器

RSS订阅已经成为了网络上非常普及的一种新闻聚合方式了,要订阅RSS链接,当然,你必须要有一个RSS阅读器.常用的在线RSS阅读器有Google Reader.QQ阅读器.鲜果等等,然而,在这么多的选择面前,如果你希望找一款桌面式的实时RSS阅读器,不妨试试网铃阅读器. 网铃阅读器是MSN Shell的开发者小溪开发的又一款小巧实用的免费软件,可以实现实时订阅,一旦有任何更新,你就会第一时间在桌面上收到提醒.值得一提的是,这样一个可以实时更新大量信息的软件却非常小巧,整个程序仅不到1M,运行时仅

Windows Vista系统中的日志查看器功能介绍

当我们的Windows 系统出现问题时,要分析与定位故障,最简单的办法莫过于使用事件查看器,如Windows XP中的事件查看器可以让我们分析系统日志.应用程序日志与安全性日志,以从中找出可能存在问题的线索.不过,客观地说来,之前Windows版本包括Windows XP中的事件查看器在使用中存在很多不足,很多时候所给出的信息呆板.含糊,不足以让我们准确地定位可能发生的故障,而当待找的信息淹没在大量的事件之中时,简陋的事件过滤与查询机制往往让我们很难快速找到与定位. 在Windows Vista

电子阅读器别冲动

魏武挥 本月3日,汉王科技(002362) 挂牌,股价首日涨幅近96%,似乎市场对它预期极高.早年混迹股市的我,早就知道股市是"博傻"理论最现实的版本--我20块买了某个股票,我承认我很傻,但我赌的就是有比我更傻的会25块接过盘去.故而,一个公司到底发展会如何,二级市场的股价是当不得真的. 汉王上市,总募集资金 11.3亿,主要用于五个项目,其中之一所谓"电子纸智能读写终端项目",说得通俗一点就是电子阅读器(或叫电子书,不过我更愿意用电子阅读器来指代硬件产品,电子书

电子阅读器陷阱还是馅饼?

产业环境与商业模式成致命瓶颈 电子阅读器 陷阱还是馅饼? 本报记者 许意强 近年来,国内数码产品的更新换代速度惊人.从最初的MP3.MP4甚至还出现了MP5以及多媒体移动电视等产品,产品层出不穷,概念争相斗艳,但大多是各领风骚三五年,面临被快速淘汰的命运. 今年初,一款名为"电子阅读器"的产品在北京.上海.广州等大城市陆续出现,并受到了一部分消费群体的热捧.由于该产品不同于普通的MP4和手机电子书功能,而是采用一种电子墨水屏,长时间阅读不伤眼,且电子书籍存储容量巨大,满足了一部分专业读

Nedap推出高端RFID阅读器uPASS Target,适用于工业环境

Nedap日前宣布推出一个高端的RFID阅读器uPASS Target,符合Rain RFID超高频(UHF)EPC Gen 2标准,提供远程车辆识别.uPASS Target为需要通过无源RFID标签自动识别车辆和其他移动物体应用而设计.新的读写器提供了一个长达10米(33英尺)的阅读范围,该公司报告称,这使得它适合在工业场所和物流仓库车辆和人员的远距离识别.     uPASS Target超高频阅读器 uPASS Target设计目标是以200公里每小时(125英里每小时)速度行驶,采用无

英特尔推出面向视障人群的语音电子阅读器

网易科技讯 11月10日消息,据国外媒体Pcworld网站报道,英特尔(博客)将从本周二开始面向视障人群发布一款新型http://www.aliyun.com/zixun/aggregation/34488.html">电子书阅读器.该款阅读器能对阅读材料进行拍照和扫描,然后根据该内容为视障人群提供语音朗读服务. 这款阅读器被命名为"英特尔阅读器",售价为1499美元,面向的客户为盲人.弱视或诵读困难症患者,由英特尔数字健康部门开发.该部门的访问技术业务主管本•福斯(B