Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
10
Help us understand the problem. What is going on with this article?
@CLCL

fluentdでApacheログをLTSVで転送するときのひと工夫(内部リダイレクト表記対策)

More than 5 years have passed since last update.

Apacheのアクセスログの書式、それをfluentd等の他のログ収集システムに持っていくときの問題です。

Apacheログ "%U%q" のパス出力は"%r"と互換性が無い

Apacheのmod_rewriteによる内部リダイレクト規則を適用する場合、例えば下記のような

.htaccess
<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はこんな感じ。

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で収集したLTSV表記Apacheログでパス表記が食い違うことに……

ここで唐突に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すればいいじゃない

効かないんだなーこれが

解決法

td-agent.conf
## Apache 拡張ltsvログ用
# LogFormat "domain:%V\thost:%h\tserver:%A\tuser:%u\t
#time:%{%d/%b/%Y:%H:%M:%S %z}t\tmethod:%m\tpath:%U%q\tprotocol:%H\tcode:%>s
#\tsize:%b\treferer:%{Referer}i\tagent:%{User-Agent}i\tresponse_time:%D\t
#cookie:%{cookie}i\tset_cookie:%{Set-Cookie}o\tcountry:%{GEOIP_COUNTRY_CODE}e\t
#requestFirstLine:\"%r\"" combined_ltsv

<source>
  type         tail
  path         /var/log/httpd/ltsv_access_log
  pos_file     /var/log/td-agent/apache_access.pos
  format       ltsv
  time_key     time
  time_format  %d/%b/%Y:%H:%M:%S %z
  tag          apache.access.addHostname.fixPath
  types        code:integer,size:integer,response_time:integer
</source>

## record_transformerプラグインで、ホストを追加する
<filter **.addHostname>
  @type record_transformer
  <record>
    hostname ${hostname}
  </record>
</filter>

## record_transformerプラグインで、requestFirstLineからpathを分離し、追加する
<filter **.fixPath>
  @type record_transformer
  enable_ruby true
  <record>
    path     ${requestFirstLine.split(/ /)[1]}
  </record>
  remove_keys  requestFirstLine
</filter>


# Apache関連のログを転送
<match apache.**>
  type copy

  # デバッグ用
  #<store>
  #  type stdout
  #</store>

  # fluentdサーバに送信
  <store>
    type forward
    flush_interval 30s
    <server>
      host fluentd-server.example.com
      port 24224
    </server>
  </store>

</match>

など、apacheの方で%rでrequestFirstLineを追加、record_transformerプラグインでrequestFirstLineからpath部を分離し、pathとして追加する方法を採用しました。

filterやrecord_transformerが使える、fluentd v0.12以降(td-agent2なら2015/4/6のtd-agent v2.2.0以降)が必要。

[http://cl.hatenablog.com/entry/apache-customlog より加筆]

10
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
CLCL

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
10
Help us understand the problem. What is going on with this article?