kakakakakku blog

Weekly Tech Blog: Keep on Learning!

Rails で簡単に PV を計測できる impressionist を触ってみた

impressionist

Rails で簡単に PV を計測できる Gem の impressionist を触ってみた.

README にも書いてある通り,Google Analytics などの計測ツールを使わなくても自前で PV を集計できる点がメリット.逆に複雑な分析をしたかったり,高トラフィックなサービスなら計測ツールを使うべきかなって感じ.

The goal of this project is to provide customizable stats that are immediately accessible in your application as opposed to using Google Analytics and pulling data using their API.

github.com

導入手順

README の通りで OK!

  • Gemfile に追加して
gem 'impressionist'
  • マイグレーションを流す
bundle install
rails g impressionist
rake db:migrate

impressions テーブル

マイグレーションを流すと impressions テーブルが CREATE される.スキーマはこんな感じ.

アドテク系のプロダクトだと既に impressions っていうテーブルがあったりなかったりwww

CREATE TABLE `impressions` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `impressionable_type` varchar(255) DEFAULT NULL,
  `impressionable_id` int(11) DEFAULT NULL,
  `user_id` int(11) DEFAULT NULL,
  `controller_name` varchar(255) DEFAULT NULL,
  `action_name` varchar(255) DEFAULT NULL,
  `view_name` varchar(255) DEFAULT NULL,
  `request_hash` varchar(255) DEFAULT NULL,
  `ip_address` varchar(255) DEFAULT NULL,
  `session_hash` varchar(255) DEFAULT NULL,
  `message` text,
  `referrer` text,
  `created_at` datetime NOT NULL,
  `updated_at` datetime NOT NULL,
  PRIMARY KEY (`id`),
  KEY `impressionable_type_message_index` (`impressionable_type`,`message`(255),`impressionable_id`),
  KEY `poly_request_index` (`impressionable_type`,`impressionable_id`,`request_hash`),
  KEY `poly_ip_index` (`impressionable_type`,`impressionable_id`,`ip_address`),
  KEY `poly_session_index` (`impressionable_type`,`impressionable_id`,`session_hash`),
  KEY `controlleraction_request_index` (`controller_name`,`action_name`,`request_hash`),
  KEY `controlleraction_ip_index` (`controller_name`,`action_name`,`ip_address`),
  KEY `controlleraction_session_index` (`controller_name`,`action_name`,`session_hash`),
  KEY `index_impressions_on_user_id` (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

設定方法

本当に簡単で README の通りに進めてみた.

1. Controller

計測するコントローラーに以下を設定する.アクションメソッドを限定することもできる.

class AppsController < ApplicationController
  impressionist

or

class AppsController < ApplicationController
  impressionist actions: [:index, :show]

2. Model

show などリソースを特定するアクションメソッドを計測するならモデルに以下を設定する.

class App < ActiveRecord::Base
  is_impressionable
end

3. アクションメソッド

アクションメソッドの中に以下を設定して PV を計測できるようにする.

impressionist(@app)

ただし index など ActiveRecord::Relation を扱うアクションメソッドの場合は何も設定しないこと!逆に設定してしまうと RuntimeError が出てしまう.

impressionist(@apps)
ActiveRecord::Relation is not impressionable!

レコード確認

この状態でリクエストを流すと impressions に自動的に PV が計測される.

ちなみに @current_user にユーザー情報が設定されていると,自動的に impressions.user_id に保存されるのは便利だなと思った.

ザックリとこんなデータになる.ちなみに index の場合は impressionable_id = NULL になる.

mysql> SELECT id, impressionable_type, impressionable_id, user_id, controller_name, action_name, created_at FROM impressions;
+----+---------------------+-------------------+---------+-----------------+-------------+---------------------+
| id | impressionable_type | impressionable_id | user_id | controller_name | action_name | created_at          |
+----+---------------------+-------------------+---------+-----------------+-------------+---------------------+
|  1 | App                 |              NULL |       1 | apps            | index       | 2015-06-19 15:40:52 |
|  2 | App                 |                 1 |       1 | apps            | edit        | 2015-06-19 15:42:24 |
+----+---------------------+-------------------+---------+-----------------+-------------+---------------------+
2 rows in set (0.00 sec)

モデルごとに集計する

モデルオブジェクトから impressionist_count を呼べるようになっていて PV を取得することができる.

日付で絞り込むこともできる.

このメソッドを活用して PV 画面を別で作る感じになる気がする.

pry(main)> @app.impressionist_count
   (0.2ms)  SELECT COUNT(DISTINCT `impressions`.`request_hash`) FROM `impressions` WHERE `impressions`.`impressionable_id` = 1 AND `impressions`.`impressionable_type` = 'App'
=> 5

一覧画面を集計する

index の場合は特に方法が無さそうで,自分で取得すれば良いのかなぁ?

pry(main)> Impression.where(controller_name: :apps, action_name: :index).size
   (0.3ms)  SELECT COUNT(*) FROM `impressions` WHERE `impressions`.`controller_name` = 'apps' AND `impressions`.`action_name` = 'index'
=> 3

まとめ

  • お手軽に PV を計測できる
  • 可視化などは全て自前で実装する必要がある
  • リクエストの中で MySQL or MongoDB にレコードが挿入されるし,ある程度リクエスト数が多くなると厳しそう
  • もしくは任意の期間でレコードを削除するバッチと併用する?

関連エントリー