从 Logstash 1.3.0 开始引入了一个新的概念 -- codec(coder 与 decoder 两个单词合成的缩写)
在此之前,logstash 的工作流程是:收集纯文本日志 -> filter -> output 过滤
而 codec 实现了纯文本日志再处理的功能,整个流程变成了:
input -> decode -> filter -> encode -> output
这个过程中的 decode 和 encode 就是 codec 所做的事情
codec 的引入,使得 logstash 可以更好更方便的与其他有自定义数据格式的运维产品共存,比如 graphite、fluent、netflow、collectd,以及使用 msgpack、json、edn 等通用数据格式的其他产品等
之前我们使用的 rubydebug 就是一种 codec
json 是一种十分常用的格式化文本协议
nginx 配置输出 json 格式 accesslog
比如我们将 nginx 的 accesslog 配置改为:
logformat json '{"@timestamp":"$time_iso8601",'
'"@version":"1",'
'"host":"$server_addr",'
'"client":"$remote_addr",'
'"size":$body_bytes_sent,'
'"responsetime":$request_time,'
'"domain":"$host",'
'"url":"$uri",'
'"status":"$status"}';
access_log /var/log/nginx/access.log_json json;
那么,nginx 打出的 accesslog 将会是以 json 为格式存储的
logstash 配置
input {
file {
path => "/var/log/nginx/access.log_json""
codec => "json"
}
}
收集结果
这样收集到的结果就是:
{
"@timestamp" => "2014-03-21T18:52:25.000+08:00",
"@version" => "1",
"host" => "raochenlindeMacBook-Air.local",
"client" => "123.125.74.53",
"size" => 8096,
"responsetime" => 0.04,
"domain" => "www.domain.com",
"url" => "/path/to/file.suffix",
"status" => "200"
}
注意
需要注意的是,对于 $upstream_response_time 等变量,可能不是数字,而是 '-',这样在 logstash 验证的时候就会发生异常,有两种方法可以解决:
- 在 nginx 配置中,用引号包裹相应的变量,强制变成字符串类型
- 在收集前进行预处理,将 '-' 变成 0
针对第二种方法,可以使用:
tail -F /var/log/nginx/proxy_access.log_json \
| sed 's/upstreamtime":-/upstreamtime":0/' \
| /usr/local/logstash/bin/logstash -f /usr/local/logstash/etc/proxylog.conf
让 logstash 使用 stdin 作为输入,输入数据为上述命令的处理结果
有时,我们需要将多行数据合并成一条日志处理,这样的情况通过命令行很难处理
logstash 的 codec 提供了 multiline 插件用来处理这样的场景,他还可以处理其他类似的堆栈式信息
logstash 配置
input {
stdin {
codec => multiline {
pattern => "^\["
negate => true
what => "previous"
}
}
}
在配置中,logstash 通过匹配正则表达式 "^\[" 找到日志的起始位置,将到下一次匹配之间的内容作为日志内容输入
运行结果
当传入 log 为:
[Aug/08/08 14:54:03] hello world
[Aug/08/09 14:54:04] hello logstash
hello best practice
hello raochenlin
[Aug/08/10 14:54:05] the end
logstash 会输出:
{
"@timestamp" => "2014-08-09T13:32:03.368Z",
"message" => "[Aug/08/08 14:54:03] hello world\n",
"@version" => "1",
"host" => "raochenlindeMacBook-Air.local"
}
{
"@timestamp" => "2014-08-09T13:32:24.359Z",
"message" => "[Aug/08/09 14:54:04] hello logstash\n\n hello best practice\n\n hello raochenlin\n",
"@version" => "1",
"tags" => [
[0] "multiline"
],
"host" => "raochenlindeMacBook-Air.local"
}
message 字段中存储了对应的三行内容