トップページに戻る

#osc16ep OSC 2016 Tokyo enterprise で発表しました

Piwik を elasticsearch + kibana で可視化してみる

Piwik の集計は、Web サイトに組みこんだ JavaScript (Piwik トラッカー)が Piwik に閲覧データを送ることで行われます。 これは普通に get メソッドで、アクセスログにこのような形で記録されます。

114.198.0.0 - - [16/Aug/2016:11:28:32 +0900] "GET /piwik/piwik.php?action_name=%E8%87%AA%E5%88%86%E8%BC%9D%E3%81%8F%E7%99%92%E3%82%84%E3%81%97%E3%81%AE%E3%82%BB%E3%83%AB%E3%83%95%E3%83%8A%E3%83%93%E3%80%80%20%E3%82%AF%E3%82%A9%E3%83%B3%E3%82%BF%E3%83%A0%E3%82%BF%E3%83%83%E3%83%81%20%E3%83%9A%E3%83%B3%E3%82%B8%E3%83%A5%E3%83%A9%E3%83%A0%E3%80%80%E3%83%81%E3%83%A3%E3%82%AF%E3%83%A9%E3%80%80%20%E3%83%92%E3%83%BC%E3%83%AA%E3%83%B3%E3%82%B0%E3%80%80%E9%9F%B3%E5%8F%89%E3%80%80%E3%82%AF%E3%83%AA%E3%82%B9%E3%82%BF%E3%83%AB%20-%20%E6%9C%80%E6%96%B0%E3%82%A8%E3%83%B3%E3%83%88%E3%83%AA%E3%83%BC&idsite=2&rec=1&r=373294&h=11&m=28&s=32&url=http%3A%2F%2Fselfnavi.com%2Fmodules%2Fd3blog%2F&urlref=http%3A%2F%2Fselfnavi.com%2Fmodules%2Fpico%2Findex.php%2Fcategory0012.html&_id=f410f1a3c7a06a3a&_idts=1466345456&_idvc=2&_idn=0&_refts=1471313709&_viewts=1471313709&_ref=http%3A%2F%2Fsearch.yahoo.co.jp%2Fsearch%3B_ylt%3DA2RADIUEd7JXSE0ACMjMFvR7%3Fp%3D%E3%82%BB%E3%83%AB%E3%83%95%E3%83%8A%E3%83%93%E5%B1%B1%E6%9C%AC%E7%9C%9F%E6%BE%84%26search.x%3D1%26fr%3Dtop_ga1_sa%26tid%3Dtop_ga1_sa%26ei%3DUTF-8%26aq%3D%26oq%3D%26afs%3D&send_image=1&pdf=0&qt=0&realp=0&wma=0&dir=0&fla=1&java=1&gears=0&ag=1&cookie=1&res=1366x768&gt_ms=84 HTTP/1.1" 200 43 "http://selfnavi.com/modules/d3blog/" "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko"
Piwik から get メソッドを解釈してさまざまな角度から分析ができますが、ここでは、このログを elasticsearch いれて kibana で見てみようという話です。

可視化までのデータフロー

  1. Piwik トラッカーから Piwik サーバーをたたくが(通常はここで Piwik が集計)
  2. Piwik サーバーの apacne/nginx (ここでは apache) ログを fluentd で加工
  3. fluentd で加工後、elasticsearch にストア
  4. kibana で可視化

Today's goal

Piwik トラッカーは何を Piwik に送るのか

JavaScript でわざわざ用意されているだけあって、通常の Web アクセスログ以上のデータを Piwik トラッカーは送ります。

普通の Web アクセスログとして記録されます

  • Client IP, User agent, referer

Piwik トラッカーが追加で記録します

piwik.php の get パラメータで送信されます。

  • idsite : Piwik で集計しているのはどの Web サイトか?(Piwik 管理画面->ID の数値)
  • action_name : 見られた Web ページのタイトル
  • _id : クライアント固有 ID
  • res : クライアント PC の画面解像度
  • pdf : クラアイント Web ブラウザに pdf プラグインが入っている?
  • java : クラアイント Web ブラウザに java プラグインが入っている?
  • fla : クラアイント Web ブラウザに flash プラグインが入っている?
  • cookie : クラアイント Web ブラウザは cookie を受け付ける?
  • _viewts : 前回訪問時間

他にもあります Tracking HTTP API

追加インストール、ポートの確認

Piwik が動いているサーバーに td-agent(fluentd) と elasticsearch, kibana を追加インストールします。

td-agent(fluentd)

  1. Piwik サーバーのアクセスログ(/var/log/httpd/access_log)を常に tail し Piwik トラッカー(piwik.php get)のリクエストだけを抽出、get パラメータを分解します。
  2. url encode されているパラメータがあれば decode します。
  3. クライアントの IP アドレスを GeoIP を使い、緯度、経度を出します。
  4. 分解、加工した Piwik トラッカーデータを elasticsearch に投げます。

インストール

ここより td-agent のパッケージを作りインストールします。 素の状態から次の td-agent プラグインを追加しなければなりません。

  • fluent-plugin-elasticsearch
  • fluent-plugin-record-reformer
  • fluent-plugin-uri_decoder
  • fluent-plugin-geoip

elasticsearch

  1. td-agent(fluentd) から送られてくる Piwik トラッカーデータを受け付け、蓄えます。
インストール

以下 root で

# rpm --import https://packages.elastic.co/GPG-KEY-elasticsearch
# vim /etc/yum.repos.d/elasticsearch.repo

/etc/yum.repos.d/elasticsearch.repo を新規作成します:

[elasticsearch-2.x]
name=Elasticsearch repository for 2.x packages
baseurl=http://packages.elastic.co/elasticsearch/2.x/centos
gpgcheck=1
gpgkey=http://packages.elastic.co/GPG-KEY-elasticsearch
enabled=1

java 1.8 とともにインストール

# yum install java-1.8.0
# yum install elasticsearch
action_name(見られた Web ページのタイトル)を日本語全文検索できるよう日本語 index を作成します。 構文解析のために kuromoji をプラグインを追加します。
# /usr/share/elasticsearch/bin/plugin install analysis-kuromoji

kibana

  1. elasticsearch に蓄えられた Piwik トラッカーデータを可視化します。

インストール

以下 root で /etc/yum.repos.d/kibana.repo を作成します:

[kibana-4.5]
name=Kibana repository for 4.5.x packages
baseurl=http://packages.elastic.co/kibana/4.5/centos
gpgcheck=1
gpgkey=http://packages.elastic.co/GPG-KEY-elasticsearch
enabled=1

kibana をインストールします:

# groupadd kibana
# useradd kibana -s /sbin/nologin -b /home/elasticsearch
# yum install kibana
# touch /opt/kibana/optimize/.babelcache.json
# chown kibana:kibana /opt/kibana/optimize/.babelcache.json

必要ポートを解放します

kibana Web インターフェース

$ sudo firewall-cmd --permanent --zone=public --add-port=5601/tcp

td-agent(fluentd)に外のサーバーからログを送り込む場合

$ sudo firewall-cmd --permanent --zone=public --add-port=24224/tcp
$ sudo firewall-cmd --permanent --zone=public --add-port=24224/udp

確認

  • http, https はすでにあけてあります。
    $ sudo  firewall-cmd --list-all
    public (default, active)
      interfaces: eth0
      sources:
      services: dhcpv6-client http https ssh
      ports: 24224/udp 5601/tcp 24224/tcp
      masquerade: no
      forward-ports:
      icmp-blocks:
      rich rules:
    

アクセスログを td-agent から読めるようにします

$ sudo chmod 775 /var/log/httpd/

/etc/td-agent/td-agent.conf の配置

ここより td-agent.conf をダウンロードして、/etc/td-agent にコピーします。

$ pushd .
$ cd /etc/td-agent
[td-agent] $ sudo mv td-agent.conf td-agent.conf.orig
$ popd
$ sudo cp  td-agent.conf /etc/td-agent

elasticsearch に Piwik トラッカーデータのスキーマ(テンプレートという)を作ります

elasticsearch はスキーマレスなのに、なんで? なのですが、 fluent-plugin-elasticsearch から elasticsearch に投げられるデータは、 指定されない限りすべて string 扱い になってしまうのです。というわけで string 以外のデータストアは td-agent.conf か、elasticsearch 側で型を指定しないとなりません。どっちでもいいのですが、今回は下記の理由により elasticsearch 側で型を指定します:

  • kuromoji を使って日本語 index を作りたい
  • データ肥大化を避けるため元データは蓄えない

では作成します

  1. ここより piwik-template.json をダウンロードします。
  2. elasticsearch を立ち上げます
    $ sudo service elasticsearch start
    
  3. テンプレートを投入
    $ curl -XPUT localhost:9200/_template/piwik-template -d "`cat piwik-template.json`" 
    

確認

  • テンプレート一覧
    $ curl -XGET http://127.0.0.1:9200/_template/*?pretty=true
    
  • テンプレート削除
    $ curl -XDELETE http://127.0.0.1:9200/_template/piwik-template?pretty=true
    

elasticsearch へ Piwik トラッカーデータをストア開始

  1. 立ち上げます
    $ sudo service elasticsearch start
    $ sudo service td-agent start
    $ sudo kibana start
    
  2. 集計対象の Web を Web ブラウザで見ます、常に客が入ってくる Web サイトならそのまま放っておく
  3. kibana で可視化されたデータを見る

トラブル時は

確認すべきログ

  • /var/log/kibana/kibana.stderr
  • /var/log/elasticsearch/elasticsearch.log
  • /var/log/messages
  • /var/log/td-agent/access_log.pos

elasticsearch に本当にデータが転送されているか?

  1. /etc/td-agent/td-agent.conf で下記の箇所、 # を消去します
    <match piwiktracker.apache.access.store>
        type copy
        <store>
            type elasticsearch
            type_name access_log
            host 127.0.0.1
            port 9200
            logstash_format true
            logstash_prefix apache-log
            logstash_dateformat %Y%m%d
            include_tag_key true
            tag_key @log_name
            flush_interval 10s
        </store>
    #    <store>
    #        type file
    #        path /tmp/fluentd-debug.log
    #    </store>
    </match>
    
  2. td-agent を再起動します
    $ sudo service td-agent stop
    $ sudo service td-agent start
    
  3. elasticsearch ストアされるデータと同じものが /tmp/fluentd-debug.log* に書き込まれます。

elasticsearch も td-agent もエラーなしで起動しているけどうまく動いてくれない

  1. Piwik サーバーの Web アクセスログを拾う の、/var/log/httpd/access_log が実際にあるか?
    • なければ、Piwik Web アクセスログが記録されているファイル名に変更
    • あれば、/var/log/httpd/access_log に td-agent:td-agent でアクセスできるか?とくに /var/log/httpd/ のパーミッションは要注意
  2. Piwik トラッカーログだけを抽出 で regexp1 正規表現できちんと Piwik トラッカーのログを拾えているのかどうか確認