Grok正则捕获详解:运维日志解析核心技巧

admin 商品展示 4

Grok 正则捕获

Grok属于Logstash最为关键的插件, 你能够于grok内事先定义好被称作定的正则表达式, 在后续(grok参数或是别的正则表达式当中)对其加以引用。

正则表达式语法

运维工程师或多或少都知晓一些正则, 正如此处这般, 你能够于grok里头撰写标准的正则。

\s+(?\d+(?:\.\d+)?)\s+

小贴士: 这种正则表达式的撰写方式, 对于 Perl 程序开发者而言, 应当是颇为熟悉的, 而 Python 程序开发者或许会更倾向于写成 (?Ppattern), 没有办法, 去适应一下。

当下, 为我们的配置文件增加首个过滤器区段配置, 此配置需添加于输入区段与输出区段之间, logstash执行区段时并不依赖于次序, 然而为了自身查看之便, 依旧按次序书写。

input {stdin{}}
filter {
    grok {
        match => {
            "message" => "\s+(?\d+(?:\.\d+)?)\s+"
        }
    }
}
output {stdout{}}

运行logstash进程, 之后输入"begin123.456end", 此时你会看到有着类似下面这样一番呈现的输出:

{
         "message" => "begin 123.456 end",
        "@version" => "1",
      "@timestamp" => "2014-08-09T11:55:38.186Z",
            "host" => "raochenlindeMacBook-Air.local",
    "request_time" => "123.456"
}

哇塞, 真的是挺漂亮着!然而, 数据的类型似乎并不是那么让人感到满意哟……request_time这个, 它原本预期的应该是那种数值类型的,而不是现在这样的字符串类型。

在 grok 里开云真人app,开云真人app地址, 有自己的魔法来实现转换字段值类型这个功能, 我们虽说已经提过稍后会学习用 LogStash::Filters::Mutate 来做这件事!

Grok 表达式语法

Grok具备将预先定义好的grok表达式写入文件里的功能, 官方所提供的预先定义的grok表达式见: https://github.com/logstash/logstash/tree/v1.4.2/patterns。

注意, 于新版本的logstash当中, pattern目录已然为空, 最后的一个commit提示, core patterns将会经由logstash-patterns-core gem予以提供, 此目录能够供用户用以存放自定义的patterns。

下面是从官方文件中摘抄的最简单但是足够说明用法的示例:

USERNAME [a-zA-Z0-9._-]+
USER %{USERNAME}

第一行, 借助普通的正则表达式去对一个 grok 表达式予以定义;第二行, 运用打印赋值格式, 凭借前面定义好的 grok 表达式来定义另外一个 grok 表达式。

grok 表达式的打印复制格式的完整语法是下面这样的:

%{PATTERN_NAME:capture_name:data_type}

需注意的小提示是,data_type这个内容开云手机入口官网下载, 当前仅仅只支持两个具体的值,分别是int以及float。

所以我们可以改进我们的配置成下面这样:

filter {
    grok {
        match => {
            "message" => "%{WORD} %{NUMBER:request_time:float} %{WORD}"
        }
    }
}

重新运行进程然后可以得到如下结果:

{
         "message" => "begin 123.456 end",
        "@version" => "1",
      "@timestamp" => "2014-08-09T12:23:36.634Z",
            "host" => "raochenlindeMacBook-Air.local",
    "request_time" => 123.456
}

这次 request_time 变成数值类型了。

最佳实践

在实际的运用情形当中开云app在线入口,开云真人官方下载, 我们是需要去处理林林总总各种各样的日志文件的。要是你全部都是在配置文件里分别各自写下一行属于自己的表达式的话, 那便会是完全没有办法进行管理的了。所以呀, 我们所给出的建议乃是在于把所有的 grok 这种表达式集中统一进行写入到一个固定的地方去。随后再运用 filter/grok 的 patterns_dir 这一选项来明确指明好了。

如若你已将“message”之中全部的信息, 都领会到各异的字段里了, 那么数据在本质上便等同于重复存储了两份。故而你能够运用remove_field参数去删除掉message字段, 或者借助overwrite参数来重写默认的message字段, 仅留存最为关键的部分。

重写参数的示例如下:

filter {
    grok {
        patterns_dir => "/path/to/your/own/patterns"
        match => {
            "message" => "%{SYSLOGBASE} %{DATA:message}"
        }
        overwrite => ["message"]
    }
}

小贴士多行匹配

当与codec/multiline搭配运用之际, 要留意一个问题, grok正则如同普通正则那般, 默认情形下并不支持对回车换行进行匹配, 如同你需要 =~ //m一般, 也得单独给予指定, 具体的书写方式是在表达式起始位置增添 (?m) 标记, 有如以下所展示的这般:

match => {
    "message" => "(?m)\s+(?\d+(?:\.\d+)?)\s+"
}

多项选择

偶尔会遇到一种情形, 就是一个日志它存在多种可能出现的格式, 处于这番状况时, 要是需写成单一正则, 那的话会比较困难, 或者说全用 | 进行隔开, 如此则又会显得比较丑陋, 而当下这个时侯呢, logstash 的语法为咱们给予了一个饶有趣味的解决办法。

在文档当中, 均已表明 logstash/filters/grok 插件 的那个 match 参数应当接收的 乃是一个 Hash 值。不过, 鉴于早期的 logstash 语法里面, Hash 值同样也是采用 如此这般的方式来书写的, 故而实际上如今传递 Array 值给予 match 参数一样也是毫无问题的。所以, 我们在此处实际上是能够传递多个正则去匹配同一个字段的:

match => [
    "message", "(?\d+(?:\.\d+)?)",
    "message", "%{SYSLOGBASE} %{DATA:message}",
    "message", "(?m)%{WORD}"
]

logstash 进行匹配时, 是会依照这个定义次序去依次尝试的, 试过之后直到匹配成功才罢手。尽管其效果跟利用 | 分割然后写出一个大大的正则表达式是相同的, 不过在可阅读性方面, 却是提升了不少的。

最后, 且是颇为关键之所指, 我以强烈之态建议, 每一人皆需运用 Grok Debugger 去调试自身的 grok 表达式。

标签: Grok 正则表达式 日志解析 运维 Logstash

发布评论 0条评论)

还木有评论哦,快来抢沙发吧~