我使用 logstash 来解析通过 TCP 通过网络发送的异常日志。由于异常日志是多行的,我使用多行过滤器来解析数据。不幸的是,最后一个正在发送的异常日志无法识别,因为 logstash 不知道它在哪里结束(由于多行模式)。甚至有可能识别它的结束位置吗?异常的结束可以是任何东西(那么如何进行正则表达式呢?)。或者是否有可能以某种方式知道,因为 TCP 流结束了,这意味着异常也已经结束?
这是我的logstash配置文件:
input {
tcp {
port => 1337
type => "exception"
}
}
filter {
if [type] == "exception" {
multiline {
pattern => "%{TIMESTAMP_ISO8601}"
negate => true
what => previous
}
grok {
match => ["message", "%{TIMESTAMP_ISO8601:timestamp} %{LOGLEVEL:log_level} \(%{INT:log_level_code}\): exception '%{DATA:exception_name}' with message '%{DATA:exception_message}' in %{PATH:path} Stack trace: %{GREEDYDATA:stack_trace}"]
remove_field => ["log_level", "log_level_code", "host"]
}
date {
match => ["timestamp", "ISO8601"]
}
}
}
output {
elasticsearch { host => localhost }
stdout {}
}
这是一个通过 TCP 发送异常的示例 PHP 脚本:
<?php
$content = "2014-11-25T20:11:55+00:00 ERR (3):
exception 'Exception' with message 'some error' in /private/var/www/index.php:88
Stack trace:
#0 {main}
2014-11-25T20:11:56+00:00 ERR (3):
exception 'Exception' with message 'some error' in /private/var/www/index.php:88
Stack trace:
#0 {main}";
$fp = stream_socket_client("tcp://127.0.0.1:1337", $errno, $errstr, 30);
if (!$fp) {
echo "$errstr ($errno)<br />\n";
} else {
fwrite($fp, $content);
fclose($fp);
}
运行此示例只会将第一个异常识别为事件日志。一旦下一个时间戳到达,第二个异常就会被识别出来,在这种情况下不会,因为数据流结束了。