More Related Content Similar to Piwik fluentd at OSC Tokyo 2015 Fall (20) Piwik fluentd at OSC Tokyo 2015 Fall1. Piwik + flutned で 100 万 pv/month サイトのログ解析
YAMAMOTO Takashi
yamachan@piwikjapan.org
Piwik Japan
OSC Tokyo fall
Oct 25, 2015
2. すでに公開しています
■ Piwik Japan ユーザー会
■ http://www.piwikjapan.org/
■ osdn https://osdn.jp/projects/piwik-fluentd/
■ Piwik osdn で検索するとでます。
■ 細かい設定はすべてこちらに記述しています。
■ 日本語問題のパッチもここに置いています。
2 of 28
5. なぜ Piwik なのか
■ Urchin がなくなった
□ google に買収され、現在は google Analytics になった
□ アプリケーションであり google にデータを渡すことなく自前でログ
解析ができた
■ ID を分けて、担当の Web サイト以外の集計は見せないようし
たい
■ google にアクセスログ渡したくない
■ Open Source でログが取り込めるのは Piwik だけ
□ もちろん他もあるけどどれも開発はだいぶ前に終了、今からみれば
低機能
5 of 28
6. Piwik fluentd で何ができるのか
■ apache のログを Piwik にとりこみます
■ ログは fluentd 形式です
□ 標準では対応していません
■ ついでに、日本語文字コード関連の問題の解決
6 of 28
7. 最新版 piwik-fluentd 2.0.2 では
■ Piwik のリアルタイム集計をログから再現できるようになりま
した
□ トラッキングコード(Javascript)を Web サイトに埋め込むことに
より、apache のログでは採取できないサイト来訪者の詳細情報(画
面の解像度など)を Piwik サーバーに送信します。
□ google Analitics のトラッキングコードと同じ役割です。
□ トラッキングコードからのデータは、通常リアルタイム集計され
ます。
■ 従来からトラッキングコードのログから再現できる機能はありま
したが、fluentd に対応させていませんでした
7 of 28
8. リアルタイム集計再現でなにがうれしいのか
■ Piwik アップデート時にリアルタイム集計をとめざるをえない
□ 良くも悪くも、頻繁にアップデートされます(一か月に一度程度)
□ Piwik は MySQL をデータ蓄積につかいます
□ アップデート時にデータベースのカラムを追加することがあります
■ 数千万レコードあるテーブルにカラムを追加されることがあります
□ つまりアップデート時のリアルタイム集計停止は避けられません。
■ MySQL 自体が壊れてリアルタイム集計停止
□ 長時間の稼働停止... 各部署から怒られる、まあ直せばいいけど
□ でも、壊れている間のデータはどうなるの
■ Piwik サーバーのログさえあれば後からなんとかできるのはうれ
しい
8 of 28
9. Piwik ログ取り込みプログラム import logs.py(1)
■ あらゆるログの取り込みを担当
□ piwik/misc/log-analytics/import logs.py
■ ここだけ Python(他は PHP)
■ ログを読み取って、Piwik の API に変換します
□ apache (Urchin 形式含む)、nginx、IIS など
9 of 28
10. Piwik ログ取り込みプログラム import logs.py(2)
■ 指定したファイルをとりこむだけ。気が利いた機能の実装はあり
ません。
□ 複数のサーバーから apache ログを ftp でとってくるとかそんなの
ない。
□ すでに取り込んだファイルはどこかで覚えておかないとならない。
□ 馬鹿でかいログのの途中から取り込む機能はあるが、開始行を指定
しないとなりません。
■ HTTP POST, GET だけとりこんでくれればいいのだがなぜか
フィルタなし。
□ apache のログを取り込む場合です。
□ トラッキングコードのログ取り込み時は piwik.php のログだけを選択
します。
10 of 28
11. 実装することにします
■ ログの管理機能強化
□ 取り込み済ログの識別 → make を使う
□ 複数サーバーからのとりこみ → fluentd を使う
■ 便利オプションの追加
□ HTTP ヘッダ別で取り込みを選択できるように
□ ある時間範囲だけ取り込むように
□ ページビューから除外する拡張子(urchin と実装を同じにできる)
□ ページビューに含む拡張子(urchin と実装を同じにできる)
□ fluentd 形式(json)ファイルの取り込み
■ バグ? の修正
□ apache ログ取り込み時刻を JST になおす
11 of 28
13. Web ログサーバーをつくることにしました(1)
■ ディレクトリ構成
/your_own_path/fluentd/
├ bin (fluentd 対応の import_logs.py、シェルスクリプト)
├ exclude (取り込んではいけない URL パス)
├ log (piwik/console core:archive のログ)
└ td-agent (各サイト毎アクセスログディレクトリ)
├ piwik_tracker (Piwik tracker のアクセスログ)
├ site1(Web サイト 1 のアクセスログ)
├ site2(Web サイト 2)
├ site3(Web サイト 2)
└ site4(Web サイト 2)
13 of 28
14. Web ログサーバーをつくることにしました(2)
■ site[1..N] に fluentd からのアクセスログを取り込みます。
□ piwik tracker には piwik 自身のからのアクセスログです。
■ fluentd の設定は osdn を見てください
□ osdn の例では、16M バイト毎に分割していますが、変更可能です。
■ 複数サイトでも fluentd で楽勝です。
■ 少々停止しても転送してくれます。
14 of 28
15. Web ログサーバーをつくることにしました(3)
■ fluentd からのアクセスログは一定時間毎のバッチで Piwik に取り
込みます。
■ 取り込み完了しているか否かの判定は make に任せます。
□ 新しいファイルは import logs.py にかけられます。
□ ひとつのファイルを取り込みごとに .archive ファイルを作ります
■ このファイルに import logs.py の実行結果が入ります
■ とりこんだ後に集計プロセスを実行しないとなりません
□ import logs.py で取り込んだだけではグラフがでません。
□ バッチの最後に一度だけ、集計プロセスを動かすことにします。
15 of 28
16. ディレクトリ構成をもう少し見てみましょう
■ ディレクトリ構成
/your_own_path/fluentd/
├ bin (fluentd 対応の import logs.py、シェルスクリプト)
├ exclude (取り込んではいけない URL パス)
├ log (piwik/console core:archive のログ)
└ td-agent (各サイト毎アクセスログディレクトリ)
├ piwik_tracker (Piwik tracker のアクセスログ)
├ site1(Web サイト 1 のアクセスログ)
├ site2(Web サイト 2)
├ site3(Web サイト 2)
└ site4(Web サイト 2)
16 of 28
17. 全体的な設定
■ /your own path/fluentd/bin/env.sh
export PIWIK_INSTALL_DIR=/var/www/piwik/
export PIWIK_URL=http://piwik.example.com/
export PIWIK_TOKEN_AUTH=cxxxxxxxxxxxxxxxxxxxxc ← トークン
export PIWIK_BULK_ARCHIVE=1 ← 最後に一度だけ集計プロセス=1
□ import logs.py から Piwik API を叩くための設定
17 of 28
18. 各サイトの設定(1)∼ 集計除外 URL
■ /your own path/fluentd/exclude/exclude idsite1.txt
/robots.txt
/favicon.*
□ 集計除外したいファイルを指定する
□ 数字は siteid です。exclude idsite[siteid].txt
18 of 28
19. 各サイトの設定(2)∼ siteid
■ /your own path/fluentd/td-agent/site1/IDSITE
IDSITE=4
□ td-agent の下のディレクトリ名は実は適当でいいです。
□ ただしディレクトリ名に disable を入れると集計から除外します。例:
site1 disable
□ リアルタイム集計再現のときは IDSITE=0
19 of 28
20. 各サイトの設定(3)∼ 集計済ファイルの退避先
■ /your own path/fluentd/td-agent/site1/MOVECONDITIONS
LEAVEFILES=2000
DESTDIR=done
□ 集計済ファイルが 2000 を超えると td-agent/site1/done に入れます
■ DESTDIR はなければ作成します。
■ ファイルがあまり多いと make でさばきれなくなるのです。
20 of 28
21. 各サイトの設定(4)∼ 時間範囲
■ /your own path/fluentd/td-agent/site1/IMPORTRANGE
IMPORT_START="2015-10-23:0:0:0"
IMPORT_END="infinity"
□ IMPORT START から IMPORT END までのデータを取り込みます。
■ 取り込みが終わっていないファイルが対象です。
■ 時間外のファイルはすべて集計済としますが、取り込みません。
■ IMPORT START, IMPORT END 両方に infinity を指定できます。
■ Piwik が停止していた時刻だけ取り入れることを想定。
21 of 28
23. 開発サーバーとの共用で問題発覚
■ 開発サーバーと共用していて my.cnf で自動変換をお断りしていた
[mysql]
sql_mode="traditional" ← お断りの呪文
■ MySQL の自動変換とは 1
数値 範囲外の数値は頭を押さえつけられる
数値 小数は勝手に丸められる(warning も出ない)
数値 数字以外が入っていると分かるところまでを登録してくれる
文字列 長さを超えると勝手にカットされる
文字列 カラムと異なる文字コードは適当に丸められる
■ 呪文で自動変換をやめさせて、エラーとします
□ 開発時にはエラーとしないとあとから非常に厄介です
1
http://sakaik.hateblo.jp/entry/20100225/mysqlautochange23 of 28
24. 自動変換なし: 文字化け、自動変換お断り: 落ちる
■ パターン 1: UTF-8 前提としたつくりに抵触する
□ サイト検索エンジンキーワードが SJIS または EUC
□ 自サイトの検索キーワードが SJIS または EUC
□ そもそも Piwik トラッカーからのリクエストが文字化け
■ トラッカーからは title 文字列が UTF-8 で送られてきます
■ パターン 2: マルチバイトを前提としたつくりになっていない
□ substr じゃなくて mb substr
□ カラムに合わせて文字列を詰める箇所があるのですが、
□ MySQL の VARCHAR(n) の n はマルチバイトも含めた文字数です。
■ Piwik コミッターがバイト=文字列と思いこんでいる
□ マルチバイトの途中で詰められるともちろん文字化け
24 of 28
25. サイト検索エンジンキーワード
■ piwik/core/DataFiles/SearchEngines.php
// goo
- ’search.goo.ne.jp’ =>
array(’goo’, ’MT’, ’web.jsp?MT=k’),
- ’ocnsearch.goo.ne.jp’ =>
array(’goo’),
+ ’search.goo.ne.jp’ =>
array(’goo’, ’MT’, ’web.jsp?MT=k’,
array(’UTF-8’, ’EUC-JP’, ’MS932’)),
+ ’ocnsearch.goo.ne.jp’ =>
array(’goo’, ’’, ’’,
array(’UTF-8’, ’EUC-JP’, ’MS932’)),
25 of 28
26. Piwik トラッカーからの文字列が文字化け
■ piwik/core/Tracker/PageUrl.php
public static function cleanupString($string)
{
$string = trim($string);
- $string = str_replace(array("n", "r", "0"), ’’, $string);
-
+ if (function_exists(’mb_check_encoding’)
+ && !@mb_check_encoding($string, ’utf-8’, true)
+ ) {
□ mb check encoding の三番目のパラメータが重要
□ It would perform a more thorough check, and the result of that call
would be FALSE.2
2
http://stackoverflow.com/questions/17958226/what-does-mbstring-strict-
detection-do26 of 28
27. マルチバイトを考慮していない
■ piwik/plugins/Referrers/Columns/Keyword.php
$information = $this->getReferrerInformationFromRequest($request);
if (!empty($information[’referer_keyword’])) {
- return substr($information[’referer_keyword’], 0, 255);
+ if (function_exists(’mb_substr’)) {
+ return mb_substr($information[’referer_keyword’], 0, 255, ’UTF-8’
+ } else {
+ return substr($information[’referer_keyword’], 0, 255);
+ }
}
return $information[’referer_keyword’];
□ VARCHAR(255) 制限のために入れたみたいだけど... これはひどい...
27 of 28