Glide Note

glidenote's blog

fluentdのformat(正規表現)の作り方について試行錯誤中 #fluentd

Fluentdを触るようになって、いろんなログをfluentdに 渡すように試行錯誤している最中。

td-agent.conffluent.confを用意するときに任意のjson形式にするために 正規表現を用いてformatを書く必要があるんですが、formatの作り方というかデバック方法について どういう手順に作ると良いのか情報がネット上に見当たらず試行錯誤中。

もっと良い方法を教えてもらいたいので、今やっている方法を晒してみる。

そもそもの疑問、どうやってformatを作るのか

たとえばfluentd関連の情報を調べてると、

1
format /^(?<date>[^ ]+) (?<host>[^ ]+) (?<process>[^:]+): (?<message>((?<key>[^ :]+)[ :])? ?((to|from)=<(?<address>[^>]+)>)?.*)$/
1
format /^[^ ]+ [^ ]+ [^ ]+ [^ ]+ \[(?<time>[^\]]+)\] "(?<method>[^ ]+) (?<path>[^ ]+) [^"]+" (?<status>[^ ]+) [^ ]+ [^ ]+ "[^"]+" "[^"]+" (?<response_time>[^ ]+)$/

という感じで、formatの正規表現がサラッと書いてあって、 当然作れるでしょ的な感じでformatの作り方については言及されてない。 でも実際に作ろうとすると、どういう方法でやればいいのかよく分からない。

やりたいこと、squidのaccess.logをjson形式に

たとえば下記のようなsquidのaccess.log(squidのログ形式)をfluentdに渡して

1
1342297357.149    440 192.168.11.3 TCP_MISS/302 627 GET http://glidenote.disqus.com/count.js - HIER_DIRECT/75.126.109.204 text/javascript

下記のようにシリアライズしたい。

1
2
3
4
5
6
7
8
9
10
11
12
{
  "date"           : "1342297357.149",
  "duration"       : "440",
  "client address" : "192.168.11.3",
  "result code"    : "TCP_MISS/302",
  "bytes"          : "627",
  "request method" : "GET",
  "url"            : "http://glidenote.disqus.com/count.js",
  "rfc931"         : "-",
  "hierarchy code" : "HIER_DIRECT/75.126.109.204",
  "type"           : "text/javascript"
}

でもこれを実現するためのformatの作り方の手順を解説しているところが無い。(調べ方が悪いだけかもしれないですが)

最初にformat作成のためにやっていたこと(非効率な方法)

最初は

  1. confを修正
  2. 設定ファイル再読込
  3. 確認

というのを繰り返しやっていたんですが、非効率過ぎてこれだとformatを作る気にならず途中で断念。 というのが数ヶ月前の話。

今回format作成のためにやってみたこと

今回再チャレンジでいろいろ調べてみると有益な情報が。

fluent/parserの"RegexpParser"クラスを利用すればformat作成のデバッグが出来るらしい。

デバッグ用スクリプトの用意

上記サイトを参考に、下記のようなデバッグ用スクリプトを用意してlog,format,time_formatの部分を調整していく。 vim+quickrunとかの環境だと書きながらテストが出来るのでオススメです。 (外部ファイルを読み込ませる形より、log,formatを直接修正しながらテストしたほうが効率的でした)

いきなり全部のformatを書くのは無理なので、下記のような感じでログの一部ずつやっていく。 (今回の例だとtime_formatは利用していないので空のままです)

下記のような形でdateの項目だけ記載してシリアライズしてみる

意図した形式で出力された。

1
{"date"=>"1342297357.149"}

上手くいったら、durationなど1個ずつ項目を増やしてやっていく。

これを繰り返していくと、下記のような形で出来上がる。

これをconfに反映。とりあえずfile書き出しで様子見。(td-agent.confには=は必要無いので消す)

1
2
3
4
5
6
7
8
9
10
11
12
13
<source>
  type tail
  path /var/log/squid/access.log
  tag squid
  format /^(?<date>[^ ]+)\s+(?<duration>.*) (?<client address>.*) (?<result code>.*) (?<bytes>.*) (?<request method>.*) (?<url>.*) (?<rfc931>.*) (?<hierarchy code>.*) (?
<type>.*)$/
  pos_file /var/log/fluent/squid.pos
</source>

<match squid.**>
  type file
  path /var/log/fluent/squid.log
</match>

これでやりたいことが実現出来た。

もっと上手いやり方ありそうなんだけど、「こうすると良い」とか誰かもっと良い方法を教えて欲しい。

追記 2012年7月16日

@tagomorisさんがirbを利用する方法を教えてくれました。感謝です

追記 2012年10月01日

今だとこういう便利なものがあるようです!!

参考

Comments