Logstash filter 插件之 grok


本文簡單介紹一下 Logstash 的過濾插件 grok。

Grok 的主要功能

Grok 是 Logstash 最重要的插件。它可以解析任意文本並把它結構化。因此 Grok 是將非結構化的日志數據解析為可查詢的結構化數據的好方法
這個工具非常適合 syslog 日志、apache 和其他 web 服務器日志、mysql 日志,以及那些通常為人(而不是計算機)編寫的日志格式。

Grok 使用正則表達式提取日志記錄中的數據,這也正是 grok 強大的原因。Grok 使用的正則表達式語法與 Perl 和 Ruby 語言中的正則表達式語法類似。你還可以在 grok 里預定義好命名正則表達式,並在稍后(grok 參數或者其他正則表達式里)引用它。

Grok 語法

語法格式:
%{SYNTAX:SEMANTIC}

SYNTAX 是文本匹配的正則表達式模式。比如 NUMBER 模式可以匹配到 3.15 之類的數字;IP 模式可以匹配到 192.168.0.1 等 IP 地址。
SEMANTIC 是為匹配的文本提供的標識符。比如,3.15 可以是事件的 duration(持續時間),因此可以簡單地將其稱為 duration;字符串 192.168.0.1 用來標識發出請求的 client。
因此和用下面的模式來結構化日志記錄:
%{NUMBER:duration} %{IP:client}

其實上面的模式還不完善,%{NUMBER:duration} 匹配到的內容為字符串。如果你通過 duration 字段進行查詢,比較的方式為字符串間的比較。我們可以在 duration 模式中添加數據類型轉換的邏輯,將字符串更改為整數,只需要添加目標數據類型的后綴就可以了。例如 %{NUMBER:duration:float},它將 duration 語義從字符串轉換為浮點數。目前支持的轉換的類型只有 int 和 float。

我們可以通過 Grok Debugger 來學習和測試 grok 模式:

下面介紹一些常見的 demo

切出 path 中的特殊目錄名稱

筆者運維的一個系統中日志文件所在的目錄以服務的名稱命名,比如下面的 path:

/home/kr/work/sxs/logs/xxx.log

其中 sxs 為服務的名稱,所有服務的日志都以該策略保存。所以可以通過 grok 輕松的從 path 中切出服務的名稱:

grok {
    match => {
        "path" => "work/(?<service>%{WORD})/logs"
    }
}

使用 grok debugger 測試的結果如下:

切出 http 請求的返回狀態和響應時間

筆者系統中的日志記錄中記錄了 http 請求的返回狀態和響應時間,其格式大致如下:

xxxxxxx <= [172.18.0.10] [GET /api/users/me] [200] [103.055334 ms]

其中最后兩個方括號中分別是返回狀態和響應時間(單位毫秒)。可以使用下面的模式切出返回狀態和響應時間:

grok {
    match => {
        "message" => "<= \[.*\] \[%{NUMBER:responsestatus}:int\] \[%{NUMBER:responsetime:float} ms\]"
    }
}

上面的代碼同時把切出的結果進行了類型轉換。由於 grok debuger 不支持類型轉換,所以使用下面的模式進行測試:

<= \[.*\] \[%{NUMBER:responsestatus}\] \[%{NUMBER:responsetime} ms\]

結果如下:

在 kibana 中,我們可以看到對應字段的類型顯示為 number:

在 elasticsearch 中這兩個字段的類型分別為 long 和 float:

"responsestatus": {
    "type": "long"
},
"responsetime": {
    "type": "float"
},

切分 nginx 日志

我們可以在 nginx 的配置文件中指定其日志的格式,比如下面的配置:

log_format  main  '[$time_local] [$remote_addr] [$request] [$http_user_agent] [$http_referer] [$status] [$request_time]';

使用下面的 grok 規則就能夠正確切分出日志記錄中的每一個字段:

grok {
    match => {
        "message" => "\[%{HTTPDATE:timestamp}\] \[%{IPV4:client}\] \[%{DATA:request}\] \[%{DATA:useragent}\] \[%{DATA:referer}\] \[%{NUMBER:responsestatus}\] \[%{NUMBER:responsetime}\]"
    }
}

我們使用下面的一條日志記錄在 Grok Debugger 中測試:

[26/Mar/2019:10:13:19 +0000] [52.187.2.193] ["GET /api/hc/mongo HTTP/1.1"] ["Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.104 Safari/537.36"] ["-"] [301] [0.050]

解析出的內容如下:

{
  "timestamp": [
    [
      "26/Mar/2019:10:13:19 +0000"
    ]
  ],
  "client": [
    [
      "52.187.2.193"
    ]
  ],
  "request": [
    [
      ""GET /api/hc/mongo HTTP/1.1""
    ]
  ],
  "useragent": [
    [
      ""Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.104 Safari/537.36""
    ]
  ],
  "referer": [
    [
      ""-""
    ]
  ],
  "responsestatus": [
    [
      "301"
    ]
  ],
  "responsetime": [
    [
      "0.050"
    ]
  ]
}

 

參考:
Grok filter plugin
Grok Debugger
《ELK Stack 權威指南》


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM