首页 > 技术文章 > logstash filter grok 用法

toSeek 2016-11-30 15:07 原文

在elk+filebeat都安装好,且明白了基本流程后,主要的就是写logstash的filter了,以此来解析特定格式的日志

logstash的filter是用插件实现的,grok是其中一个,用来解析自定义结构的日志,就是说可以完全自定义的去解析

grok的语法是%{pattern:field}

pattern是指模板(或者说是类型),logstash内置了很多,也可以自定义(用正则)

field是指解析后的键值中的键,当然值就是从日志解析出来的内容

(无论用什么pattern解析到elasticsearch默认都是用string存储,可以通过%{pattern:field:int}将之转换为number类型就可以进行加减计算了,只支持int和float)

比如,一个日志文件中是序号+ip,这样

1 127.0.0.1
2 127.0.0.2
3 127.0.0.3

filter就可以这样写(input省略了,肯定是从filebeat来的,output中指定index,方便测试)

filter {
    grok {
        match => { "message" => "%{NUMBER:myid} %{IP:myip}"}
    }
}
output {
    elasticsearch {
        hosts => "localhost"
        index => "mytest"
    }
}

那么日志到 elasticsearch中,就是这样:

{
  ...
  "hits" : {
    ...
    "hits" : [ {
      ...
      "_source" : {
        "message" : "1 127.0.0.1",
        ...
        "myid" : "1",
        "myip" : "127.0.0.1"
      }
    }, {
      ...
      "_source" : {
        "message" : "2 127.0.0.2",
        ...
        "myid" : "2",
        "myip" : "127.0.0.2"
      }
    }, {
      ...
      "_source" : {
        ...
        "myid" : "3",
        "myip" : "127.0.0.3"
      }
    } ]
  }
}

kibana中的效果

grok的基础用法就是这样了,一般来说内置的pattern就够用了

更多pattern可以看https://github.com/logstash-plugins/logstash-patterns-core/blob/master/patterns

像IP、NUMBER这样的基本pattern位于grok-patterns中,常用的有:

INT int类型
NUMBER 数字
DATA 数据,可以对应字符串
GREEDYDATA 数据,可以对应字符串,贪婪匹配
QUOTEDSTRING 带引号的字符串,可以简写为QS
WORD 一个词
IP ip地址,v4 或 v6
DATE 日期
TIME 时间
DATESTAMP 日期+时间
PATH 系统路径
HOSTNAME 计算机名
MAC mac地址
UUID uuid
LOGLEVEL 日志等级
EMAILADDRESS email地址

另外,还有可以直接用的模板集合,比如官方文档中的例子:

filter {
    grok {
        match => { "message" => "%{COMBINEDAPACHELOG}"}
    }
}

这个COMBINEDAPACHELOG就是一个内置的集合,这种集合还有很多,也在上面那个链接中,COMBINEDAPACHELOG就位于httpd,它的定义是:

COMBINEDAPACHELOG %{HTTPD_COMBINEDLOG}
HTTPD_COMBINEDLOG %{HTTPD_COMMONLOG} %{QS:referrer} %{QS:agent}
HTTPD_COMMONLOG %{IPORHOST:clientip} %{HTTPDUSER:ident} %{HTTPDUSER:auth} ...

(HTTPD_COMMONLOG的定义有点长,就省略了~~)

当日志的结构比较多,就需要自定义为模板集合,方便管理(自定义模板是一样的方式,感觉没必要,用内置的组合成自己的集合就行了)

mkdir -p /etc/logstash/patterns

vi /etc/logstash/patterns/test.conf

MYPATTERN %{NUMBER:myid} %{IP:myip}

filter改为

filter {
    grok {
        patterns_dir => ["/etc/logstash/patterns"]
        match => { "message" => "%{MYPATTERN}"}
    }
}

测试下,效果当然跟上面是一样的。

还有一点,pattern本质都是正则,%{}之间的空格不是结构要求,而是因为日志就是空格分隔的,如果日志都用空格和-来分隔,那就是:

MYPATTERN %{TIME:mytime} - %{DATA:mythread} - %{LOGLEVEL:mylevel} - %{DATA:myclass} - %{GREEDYDATA:myinfo}

特别说明一个情况,java中log4j的日志会出现日志级别ERROR和DEBUG后面一个空格,而其他INFO那些后面两个空格

原因应该是ERROR和DEBUG比INFO那些多一个字母,为了对齐,这种情况难在不知道以致浪费时间到处查解析正确的原因,知道了当然就简单了

%{LOGLEVEL:mylevel}  %{DATA:myclass}
改为
%{LOGLEVEL:mylevel}\s{1,2}%{DATA:myclass}

over

推荐阅读