我们需要解析几个日志文件并对找到的日志条目运行一些统计信息(例如某些消息的出现次数,出现的峰值等)。问题在于编写一个日志解析器,它将处理几种日志格式,并允许我添加一种新的日志格式而且工作量很少。
为了让事情变得简单,我只关注基本上与此类似的日志:
[11/17/11 14:07:14:030 EST] MyXmlParser E Premature end of file
因此每个日志条目将包含timestamp
,originator
(日志消息),level
和日志message
。一个重要的细节是消息可能有多行(例如堆栈跟踪)。
日志条目的另一个实例可能是:
17-11-2011 14:07:14 ERROR MyXmlParser - Premature end of file
我正在寻找一种指定日志格式的好方法,以及为其实现解析器的最合适的技术。 我虽然讲正则表达式,但我认为处理多行消息(例如堆栈跟踪)等情况会很棘手。
实际上,当我考虑多行消息的可能性时,为特定日志格式编写解析器的任务本身并不那么容易。你如何解析这些文件?
理想情况下,我可以将此类内容指定为日志格式:
[%TIMESTAMP] %ORIGIN %LEVEL %MESSAGE
或
%TIMESTAMP %LEVEL %ORIGIN - %MESSAGE
显然,我必须为每个字段分配正确的转换器才能正确处理它(例如时间戳)。
有没有人能给我一些关于如何以健壮和模块化的方式实现这一点的好主意(我使用的是Java)?
答案 0 :(得分:3)
AWStats是一个很棒的日志解析器,开源,您可以使用它生成的结果数据库执行任何操作。
答案 1 :(得分:2)
例如,您可以使用扫描仪和一些正则表达式。以下是我解析一些复杂日志所做的一小部分:
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;
}
因此,使用正则表达式和组,它可以很好地工作。
答案 2 :(得分:1)
如果您有可能(并且您应该使用良好的记录器框架),我建议您以可分析的格式复制日志。例如,使用log4j使用XMLLayout或类似的东西。 解析起来会容易得多,因为这样你就会知道日志的确切格式。
只需通过设置,您就可以非常透明地对正在运行的应用程序执行此操作。考虑使用异步appender以免干扰正在运行的应用程序。
此外,如果XMLLayout可以满足您的需求,请查看Apache chainsaw
答案 3 :(得分:1)
Log4j的LogFilePatternReceiver正是这样......
此日志条目: 17-11-2011 14:07:14错误MyXmlParser - 文件过早结束
可以使用以下logformat进行解析(假设origin与'logger'相同),时间戳利用Java的SimpleDateFormat为dd-MM-yyyy kk:mm:ss
TIMESTAMP LEVEL LOGGER - MESSAGE
时区和其他形式的级别有点诡计......有能力将字符串重新映射到级别(E到ERROR),但我不知道时区会很有效。
尝试一下,查看源代码,并在Chainsaw的最新开发者快照中使用它的支持:
答案 4 :(得分:1)
我最终没有自己编写并使用logstash。
答案 5 :(得分:0)
在工作中,我们推出了自己的日志解析器(使用Java),因此我们可以从生产日志中过滤已知的堆栈跟踪,以识别新的潜在生产问题。它使用正则表达式,并且它与我们的log4j日志格式紧密耦合。
我们还有一个python脚本,当特定错误的计数过高时,它会在实时生产事务日志和报告(到SiteScope - 我们的基础架构监视工具)上运行。
虽然两者都很有用,但它们维护起来很糟糕,我建议首先尝试使用任何开源工具解析工具,并且只在必要时尝试编写自己的解析工具。哎呀,我甚至会支付以获得这样做的工具;)
答案 6 :(得分:0)
也许你可以写一个Log4j CustomAppender?例如,如下所述:http://mytechattempts.wordpress.com/2011/05/10/log4j-custom-memory-appender/
您的自定义appender可以使用JMX查询的数据库或简单Java对象来获取统计信息。所有这些都取决于需要保留多少数据。