如何编写通用日志分析器

我们需要解析几个日志文件并对找到的日志条目运行一些统计信息(例如某些消息的出现次数,出现的峰值等)。 问题是编写一个日志解析器,它将处理几种日志格式,并允许我添加一个新的日志格式,只需要很少的工作。

为了让事情变得简单,我只关注基本上与此类似的日志:

[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 

我正在寻找一种指定日志格式的好方法,以及为它实现解析器的最适当的技术。 我虽然讲正则表达式,但我认为处理诸如多行消息(例如stacktrace)之类的情况会很棘手。

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

理想情况下,我可以将此类内容指定为日志格式:

 [%TIMESTAMP] %ORIGIN %LEVEL %MESSAGE 

要么

 %TIMESTAMP %LEVEL %ORIGIN - %MESSAGE 

显然,我必须为每个字段分配正确的转换器才能正确处理它(例如时间戳)。

谁能给我一些关于如何以健壮和模块化的方式实现它的好主意(我使用的是Java)?

AWStats是一个很棒的日志解析器,开源,您可以使用它生成的结果数据库执行任何操作。

例如,您可以使用扫描仪和一些正则表达式。 这是我解析一些复杂日志所做的一小部分:

 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使用XMLLayout或类似的东西。 解析会更容易,因为这样你就会知道日志的确切格式。

您可以通过安装程序对运行的应用程序完全透明地执行此操作。 考虑使用异步appender以免干扰正在运行的应用程序。

此外,如果XMLLayout可以满足您的需求,请查看Apache电锯

Log4j的LogFilePatternReceiver正是这样做的……

此日志条目:17-11-2011 14:07:14错误MyXmlParser – 文件过早结束

可以使用以下logformat进行解析(假设origin与’logger’相同),时间戳利用Java的SimpleDateFormat为dd-MM-yyyy kk:mm:ss

TIMESTAMP LEVEL LOGGER – 消息

时区和另一种forms的级别有点诡计……有能力将字符串重新映射到级别(E到ERROR),但我不知道时区会完全奏效。

尝试一下,查看源代码,并在Chainsaw的最新开发者快照中使用它的支持:

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

我最后没有编写自己的并使用logstash 。

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

我们还有一个python脚本,当特定错误的计数过高时,它会在实时生产事务日志和报告(到SiteScope – 我们的基础结构监视工具)上运行。

虽然两者都很有用,但它们维护起来很糟糕,我建议首先尝试使用任何开源工具解析工具,并在必要时尝试编写自己的解析工具。 哎呀,我甚至会为这样做的工具买单 ;)

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

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