如何编写通用日志解析器

问题描述:

我们需要解析几个日志文件并对找到的日志条目(如某些消息的发生次数,出现的尖峰等)执行一些统计。问题在于编写一个日志解析器,它将处理多种日志格式,并允许我添加一个新的日志格式,而且工作量很少。如何编写通用日志解析器

为了让事情现在我只是在看日志,将基本上类似于这样更容易:

[11/17/11 14:07:14:030 EST] MyXmlParser  E Premature end of file 

所以每个日志条目将包含timestamporiginator(的日志消息),level和日志message。一个重要的细节是消息可能有多行(例如堆栈跟踪)。日志项 另一个例子可能是:

17-11-2011 14:07:14 ERROR MyXmlParser - Premature end of file 

我找指定的日志格式以及最适当的技术来实现解析器的好方法。 我虽然关于正则表达式,但我认为处理诸如多线消息(例如堆栈跟踪)的情况将会非常棘手。

实际上,当我考虑多线消息的可能性时,为特定日志格式编写解析器的任务听起来并不那么容易。你如何解析这些文件?

理想我想能够指定这样的东西作为日志格式:

[%TIMESTAMP] %ORIGIN %LEVEL %MESSAGE 

%TIMESTAMP %LEVEL %ORIGIN - %MESSAGE 

很显然,我将不得不权转换器分配给每个字段它会正确处理它(例如时间戳)。

任何人都可以给我一些好的想法,如何以强大的模块化方式实现这一点(我使用Java)?

+0

http://stackoverflow.com/questions/465329/best-xml-format-for-log-events-in-terms-of-tool-support-for-data-mining-and-visu – ThomasRS

我最终没有写我自己的,并使用logstash

AWStats是一款优秀的日志解析器,开放源代码,您可以对生成的数据库进行任何操作。

+0

感谢您的有关AWStats的信息。但是,我快速浏览了它,它似乎不是一个通用的日志解析器。我错过了什么吗? 另外,即使是这样,我认为从长远来看,我仍然希望能够自己解析日志,因为我希望灵活性来实现我已经想到的一些功能。 –

+1

您可以定义几乎任何类型的日志。 LogFormat指令让你告诉它要查找和解析什么。 –

在工作中,我们推出了自己的日志解析器(使用Java),所以我们可以过滤出生产日志中已知的堆栈跟踪来识别新的潜在生产问题。它使用正则表达式,它与我们的log4j日志格式紧密结合。

当特定错误的计数过高时,我们还获得了一个运行在生产事务日志和报告(到SiteScope - 我们的基础设施监控工具)上的python脚本。

虽然两者都很有用,但它们维护起来很糟糕,我建议先尝试任何开源工具解析工具,然后仅在必要时才编写自己的工具。哎,我甚至支付这样做的工具;)

您可以使用扫描仪,例如和一些正则表达式。这里是我做过什么来分析一些复杂的日志片段:

private static final Pattern LINE_PATTERN = Pattern.compile(
    "(\\S+:)?(\\S+? \\S+?) \\S+? DEBUG \\S+? - DEMANDE_ID=(\\d+?) - listener (\\S+?) : (\\S+?)"); 

public static EventLog parse(String line) throws ParseException { 
    String demandId; 
    String listenerClass; 
    long startTime; 
    long endTime; 

    SimpleDateFormat sdf = new SimpleDateFormat(DATE_PATTERN); 
    Matcher matcher = LINE_PATTERN.matcher(line); 
    if (matcher.matches()) { 
     int offset = matcher.groupCount()-4; // 4 interesting groups, the first is optional 
     demandeId = matcher.group(2+offset); 
     listenerClass = matcher.group(3+offset); 
     long time = sdf.parse(matcher.group(1+offset)).getTime(); 
     if ("starting".equals(matcher.group(4+offset))) { 
      startTime = time; 
      endTime = -1; 
     } else { 
      startTime = -1; 
      endTime = time; 
     } 
     return new EventLog(demandeId, listenerClass, startTime, endTime); 
    } 
    return null; 
} 

所以,用正则表达式和组,它工作得很好。

也许你可以写一个Log4j CustomAppender?例如,如下所述:http://mytechattempts.wordpress.com/2011/05/10/log4j-custom-memory-appender/

您的自定义appender可以使用JMX查询的数据库或简单的Java对象来获取您的统计信息。所有这些都取决于需要保存多少数据。

如果您有可能(并且您应该有一个好的记录器框架),我会建议您以可解析的格式复制日志。例如,使用log4j使用XMLLayout或类似的东西。 解析起来会容易很多,因为那样你才会知道日志的确切格式。

您可以通过安装程序对运行的应用程序进行非常透明的操作。考虑使用异步appender,以免扰乱太多正在运行的应用程序。

此外,如果XMLLayout能满足您的需求来看看Apache chainsaw

Log4j的LogFilePatternReceiver正是这么做的......

此日志条目: 17-11-2011 14点07分14秒ERROR MyXmlParser - 文件

可以使用以下记录格式进行解析的过早结束(假定原点相同“记录器”),与时间戳利用DD-MM-YYYY KK的Java的的SimpleDateFormat:MM:SS

TIMESTAMP LEVEL LOGGER - MESSAGE

时区和另一种形式的级别有一点技巧......有能力将字符串重新映射到级别(E到ERROR),但我不知道时区会相当的工作。

尝试一下,检查出的来源,并在电锯的最新开发快照的支持发挥了它:

http://people.apache.org/~sdeboy