piwik fluentd at osc tokyo 2015 fall
TRANSCRIPT
Piwik + flutned で 100 万 pv/month サイトのログ解析
YAMAMOTO [email protected]
Piwik Japan
OSC Tokyo fallOct 25, 2015
すでに公開しています■ Piwik Japan ユーザー会■ http://www.piwikjapan.org/
■ osdn https://osdn.jp/projects/piwik-fluentd/
■ Piwik osdn で検索するとでます。■ 細かい設定はすべてこちらに記述しています。■ 日本語問題のパッチもここに置いています。
2 of 28
ひとつ前のバージョンに対応しています■ Piwik 2.6.0 - Piwik 2.14.3
■ 2.14.3 は 2015/8 に公開■ 最新といいたかったんだけど 2.15.0 がおととい(2015/10/21)にでてしまいました...
3 of 28
その前に
4 of 28
なぜ Piwik なのか■ Urchin がなくなった
□ google に買収され、現在は google Analytics になった□ アプリケーションであり google にデータを渡すことなく自前でログ解析ができた
■ ID を分けて、担当の Web サイト以外の集計は見せないようしたい
■ google にアクセスログ渡したくない■ Open Source でログが取り込めるのは Piwik だけ
□ もちろん他もあるけどどれも開発はだいぶ前に終了、今からみれば低機能
5 of 28
Piwik fluentd で何ができるのか■ apache のログを Piwik にとりこみます■ ログは fluentd 形式です
□ 標準では対応していません
■ ついでに、日本語文字コード関連の問題の解決
6 of 28
最新版 piwik-fluentd 2.0.2 では■ Piwik のリアルタイム集計をログから再現できるようになりました□ トラッキングコード(Javascript)を Web サイトに埋め込むことにより、apache のログでは採取できないサイト来訪者の詳細情報(画面の解像度など)を Piwik サーバーに送信します。
□ google Analitics のトラッキングコードと同じ役割です。□ トラッキングコードからのデータは、通常リアルタイム集計されます。
■ 従来からトラッキングコードのログから再現できる機能はありましたが、fluentd に対応させていませんでした
7 of 28
リアルタイム集計再現でなにがうれしいのか■ Piwik アップデート時にリアルタイム集計をとめざるをえない
□ 良くも悪くも、頻繁にアップデートされます(一か月に一度程度)□ Piwik は MySQL をデータ蓄積につかいます□ アップデート時にデータベースのカラムを追加することがあります
■ 数千万レコードあるテーブルにカラムを追加されることがあります□ つまりアップデート時のリアルタイム集計停止は避けられません。
■ MySQL 自体が壊れてリアルタイム集計停止□ 長時間の稼働停止... 各部署から怒られる、まあ直せばいいけど□ でも、壊れている間のデータはどうなるの
■ Piwik サーバーのログさえあれば後からなんとかできるのはうれしい
8 of 28
Piwik ログ取り込みプログラム import logs.py(1)■ あらゆるログの取り込みを担当
□ piwik/misc/log-analytics/import logs.py
■ ここだけ Python(他は PHP)■ ログを読み取って、Piwik の API に変換します
□ apache (Urchin 形式含む)、nginx、IIS など
9 of 28
Piwik ログ取り込みプログラム import logs.py(2)■ 指定したファイルをとりこむだけ。気が利いた機能の実装はありません。□ 複数のサーバーから apache ログを ftp でとってくるとかそんなのない。
□ すでに取り込んだファイルはどこかで覚えておかないとならない。□ 馬鹿でかいログのの途中から取り込む機能はあるが、開始行を指定しないとなりません。
■ HTTP POST, GET だけとりこんでくれればいいのだがなぜかフィルタなし。□ apache のログを取り込む場合です。□ トラッキングコードのログ取り込み時は piwik.php のログだけを選択します。
10 of 28
実装することにします■ ログの管理機能強化
□ 取り込み済ログの識別 → make を使う□ 複数サーバーからのとりこみ → fluentd を使う
■ 便利オプションの追加□ HTTP ヘッダ別で取り込みを選択できるように□ ある時間範囲だけ取り込むように□ ページビューから除外する拡張子(urchin と実装を同じにできる)□ ページビューに含む拡張子(urchin と実装を同じにできる)□ fluentd 形式(json)ファイルの取り込み
■ バグ? の修正□ apache ログ取り込み時刻を JST になおす
11 of 28
fluentd はほんとよくできてます■ こんなことが便利です
□ 複数サイトからログを集約できる□ 接続断でも、復活後追いかけてくれる□ ファイルの分割機能
12 of 28
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
Web ログサーバーをつくることにしました(2)■ site[1..N] に fluentd からのアクセスログを取り込みます。
□ piwik tracker には piwik 自身のからのアクセスログです。■ fluentd の設定は osdn を見てください
□ osdn の例では、16M バイト毎に分割していますが、変更可能です。
■ 複数サイトでも fluentd で楽勝です。■ 少々停止しても転送してくれます。
14 of 28
Web ログサーバーをつくることにしました(3)■ fluentd からのアクセスログは一定時間毎のバッチで Piwik に取り込みます。
■ 取り込み完了しているか否かの判定は make に任せます。□ 新しいファイルは import logs.py にかけられます。□ ひとつのファイルを取り込みごとに .archive ファイルを作ります
■ このファイルに import logs.py の実行結果が入ります
■ とりこんだ後に集計プロセスを実行しないとなりません□ import logs.py で取り込んだだけではグラフがでません。□ バッチの最後に一度だけ、集計プロセスを動かすことにします。
15 of 28
ディレクトリ構成をもう少し見てみましょう■ ディレクトリ構成
/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
全体的な設定■ /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
各サイトの設定(1)∼ 集計除外 URL■ /your own path/fluentd/exclude/exclude idsite1.txt
/robots.txt
/favicon.*
□ 集計除外したいファイルを指定する□ 数字は siteid です。exclude idsite[siteid].txt
18 of 28
各サイトの設定(2)∼ siteid■ /your own path/fluentd/td-agent/site1/IDSITE
IDSITE=4
□ td-agent の下のディレクトリ名は実は適当でいいです。□ ただしディレクトリ名に disable を入れると集計から除外します。例:
site1 disable□ リアルタイム集計再現のときは IDSITE=0
19 of 28
各サイトの設定(3)∼ 集計済ファイルの退避先■ /your own path/fluentd/td-agent/site1/MOVECONDITIONS
LEAVEFILES=2000
DESTDIR=done
□ 集計済ファイルが 2000 を超えると td-agent/site1/done に入れます■ DESTDIR はなければ作成します。■ ファイルがあまり多いと make でさばきれなくなるのです。
20 of 28
各サイトの設定(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
Piwik 日本語問題
22 of 28
開発サーバーとの共用で問題発覚■ 開発サーバーと共用していて my.cnf で自動変換をお断りしていた
[mysql]
sql_mode="traditional" ← お断りの呪文
■ MySQL の自動変換とは 1
数値 範囲外の数値は頭を押さえつけられる数値 小数は勝手に丸められる(warningも出ない)数値 数字以外が入っていると分かるところまでを登録してくれる
文字列 長さを超えると勝手にカットされる文字列 カラムと異なる文字コードは適当に丸められる
■ 呪文で自動変換をやめさせて、エラーとします□ 開発時にはエラーとしないとあとから非常に厄介です
1http://sakaik.hateblo.jp/entry/20100225/mysqlautochange23 of 28
自動変換なし: 文字化け、自動変換お断り: 落ちる■ パターン 1: UTF-8 前提としたつくりに抵触する
□ サイト検索エンジンキーワードが SJIS または EUC□ 自サイトの検索キーワードが SJIS または EUC□ そもそも Piwik トラッカーからのリクエストが文字化け
■ トラッカーからは title 文字列が UTF-8 で送られてきます
■ パターン 2: マルチバイトを前提としたつくりになっていない□ substr じゃなくて mb substr□ カラムに合わせて文字列を詰める箇所があるのですが、□ MySQL の VARCHAR(n) の n はマルチバイトも含めた文字数です。
■ Piwik コミッターがバイト=文字列と思いこんでいる□ マルチバイトの途中で詰められるともちろん文字化け
24 of 28
サイト検索エンジンキーワード■ 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
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
2http://stackoverflow.com/questions/17958226/what-does-mbstring-strict-detection-do26 of 28
マルチバイトを考慮していない■ 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
ブースは 202 です。ロシアの飴ちゃん配ってます。
28 of 28