Google Analytics API はそこそこ遅い
Google Analytics APIを使ったことがある人なら「結果帰ってくるの遅いなあ…」とぼやいたことあると思います。
速くするためには期間で絞り込みする、ディメンション(指標)を複雑にしない、結果件数を絞り込む(10件とか)、gzipの指定をする。の方法がありますが、これらを行っても遅いものは遅いのです。
Legato 使っても当然そこそこ遅い
RubyからGoogeAnalyticsAPIを使うには"Legato"がとても便利です。
使い方の説明は同じQiita内の以下記事をご確認ください。
Legato中でOAuth認証とGoogleAnalyticsAPIのエンドポイントへアクセスしているので、当たり前ですがそこそこ遅いです。
クエリー結果をキャッシュする
どのレイヤーでキャッシュするのか?を考えた時にアプリケーションのビューやモデル内も考えられますが、もっとも広範囲で恩恵を得られるのはLegatoの中です。
そういう事でLegato内でクエリー結果をキャッシュする事で高速化を図りましょう。
キャッシュするモンキーパッチ
Railsアプリ内から使うサンプルコードです。以下パスでLegatoに簡易パッチを当てます。
config/initializers/legato_ext.rb
#
# patch on Ver 0.6.2
# https://github.com/tpitale/legato/blob/169d806f9486fed3aceb61a7e42dc04a1c405fcc/lib/legato/request.rb
#
module Legato
class Request
def cache_url
query.base_url + query_string
end
def cache_key
prefix = self.class.name.underscore
[prefix, Digest::MD5.hexdigest(user.access_token.token + cache_url)].join("/_/")
end
def cache_log
Rails.logger.info("Cache Legato::Request. key=" + cache_key + ", url=" + cache_url + ", token=#{user.access_token.token}")
end
def get(*args)
raw_response = Rails.cache.fetch(cache_key, expires_in: 8.hours){
cache_log
user.access_token.get(*args)
}
end
end
end
#
# patch on Ver 0.6.2
# https://github.com/tpitale/legato/blob/169d806f9486fed3aceb61a7e42dc04a1c405fcc/lib/legato/management/finder.rb
#
module Legato
module Management
module Finder
def cache_key(user, uri)
Digest::MD5.hexdigest(user.access_token.token + uri)
end
def cache_log(user, uri)
Rails.logger.info("Cache Legato::Management::Finder. key=" + cache_key(user, uri) + ", uri=" + uri + ", token=#{user.access_token.token}")
end
def all(user, path=default_path)
uri = base_uri + path
json = Rails.cache.fetch(cache_key(user, uri), expires_in: 10.minutes){
cache_log(user, uri)
user.access_token.get(uri).body
}
items = MultiJson.decode(json).fetch('items', [])
items.map {|item| new(item, user)}
end
end
end
end
キャッシュを有効にしていない場合は以下のようにcache_storeを指定します。Gemfileにもキャッシュストアを指定します。
ここでは MemCached + Dalli にしています。
Rails.application.configure do
#...省略
config.cache_store = :mem_cache_store, "127.0.0.1:11211"
end
gem 'dalli'
コードの説明
このコードでは以下の2つを行っています。
- クエリー結果(Core Reporting API)のレスポンスをキャッシュ
- メタ情報(Management API)のレスポンスをキャッシュ
キャッシュキーにアクセストークンとURLを組み合わせた文字列を使うことでセッション違いの同一クエリーと被らないようにしています。
あとLegatoのコードがリファクタリングされて読みやすくなっていました。これならパッチを当てるのもスムーズです。
参照情報
- Legato
- https://github.com/tpitale/legato
- Google Analytics API リファレンス
- https://developers.google.com/analytics/?hl=ja
- Dalli
- https://github.com/petergoldstein/dalli
- Memcached
- http://memcached.org/
さいごに
質問などあればコメントにお願いします。直接メッセージをしたい方はTwitter宛にお願いします。