2013年6月5日水曜日

nginxでltsv形式のaccess.logを出力する

人間による可読性の良さと、parse処理のしやすさ、1行中の出力内容の順序にたいしてロバスト(項目の順番が変わったり追加されてもparseに失敗することは無い)という点でltsv(Labeled Tab-Separated Value)というファイルフォーマットが一時期流行りました。

もちろん一時の流行ではなく、非常に実用的な手法なので、このたびnginxの出力ログをltsv形式に変えてみました。

◯設定
naoyaさんのブログ(http://d.hatena.ne.jp/naoya/20130205/1360088927)を引用すると、以下のような形になります。
http {
    …
    log_format  ltsv  'time:$time_local\t'
                      'host:$remote_addr\t'
                      'request:$request\t'
                      'status:$status\t'
                      'size:$body_bytes_sent\t'
                      'referer:$http_referer\t'
                      'ua:$http_user_agent\t'
                      'reqtime:$request_time\t'
                      'upsttime:$upstream_response_time';

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

nginxで定義されている変数を用いて、タブ区切りでフォーマットを記述していく感じですね。

個人的な環境では上記では項目が不足していたので、以下のように項目を追加しています。
  log_format  ltsv  'time:$time_local\t'
                    'msec:$msec\t'
                    'host:$remote_addr\t'
                    'forwardedfor:$http_x_forwarded_for\t'
                    'req:$request\t'
                    'method:$request_method\t'
                    'uri:$request_uri\t'
                    'status:$status\t'
                    'size:$body_bytes_sent\t'
                    'referer:$http_referer\t'
                    'ua:$http_user_agent\t'
                    'reqtime:$request_time\t'
                    'upsttime:$upstream_response_time\t'
                    'cache:$upstream_http_x_cache\t'
                    'runtime:$upstream_http_x_runtime\t'
                    'vhost:$host';

  • アクセス時間は秒単位では情報として不足しているので、milliseconds($msec)まで出力するようにした。
  • $request は "GET /hoge" のようにrequest methodとrequest pathがスペース区切りで出力されますが、後々の集計の際に一緒になっていると面倒なので、$request_methodと$request_uriをそれぞれ個別に出力するようにした。
  • reverse proxyとして動作した際に有用な情報を追加($upstream~)
あたりが追加した動機です。

なお、WEB+DB Pressの74号で「LTSVでログ活用」という記事が書かれています。こちらに、「推奨ラベル一覧」という表があるので、各項目のlabel名をどのようにするか、参考にすると良いでしょう。
http://www.amazon.co.jp/dp/4774156078


◯Fluentdで読み込み
おそらく多くの現場で、出力したログはFluentd経由で読み込み、各種metricsの可視化や、解析サーバーへの転送などを行なっていると思います。

apacheのログを読み込む際は、たとえばin_tailプラグインなどを用いて、正規表現でparseをする形になります。commonsやcombined形式であればFluentdに標準パーサーがありますが、独自の拡張が行われたログの場合は自分でparseのフォーマットを記述する必要がありました。

ltsvの場合、最新(<= 0.10.32 )のFluentdであればltsv用の標準パーサーがありますので、非常に手軽に取り込めます。
<source>
  type tail
  format ltsv
  (snip.)
</source>
出力項目が変更になってもparse処理の部分は特に気にする必要が無いので、そういう意味では楽ですね。


ltsvは若干出力サイズが冗長になると思いますが、それを補って余りあるメリットがあるので、それほど大規模でないサイトやアプリのロギング方式としては適切だと思います。



0 件のコメント:

コメントを投稿