自定义日志阅读器——包括了一个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 }

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

时间: 2024-10-12 03:17:42

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

Python日志产生器

Python日志产生器 写在前面 有的时候,可能就是我们做实时数据收集的时候,会有一个头疼的问题就是,你会发现,你可能一下子,没有日志的数据源.所以,我们可以简单使用python脚本来实现产生实时的数据,这样就很方便了 在编写代码之前,我们得知道我们的webserver日志到底长什么样,下面我找了一段的nginx服务器上真实日志,作为样例: 223.104.25.1 - - [21/Nov/2017:20:34:16 +0800] "GET / HTTP/1.1" 200 94 &qu

福昕阅读器上线PDF文档翻译 外文轻松看

看到下面这张图片的你,作何感想!相信大多数了,浏览外文PDF的时候,多少都会有点压力!经常会出现某一段或某一句看不懂,你只能选择安装一些翻译app频繁切换,非常之麻烦,部分阅读器可以选择使用一些第三方翻译插件,但始终不是一个好办法. 在社会越来越国际化的今天,我们的工作.学习生活中总会莫名其妙出现一些不得不看.不得不译的外语文档和网页,让我们措手不及,包括日常工作中涉及中英双语的会议总结,论文当中的英语参考文献,以及追星族们的爱豆经常发的外语原博,都需要即时.快速的翻译. 福昕PDF阅读器最近7

ubuntu系统下很受欢迎的PDF阅读器--okular

环境:物理机 + Ubuntu12.04 自带的阅读器evince是一个轻量级的PDF阅读器(只占用11M空间,okular占用149M),可以满足基本功能需求.但是,有一个问题最近让我 很头疼,背景永远是高亮的白色,看芯片手册或者原理图看久了会对眼睛造成很大伤害.于是,上网找了下其它的PDF阅读器,据说有linux版的福昕阅读 器,没有去尝试,选择了比较受欢迎的okular. 一. 用命令行安装 sudo apt-get install okular 安 装好后,查看软件version为0.1

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

这几天一直在学习开发Rss阅读器,遇到一个很坑的问题,InputSource这里总是出错.弄了好久,终于让我找到一个解决方法----看代码: new Thread(){ @Override public void run() { try { URL url = new URL(RSS_URL); SAXParserFactory factory = SAXParserFactory.newInstance(); SAXParser parser = factory.newSAXParser();

ELK+kafka收集 Nginx与tomcat日志

ELK日志收集 ELK原理与介绍为什么用到ELK:一般我们需要进行日志分析场景:直接在日志文件中 grep.awk 就可以获得自己想要的信息.但在规模较大的场景中,此方法效率低下,面临问题包括日志量太大如何归档.文本搜索太慢怎么办.如何多维度查询.需要集中化的日志管理,所有服务器上的日志收集汇总.常见解决思路是建立集中式日志收集系统,将所有节点上的日志统一收集,管理,访问.一般大型系统是一个分布式部署的架构,不同的服务模块部署在不同的服务器上,问题出现时,大部分情况需要根据问题暴露的关键信息,定

Shell脚本实现 tomcat 日志定时切割

日志切割的意义: 在生产环境中,当我们使用tomcat服务时,如果用户量过多,有没有日志切割,将会产生很大的日志,一天的日志都能有好几个G大小.当我们需要查看日志记录时,非常麻烦.因此,日志切割是很有必要的! 1.编写shell脚本 vim fengelog.sh #脚本声明 #!/bin/bash . /etc/profile . ~/.bash_profile #定义日志文件目录 applog_path=/usr/local/apache-tomcat-app/logs sapplog_pa

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

前言 最近老大发现Tomcat的日志文件catalina.out里存在着大量的和公司项目相关的log信息,因为一般都是会使用日志框架并另外将log信息输出到另外的文件里的,catalina.out文件里就不需要这些多余的log信息了. 不过我在测试的时候发现,Linux和Windows下catalina.out文件的输出是有区别的. 在Linux和Windows下的差异 在Windows平台下,所有System.out, System.err以及printStackTrace()输出的log信息

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

提示29. 怎样避免延迟加载或Load()阅读器问题 如果你有如下这样的代码: 1 var results = from c in ctx.Customers 2 where c.SalesPerson.EmailAddress == “…” 3 select c; 4 foreach(var customer in results) 5 { 6 Console.WriteLine(customer.Name); 7 if (IsInteresting(customer)) 8 { 9 cust

Moon转告给你一个比Log4net更好日志框架--TracerX Logger 及其对应的日志查看器

一.介绍 TracerX logger是一个易于上手,且拥有众多高级特性的.NET日志框架. 它能够发送输出结果到多目的地(循环文件.事件日志等....).它也能生成文本和二进制文件.它拥有一个强大的查看器,该查看器支持过滤.着色.多线程.目录结构.跟踪级别.....同时它也能够折叠及扩展输出格式,可以显示绝对或者先对的时间戳.可以查看任意一行的输出调用栈.这些特性可以更加容易地帮助我们诊断程序问题. 该文主要介绍如何使用该框架,其中包含了许多代码示例.同时告诉大家,该框架用于了诸多商业软件中.