/home/by-natures/dev*

データ界隈で働くエンジニアとしての技術的なメモと、たまに普通の日記。

nginx のログを fluentd で扱う方法

fluentd で nginx のログを扱おうとしたのですが、ちょっと詰まったのでメモ。

fluentd では、apache の Combined Log Format (詳しくは Apache HTTP サーバ バージョン 2.4 ログファイル 等をご参照ください) を簡単に source として利用することができます。Combined Log Format は以下のように定義されます:

LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-agent}i\"" combined
CustomLog log/access_log combined

これに対する fluentd の source の設定(最小限)は次のようになります:


  type tail
  path /var/log/httpd/access_log
  pos_file /var/log/td-agent/httpd-access.log.pos
  tag httpd.access
  format apache

nginx での注意点

nginx もデフォルトでは Combined Log Format を利用するため、上記 fluentd の設定の path 等を変更すれば、そのまま fluentd は稼働します。しかし nginx の設定ファイルである nginx.conf を見ると、アクセスログに関して次のようなコメントが記載されています:

 http {
    ...
    #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
    #                  '$status $body_bytes_sent "$http_referer" '
    #                  '"$http_user_agent" "$http_x_forwarded_for"';

    #access_log  logs/access.log  main;
    ...

このログの設定は、最初の状態ではコメントアウトされていますが、Apache の設定ファイルである httpd.conf における Combined Log Format と比較すると、最後に http_x_forwarded_for という変数が追加されています。つまり、このコメントアウトされているログの設定をコメントインしてしまうと、Combined Log Format から外れてしまいます。

実際に nginx.conf の設定で上のログ設定をコメントインして fluentd にアクセスしてみると、"pattern not match" と出力されます:

[01:55:47 root@bynatures ~]# td-agent -vv
...
2013-01-07 01:55:50 +0900: plugin/in_tail.rb:279:initialize: following tail of /var/log/nginx/access.log
(fluentd が起動したので、nginx のログが吐かれるようにブラウザでアクセス)
2013-01-07 01:55:55 +0900: fluent/parser.rb:38:call: pattern not match: 126.65.237.78 - - [07/Jan/2013:01:55:55 +0900] "GET / HTTP/1.1" 304 0 "-" "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.97 Safari/537.11" "-"

これを修正するためには、nginx.conf で設定したログに合わせて fluentd の format 設定を修正する必要があります。以下の設定例では、http_x_forwarded_for に当たるログを forwarder として取得しています:


  type tail
  path /var/log/nginx/access.log
  pos_file /var/log/td-agent/nginx-access.log.pos
  tag nginx.access
  format /^(?[^ ]*) (?[^ ]*) (?[^ ]*) \[(?

time_format の設定が増えていますが、これは format に自ら正規表現を指定したため、time として取得する日付のフォーマットを time_format の設定として与える必要があるためです。time_format の指定がないと、argument out of rangeのエラーが発生し、fluentd が正しく動作しません。(format に apache を指定した場合は、time_format も合わせて設定されますので明示的な指定は不要です。)