Apacheログ "%U%q" のパス出力は"%r"と互換性が無い
AcceptPathInfoがOffになっているような、標準とは違うApache環境下で動く不幸なCakePHPで、公開ディレクトリに書かれる.htaccessによるmod_rewite規則
<IfModule mod_rewrite.c> RewriteEngine On RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^(.*)$ index.php?url=$1 [QSA,L] </IfModule>
という奴を使うと、例えば http://example.com/top/ というURLにアクセスすると、Apacheのカスタムログフォーマットでいうと、
%r: GET /top/ HTTP/1.1 %U: /top/ %q: ?url=top/
となり、
%U%q: /top/?url=top/
となります。/top/
になってほしいのに、内部rewrite処理で生成された?url=top
が付いてしまうのです。redirect_logはこんな感じ。
(3) [perdir /var/www/html/] add path info postfix: /var/www/html/top -> /var/www/html/top/ (3) [perdir /var/www/html/] strip per-dir prefix: /var/www/html/top/ -> top/ (3) [perdir /var/www/html/] applying pattern '^(.*)$' to uri 'top/' (4) [perdir /var/www/html/] RewriteCond: input='/var/www/html/top' pattern='!-d' => matched (4) [perdir /var/www/html/] RewriteCond: input='/var/www/html/top' pattern='!-f' => matched (2) [perdir /var/www/html/] rewrite 'top/' -> 'index.php?url=top/' (3) split uri=index.php?url=top/ -> uri=index.php, args=url=top/ (3) [perdir /var/www/html/] add per-dir prefix: index.php -> /var/www/html/index.php (2) [perdir /var/www/html/] trying to replace prefix /var/www/html/ with / (5) strip matching prefix: /var/www/html/index.php -> index.php (4) add subst prefix: index.php -> /index.php (1) [perdir /var/www/html/] internal redirect with /index.php [INTERNAL REDIRECT]
fluentdのログ転送で使うLTSVフォーマット指定で、パスの表記に%U%q
で指定している例が多いので、通常のApacheログとfluentdで収集したApacheログで表記が食い違うことに……
fluentdでApacheログをLTSVで出力している人は注意が必要です……
ここで唐突にApache CustomLog書式の確認
http://httpd.apache.org/docs/2.2/ja/mod/mod_log_config.html
フォーマット文字列 | 説明 |
---|---|
%q | 問い合せ文字列 (存在する場合は前に ? が追加される。 そうでない場合は空文字列) |
%r | リクエストの最初の行 |
%U | リクエストされた URL パス。クエリ文字列は含まない |
修飾子
(略)
修飾子 "<" と ">" は内部リダイレクトされたリクエストのログに 元のリクエストか最終的なリクエストのどちらを使用するかを 指定するために使います。デフォルトでは、% ディレクティブの %s, %U, %T, %D, %r は元のリクエストを、他は最終的なリクエストを 使用します。例えば、リクエストの最終ステータスを記録するには %>s を、内部的に認証されていないリソースへリダイレクトされた リクエストで元のリクエストで認証されたユーザを記録するためには %<u を使うことができます。
LogFormatで%U%<qすればいいじゃない
効かないんだなーこれが
fluentdでの解決法
解決法はQiitaに書く(要fluentd v0.12以降)→書いた