トップページに戻る

イントロダクション、サーバー構成、fluentdのセットアップ

import_logs.py を使って fluentd 経由で apache combined アクセスログを取り込む

  • もちろん urchin ログにも対応できます(下記に例示してます)
  • fluentd の format 正規表現を変更すればあらゆるログにも当然対応できます
  • piwik-fluentd >= 2.0.0 で Web サイトに貼りこんだ Piwik の javascript (以下 Piwik traker)のアクセスログから、後追い集計できるようになりました。 これで Urchin と完全に同じです。
  • piwik-fluentd >= 2.0.0 から追加されたファイル、機能については、 (piwik-fluentd >=2.0.0) と表記します。

(piwik-fluentd >=2.0.0) 後追い集計の意義

Piwik で集計したいサイトは、Piwik 管理画面で指示される javascript をサイト内に埋め込む必要があります(Piwik tracker)。通常は、Piwik tracker により piwik.php を直接叩いてリアルタイム集計が行われるのですが、MySQL のトラブル、または Piwik の度重なる update 毎に集計がとまります。

apache または nginx のログを取り込む import_logs.py には、piwik.php のアクセスログよりリアルタイム集計を再現する機能がもともと実装されているのですが、取り込み単位が一ファイルなので、 トラブルまたはメンテナンスで停止していた時間を再集計 することが困難です。そこで、piwik-fluentd >= 2.0.0 では、 import_logs.py でログ取り込み範囲を時間選択できるオプションを追加しました。

Piwik tracker で普通に集計できていて、 piwik-fluentd で Piwik tracker のアクセスログ後追い集計を行うと二重集計になるのでご注意ください。

ダウンロード

piwik-fluentd-2.0.3.tar.gz

時にはログ集計が必要な場合もある

piwik のアクセス集計では web の各ページにトラッキングコードを入れることが最も理想的ではありますが、

  • 共通デザインテンプレートがあるらしいのだが、どこをどう読んでいるのか、みためわからない
  • cgi でコンテンツを出しているらしく、中身がよくわからない
  • トラッキングコードを入れるまでの代替手段
  • 現在のアクセス集計と数値をあまり乖離させたくない(ボットのアクセスも入ってるんです...)

等の理由により、apache の combined log から集計というせざるをえない場合があります。幸い piwik では、 import_logs.py という python ベースのアクセスログ取り込みプログラムが用意されています。しかしアクセスログから集計する上で最大かつどうしようもない問題が、 メモリ です。取り込むまではいいんです。しかし piwik では

piwik/console core:archive
を実行しなければ、グラフなどは出ません。 しかし、一つのある程度大きいログファイルを import_logs.py で読み込んだ後に、 console core:archive を叩くと、メモリが足りない
PHP Fatal error:  Allowed memory size of XXXX bytes exhausted
とエラーが出て処理がとまります。処理がとまるたびに piwik/config/config.ini.php で minimum_memory_limit_when_archiving の数値を増やして対応することになりますが、すぐに限界がきます。たかだか 10 万ページビューのアクセスログで、8G 確保しても足りなくなるのです。 piwik 2.1から改善 されてはいるようなのですが、それでもメモリー食いすぎです。

じゃあ細切れにしよう

まあでも、小さいログファイルに分割してちょくちょく

  • import_logs.py
  • console core:archive

を交互に実行すれば 100 万ページビュー/月 であろうとも集計できるのです。ただ、ログ集計は以下の点でめんどくさい:

  1. 分割するプログラムを用意しないとならない(archive 時にメモリが足りなくなるのを防ぐ)
  2. import_logs.py には複数の web サーバーから ftp でログとってくる機能なんかない
  3. 取り込み完了したファイルと未完了のファイルの識別をどうするか
  4. 集計する Web サイトは一つではないですよね...

このうち、1, 2 (4 も?) については、いま流行っている fluentd でそう手間をかけずに piwik サーバーに集約できそうです。3, 4 については、難しいこと考えず単純に make とシェルスクリプトで実現することにします。

サーバー構成と仕組み

  • import_logs.py と console core:archive を動かすサーバー(以下 piwik サーバーといいます)に各 web サイト(以下各 web サイトサーバーといいます)からのアクセスログを fluentd で集約します。
  • import_logs.py は fluentd 対応ではないので、パッチを当てます(パッチは piwik-fluentd-2.0.3.tar.gz に含まれます)
  • 一定時間ごとに import_logs.py と console core:archive を cron で動かします
  • 集計終了ログと、未集計ログの判別は make で行います

(piwik サーバー)ディレクトリ構成

import_logs.py と console core:archive を実行する piwik サーバーに piwik-fluentd-2.0.3.tar.gz を展開します。 td-agent 以下、は web サイト毎のディレクトリです(説明上展開されるディレクトリは site1 - site5 としていますが、名前は何でもいいです)。td-agent 以下各サイトのアクセスログを格納するディレクトリは fluentd 導入後に owner を td-agent:td-agent とします。

your_own_path は、 piwik-fluentd-2.0.3.tar.gz を展開したディレクトリです。

/your_own_path/fluentd/
 ├── bin (fluentd 対応の import_logs.py、シェルスクリプト)
 ├── exclude (取り込んではいけない URL パスが書かれたファイルを格納)
 ├── log (piwik/console core:archive のログ)
 ├── piwik-patch (Piwik 日本語(マルチバイト)問題解決パッチ)
 └── td-agent (各サイト毎アクセスログディレクトリ)
     ├── piwik_tracker (Piwik tracker のアクセスログ)(piwik-fluentd >=2.0.0)
     ├── site1 (Web サイト 1 のアクセスログ)
     ├── site2 (Web サイト 2)
     ├── site3
      ├── site4
     └── site5_test_disable (もしテストしたければ。disable を入れると定時処理からは除外する)

Piwik tracker のアクセスログとは何か?

Piwik で集計したいサイトは、Piwik 管理画面で指示される javascript をサイト内に埋め込む必要があります(Piwik tracker)。通常は、Piwik tracker により piwik.php を直接叩いてリアルタイム集計が行われるのですが、piwik.php のアクセスログ、つまり Piwik サーバーそのもののアクセスログをここに配置することにより、リアルタイム集計を後追いすることができます。

(piwik サーバー) Piwik の設定とパッチ

(piwik サーバー)Piwik の日本語(マルチバイト)問題を解決します

Piwik 日本語(マルチバイト)パッチ

(piwik サーバー)console core:archive で使うメモリー

対象 Web サーバー、1 siteid が 100 万ページビュー/月 を超えるときは、 piwik/config/config.ini.php の General セクションに次のように追加します:

[General]
; Minimum memory limit enforced when archived via ./console core:archive
minimum_memory_limit_when_archiving = 2048

残念ながら、2G 程度は必要です。 さらに同じサーバーでデータベースを動かすのならば最低でも 4G 程度のメモリーが必要でしょう。 デフォルトは 768 で、月末にメモリーが足りなくなります。 monthly visitor の集計を行うので、月初はいいのですが、月末に近づくほど厳しくなります。

このあたりの議論は、 How do I enable “Unique Visitors” metric for Yearly reports and for Custom Date Ranges? を参照してください。ここにあるように yearly の集計を行うのであればもっとメモリが必要になります。

(piwik サーバー、web サイトサーバー) fluentd のインストールと起動

ここからダウンロード して、td-agent を piwik サーバー、各 web サイトサーバーともにインストールします。インストール時に td-agent というユーザーとグループが作られるのですが、uid, gid は固定ではないので、全サーバーで適当に合わせておきます。

  • /var/log/td-agent/ のみ owner が td-agent:td-agent になるようです。
  • piwik サーバーは udp と tcp の 24224 を開けておく必要があります(変更可能)。

(piwik サーバー)fluentd の設定

  • 以下の設定では非圧縮時のアクセスログサイズを 16mバイトくらいに分割してくれます
  • 以下の設定では一時間でアクセスログが 16m バイトを超えないときは、一時間毎で分割されます
  • 以下は 1 サイトの設定ですが、サイトの数だけ作成します

/etc/td-agent/td-agent.conf

<match site1.example.com> ← Web サイトの tag 名と合わせること
  type file
  path /your_own_path/fluentd/td-agent/site1/access ← access はファイル名の prefix になります。
  time_slice_format %Y%m%dT%H
  time_format %Y-%m-%dT%H:%M:%S%z
  # default 8m
  buffer_chunk_limit 16m
  compress gzip
  localtime ← これがないと突然 GMT になるときがあります 
</match>

  • (piwik-fluentd >=2.0.0)Piwik tracker(= Piwik server)のログを fluentd で送るように設定します。

/etc/td-agent/td-agent.conf

<source>
  type tail
  format apache ← urchin のログ形式ではないのでこれでよし 
  time_format %d/%b/%Y:%H:%M:%S %z
  pos_file /var/log/td-agent/access_log.pos ← 複数サイトがあっても、pos_file は同じファイルにできます
  path /var/log/httpd/piwik/access_log
  tag piwiktracker.apache.access ← Piwik server の tag 名
</source>
<match piwiktracker.apache.access> ← Piwik server の tag 名と合わせること
  type file
  path /your_own_path/fluentd/td-agent/piwik_tracker/access
  time_slice_format %Y%m%dT%H
  time_format %Y-%m-%dT%H:%M:%S%z
  # default 8m
  buffer_chunk_limit 16m
  compress gzip
  localtime ← これがないと突然 GMT になるときがあります 
</match>

(web サイトサーバー)fluentd の設定

  • access_log を piwik サーバーに送り付けます。
  • ここで示している format の正規表現は combined ではなく、urchin (combined + cookie)の例です。 combined アクセスログであれば単に apache でいいです。
  • 複数サイトがあっても、pos_file は同じファイルにできます

/etc/td-agent/td-agent.conf

<source>
  type tail
  # urchin (combined + cookie)
  format /^(?<host>[^ ]*) [^ ]* (?<user>[^ ]*) \[(?<time>[^\]]*)\] "(?<method>\S+)(?: +(?<path>[^ ]*) +\S*)?" (?<code>[^ ]*) (?<size>[^ ]*)(?: "(?<referer>[^\"]*)" "(?<agent>[^\"]*)" "(?<cookie>[^\"]*)")?$/
  time_format %d/%b/%Y:%H:%M:%S %z
  pos_file /var/log/td-agent/access_log.pos ← 複数サイトがあっても、pos_file は同じファイルにできます
  path /var/log/httpd/site1/access_log
  tag site1.example.com ← この Web サイトの tag 名
</source>
<match site1.example.com> ← Web サイトの tag 名を合わせること
  type forward
  send_timeout 60s
  recover_wait 300s
  heartbeat_interval 1s
  phi_threshold 16
  hard_timeout 60s
  <server>
    name piwik
    host piwik サーバーの IP アドレス
    port 24224
    weight 100
  </server>
  # use longer flush_interval to reduce CPU usage.
  # note that this is a trade-off against latency.
  # flush_interval 60s
</match>

/var/log/httpd/site1/access_log については、一意のファイル名でないとなりません。 cronolog とか apache の rotatelogs を使ってアクセスログのファイル名に日付を付ける設定にしている場合は、現在書き込みをしているログファイルに一意の(たとえば access_log)シンボリックリンクを張るオプションを利用しファイル名が見かけ上変わらないようにします。

なお cronolog 使用時は 1 時間ごとにシンボリックリンクのタイムスタンプが変更されてしまい、fluentd がログが切り替わったと誤判定してpiwikサーバーに同じログが二重に転送されてしまいます。 cronolog ではこのようなオプションは使わず、たとえば次のようなスクリプトを毎日 00:00:00 に実行することで対処できます。

  1. #!/bin/bash
  2. for site in site1 site2 site3 site4
  3. do
  4. pushd /var/log/httpd/$site
  5. wget -O /dev/null http://$site/
  6. /bin/rm -rf access_log
  7. ln -s "access"`LANG=C; date "+%Y%m%d"`".log" access_log
  8. popd .
  9. done

td-agent.conf の format の正規表現は、現状のログに合わせてください。ミスマッチの場合、デフォルトではすべてのアクセスログが web サイトサーバーの /var/log/td-agent/td-agent.log に記録され、あっちゅー間に /var が一杯になります。アクセスログをカスタマイズしている場合は Fluentular で一度チェックします。

(piwik サーバー、web サイトサーバー) fluentd の起動

設定が完了したら fluentd を起動します。起動したら、/var/log/td-agent 以下のログで設定が問題ないかを確認します。piwik サーバーの各サイト毎アクセスログディレクトリに access.20140701T16_0.log.gz のようなファイルが作製されれば成功です。

# /etc/init.d/td-agent start
# chkconfig td-agent on