fluentdでGKEコンテナから送られたログを正規表現で分解する


はじめに

前回fluentdからelasticsearchにログを格納して、あとはkibanaでレスポンスタイムとかを解析しようとしたらコンテナの標準出力で出されるnginxのアクセスログがlog要素に全部入っていて解析できなくてこまりました。なので正規表現で分解して解析できる形にログを整形します。

nginxのlogformat

default.conf

log_format  main2  '$remote_addr - $remote_user [$time_local] "$request" '
                  '$status $body_bytes_sent "$http_referer" '
                  '"$http_user_agent" "$http_x_forwarded_for" $request_time';
...skip

server {

...skip

   access_log /var/log/nginx/access.log main2;

...skip

吐き出されるログはこんな感じですね。

10.**.**.** - - [19/Dec/2018:06:58:09 +0000] \"GET /foo/bar?zoo=1 HTTP/1.1\" 200 433 \"-\" \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36\" \"-\" 0.020\n

これがlog要素の中に全て入ってしまうため、うまくkibanaが解析できない形になってしまう

{
    "log":"10.**.**.** - - [19/Dec/2018:06:58:09 +0000] \"GET /foo/bar?zoo=1 HTTP/1.1\" 200 433 \"-\" \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36\" \"-\" 0.020\n",
    "stream":"stdout",
    "time":"2018-12-19T06:58:09.634970634Z"
}

fuentdからElasticsearchに送る時に整形する


    # コンテナ名でフィルタリングする
    <filter kubernetes.var.log.containers.my_continer_name**.log>
      @type parser
      @id my_continer_filter
      # GKEの標準出力されたログはlogキーに全部入っている
      key_name log
      reserve_data true
      remove_key_name_field true
      <parse>
        @type multi_format
        #アクセスログを分解
        <pattern>
          format /^(?<remote>[^ ]*) - - \[(?<utc_time>[^\]]*)\] "(?<method>\S+) (?<path>\S+) (?<http>\S+)" (?<code>[^ ]*) (?<size>[^ ]*) "(?<referer>[^\"]*)" "(?<agent>[^\"]*)" "(?<http_x_forwarded_for>[^\"]*)" (?<request_time>\S+)$/
          # request_timeはfloatにする
          types size:integer,request_time:float
          time_format %Y-%m-%dT%H:%M:%S.%N%:z
        </pattern>
        # 他の形式のログが増えた場合は<pattern>を追加していく
        <pattern>
            ...skip
        </pattern>

jsonを確認

{
...skip

    "remote": "10.**.**.**",
    "utc_time": "19/Dec/2018:08:05:00 +0000",
    "method": "GET",
    "path": "/foo/bar?zoo=1",
    "http": "HTTP/1.1",
    "code": "200",
    "size": "433",
    "referer": "-",
    "agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36",
    "http_x_forwarded_for": "-",
    "request_time": "0.021",
    "@timestamp": "2018-12-19T08:05:00.763071925+00:00",
  },

...skip
}

 これで各APIの平均レスポンスタイムや分布、などを作ることができるようになりました。

正規表現苦手なんで間違ってる可能性がありますw
ご意見、マサカリなどお待ちしておりますm(_ _)m