logstash之grok学习笔记

logstash之grok插件学习

环境

为了方便, 使用docker版本的logstash直接跑实验.

  • OS: Ubuntu 18.04.1 64Bit
  • Kernel: 5.0.0-37-generic
  • logstash v7.5.0
  • grok: v4.2.0
  • docker community 19.03.5

概述

logstash是一个日志过滤/解析程序, 它基本的工作过程为:
输入(input) => 过滤(filter) => 输出(output)
grok插件工作在filter这一层.

grok可以将任意的文本转换为结构化的数据.

logstash内置了约120种模式(pattern). 你可以在这里找到它们.
当然你也可以添加自己写的模式(请查看设置项: patterns_dir).

摘抄了一部分"内置模式", 如下:

USERNAME [a-zA-Z0-9._-]+
USER %{USERNAME}
EMAILLOCALPART [a-zA-Z][a-zA-Z0-9_.+-=:]+
EMAILADDRESS %{EMAILLOCALPART}@%{HOSTNAME}
INT (?:[+-]?(?:[0-9]+))
BASE10NUM (?<![0-9.+-])(?>[+-]?(?:(?:[0-9]+(?:\.[0-9]+)?)|(?:\.[0-9]+)))
NUMBER (?:%{BASE10NUM})
BASE16NUM (?<![0-9A-Fa-f])(?:[+-]?(?:0x)?(?:[0-9A-Fa-f]+))
BASE16FLOAT \b(?<![0-9A-Fa-f.])(?:[+-]?(?:0x)?(?:(?:[0-9A-Fa-f]+(?:\.[0-9A-Fa-f]*)?)|(?:\.[0-9A-Fa-f]+)))\b

其实就是预先定义好一些正则, 到时方便引用.

logstash基本使用

默认配置

首先看看logstash的默认配置:

$ docker run --rm -it logstash:7.5.0 bash
bash-4.2$ cat /usr/share/logstash/pipeline/logstash.conf
input {
  beats {
    port => 5044
  }
}

output {
  stdout {
    codec => rubydebug
  }
}

默认从5044端口接收beats的输入, 输出为标准输出(stdout), 也就是打印到屏幕上.

基本测试

为了方便实验, 我们用标准输入(stdin)作为input的部分, 配置如下:

gerrylon@Inspiron-7472:/mnt/data/workspace/test/logstash-grok
$ cat config/logstash.yml 
xpack.monitoring.enabled: false
log.level: error

gerrylon@Inspiron-7472:/mnt/data/workspace/test/logstash-grok
$ cat pipeline/logstash.conf 
input {
  stdin {
  }
}

output {
  stdout {
    codec => rubydebug
  }
}

然后用docker启动并随机输入测试:

$ docker run --rm -it -v `pwd`/pipeline/logstash.conf:/usr/share/logstash/pipeline/logstash.conf -v `pwd`/config/logstash.yml:/usr/share/logstash/config/logstash.yml logstash:7.5.0 
......省略logstash日志信息
The stdin plugin is now waiting for input:
hello
/usr/share/logstash/vendor/bundle/jruby/2.5.0/gems/awesome_print-1.7.0/lib/awesome_print/formatters/base_formatter.rb:31: warning: constant ::Fixnum is deprecated
{
      "@version" => "1",
       "message" => "hello",
    "@timestamp" => 2019-12-22T02:26:07.653Z,
          "host" => "7d4f894f7425"
}
world
{
      "@version" => "1",
       "message" => "world",
    "@timestamp" => 2019-12-22T02:26:13.018Z,
          "host" => "7d4f894f7425"
}

grok使用

在上面的基本测试中, 可以看到, 在我们输入"hello"后, logstash会输出:

{
      "@version" => "1",
       "message" => "hello",
    "@timestamp" => 2019-12-22T02:26:07.653Z,
          "host" => "7d4f894f7425"
}

自动转成了json格式(结构化的数据).

这个太简单了, 几乎没有什么有用的信息, 因为我们输入也很简单.
平时我们可能使用这样的日志格式在程序中

...
[2019-12-22 10:34:22.523] [INFO] [controller.Get:32] get request from client...
...

上面的日志格式是很常见的, 包括4个字段: 时间, 日志级别, 调用方法及所在行, 打印信息.
那我们来将这4个字段的正则写一下.
grok正则解析使用的是x, 具体在logstash中定义有两种方法:

  • 一种是将正则写到某个文件中, 再使用patterns_dir设置
  • 另一种是直接在logstash的配置文件()中用pattern_definitions来定义.

patterns_dir

新增pattern

$ tree .
.
├── config
│   └── logstash.yml
├── patterns  ## (这个是新加的)
│   └── mylog
└── pipeline
    └── logstash.conf

新增mylog:

$ cat patterns/mylog 
# 可以引用已有的模式, 如YEAR
# ref: https://github.com/logstash-plugins/logstash-patterns-core/blob/master/patterns/grok-patterns
MY_TIME %{YEAR}-%{MONTHNUM2}-%{MONTHDAY} %{HOUR}:%{MINUTE}:(?:(?:[0-5][0-9]|60)\.\d+)
MY_LOG_LEVEL %{LOGLEVEL}
MY_FUNC \w[^:]*:\d+
MY_MSG .+

修改 logstash.conf:

$ cat pipeline/logstash.conf 
input {
  stdin {
  }
}

# filter是新加的
filter {
    grok {
        patterns_dir => ["/opt/logstash/patterns"]
        match => {
            "message" => [
                "^\[%{MY_TIME:time}\] \[%{MY_LOG_LEVEL:level}\] \[%{MY_FUNC:func}\] %{MY_MSG:msg}$"
            ]
        }
    }
}

output {
  stdout {
    codec => rubydebug
  }
}

测试:

$ docker run --rm -it -v `pwd`/pipeline/logstash.conf:/usr/share/logstash/pipeline/logstash.conf -v `pwd`/config/logstash.yml:/usr/share/logstash/config/logstash.yml  -v `pwd`/patterns:/opt/logstash/patterns/ logstash:7.5.0  
......省略logstash的日志
{
          "func" => "controller.Get:32",
       "message" => "[2019-12-22 10:34:22.523] [INFO] [controller.Get:32] get request from client...",
          "host" => "d551adf987fa",
          "time" => "2019-12-22 10:34:22.523",
         "level" => "INFO",
      "@version" => "1",
           "msg" => "get request from client...",
    "@timestamp" => 2019-12-22T03:26:42.880Z
}
hello world
{
          "tags" => [
        [0] "_grokparsefailure"
    ],
       "message" => "hello world",
          "host" => "d551adf987fa",
    "@timestamp" => 2019-12-22T03:26:58.301Z,
      "@version" => "1"
}

看效果可以明白, 如果可以正确解析, 会多4个字段出来, 字段名是我们可以自己定义, 如:%{MY_TIME:time}.
如果按已有模板, 解析不出来, 会多一个_grokparsefailure的tag,
但是message还是保存着原始输入.

pattern_definitions

$ cat pipeline/logstash.conf 
input {
  stdin {
  }
}

filter {
  grok {
    # patterns_dir => ["/opt/logstash/patterns"]
    match => {
      "message" => [
        "^\[%{MY_TIME:time}\] \[%{MY_LOG_LEVEL:level}\] \[%{MY_FUNC:func}\] %{MY_MSG:msg}$"
      ]
    }

    pattern_definitions => {
        "MY_TIME" => "%{YEAR}-%{MONTHNUM2}-%{MONTHDAY} %{HOUR}:%{MINUTE}:(?:(?:[0-5][0-9]|60)\.\d+)"
        "MY_LOG_LEVEL" => "%{LOGLEVEL}"
        "MY_FUNC" =>  "\w[^:]*:\d+"
        "MY_MSG" => ".+"
    }
  }
}

output {
  stdout {
    codec => rubydebug
  }
}

运行:

docker run --rm -it -v `pwd`/pipeline/logstash.conf:/usr/share/logstash/pipeline/logstash.conf -v `pwd`/config/logstash.yml:/usr/share/logstash/config/logstash.yml   logstash:7.5.0

测试效果和使用patterns_dir一样

总结:

  • 使用patterns_dir时, 注意行尾部空格.
  • 注意logstash.conf中k-v分隔用的是"=>", 不是别的符号, 留意即可.
  • 如果出现_grokparsefailure, 但是又不知道哪里不对时, 可调试grok语法
    • grokdebug 这个我没试成功
    • Kibana -> Dev Tools -> Grok Debugger 我用这个调试的
    • 还有其他的欢迎补充

参考

发布了231 篇原创文章 · 获赞 77 · 访问量 52万+

猜你喜欢

转载自blog.csdn.net/butterfly5211314/article/details/103642383