VRFS-925 ga event processing

This commit is contained in:
Jonathan Kolyer 2014-03-09 13:38:46 +00:00
parent 5abc877a38
commit 2b11cb7abb
9 changed files with 207 additions and 25 deletions

View File

@ -130,3 +130,4 @@ scores_better_test_data.sql
connection_client_type.sql
add_countries_regions_and_cities.sql
plays_refactor.sql
bands_did_session.sql

View File

@ -0,0 +1,2 @@
ALTER TABLE bands ADD COLUMN did_real_session boolean default false;

View File

@ -258,6 +258,12 @@ module JamRuby
name
end
def in_real_session?(session)
b_members = self.users.sort_by(&:id).map(&:id)
s_members = session.users.sort_by(&:id).map(&:id)
(b_members - s_members).blank?
end
private
def require_at_least_one_genre

View File

@ -18,6 +18,7 @@ module JamRuby
validate :can_join_music_session, :if => :joining_session?
after_save :require_at_least_one_track_when_in_session, :if => :joining_session?
after_create :did_create
before_save :report_add_participant
include AASM
IDLE_STATE = :idle
@ -127,6 +128,17 @@ module JamRuby
self.user.update_lat_lng(self.ip_address) if self.user && self.ip_address
end
def report_add_participant
if self.music_session_id_changed? &&
self.music_session.present? &&
self.connected? &&
self.as_musician? &&
0 < (count = self.music_session.connected_participant_count)
GoogleAnalyticsEvent.report_session_participant(count)
end
true
end
private
def require_at_least_one_track_when_in_session
if tracks.count == 0

View File

@ -24,6 +24,8 @@ module JamRuby
has_many :recordings, :class_name => "JamRuby::Recording", :inverse_of => :music_session
belongs_to :band, :inverse_of => :music_sessions, :class_name => "JamRuby::Band", :foreign_key => "band_id"
after_create :started_session
validate :require_at_least_one_genre, :limit_max_genres
after_save :sync_music_session_history
@ -400,6 +402,18 @@ module JamRuby
self.save!(:validate => false)
end
def connected_participant_count
Connection.where(:music_session_id => self.id,
:aasm_state => Connection::CONNECT_STATE.to_s,
:as_musician => true)
.count
end
def started_session
GoogleAnalyticsEvent.track_session_duration(self)
GoogleAnalyticsEvent.track_band_real_session(self)
end
private
def require_at_least_one_genre

View File

@ -28,6 +28,7 @@ module JamRuby
before_save :sanitize_active_admin
before_create :add_to_feed
after_create :check_first_band_recording
def add_to_feed
feed = Feed.new
@ -39,6 +40,11 @@ module JamRuby
self.band_id = nil if self.band_id == ''
end
def check_first_band_recording
GoogleAnalyticsEvent.report_band_recording(self.band)
true
end
def comment_count
self.comments.size
end

View File

@ -1,43 +1,108 @@
class GoogleAnalyticsEvent
require 'resque'
@queue = 'google_analytics_event'
module JamRuby
class GoogleAnalyticsEvent
@@log = Logging.logger[GoogleAnalyticsEvent]
@queue = :google_analytics_event
def self.perform(category, action)
CAT_SESS_SIZE = 'SessionSize'
ACTION_SESS_SIZE = 'Size'
CAT_SESS_DUR = 'SessionDuration'
ACTION_SESS_DUR = 'Duration'
CAT_BAND = 'Band'
ACTION_BAND_SESS = 'Session'
ACTION_BAND_REC = 'Recording'
@@log.info("starting (#{category}, #{action})")
@@log = Logging.logger[GoogleAnalyticsEvent]
run(category, action)
SESSION_INTERVALS = [1, 5, 10, 15, 30, 45, 60, 90, 120, 180] # minutes
QUEUE_SESSION_TRACKER = :session_tracker
@@log.info("done (#{category}, #{action})")
class SessionDurationTracker
@queue = QUEUE_SESSION_TRACKER
end
def self.enqueue(category, event)
begin
Resque.enqueue(AudioMixer, category, event)
true
rescue
# implies redis is down. but since there is no retry logic with this, we should at least log a warn in case we've configured something wrong
@@log.warn("unable to enqueue")
false
def self.perform(session_id, interval_idx)
return unless session = MusicSession.find(session_id)
interval_idx += 1
GoogleAnalyticsEvent.enqueue(CAT_SESS_DUR, ACTION_SESS_DUR, interval_idx)
if SESSION_INTERVALS.count-1 > interval_idx
next_time = session.created_at + SESSION_INTERVALS[interval_idx].minutes
Resque.enqueue_at(next_time,
self,
:session_id => session_id,
:interval_idx => interval_idx)
end
end
end
end
def self.run(category, action)
class BandSessionTracker
@queue = QUEUE_SESSION_TRACKER
raise "no google analytics tracking ID" unless APP_CONFIG.ga_ua
def self.perform(session_id)
return unless session = MusicSession.find(session_id)
band = session.band
if band.in_real_session(session)?
GoogleAnalyticsEvent.enqueue(CAT_BAND, ACTION_BAND_SESS)
band.update_attributes!(did_real_session: true)
end if band
end
end
params = {
def self.track_session_duration(session)
Resque.enqueue_at(SESSION_INTERVALS[0].minute.from_now,
SessionDurationTracker,
:session_id => session.id,
:interval_idx => 0)
end
BAND_SESSION_MIN_DURATION = 15 # minutes
def self.track_band_real_session(session)
if session.band && !session.band.did_real_session?
Resque.enqueue_at(BAND_SESSION_MIN_DURATION.minutes.from_now,
BandSessionTracker,
:session_id => session.id)
end
end
def self.report_band_recording(band)
if band && 1 == Recording.where(:band_id => band.id).count
self.enqueue(CAT_BAND, ACTION_BAND_REC)
end
end
def self.report_session_participant(participant_count)
self.enqueue(CAT_SESS_SIZE, ACTION_SESS_SIZE, participant_count)
end
def self.enqueue(category, event, data=nil)
begin
Resque.enqueue(GoogleAnalyticsEvent, category, event, data)
true
rescue
# implies redis is down. but since there is no retry logic with this, we should at least log a warn in case we've configured something wrong
@@log.warn("unable to enqueue")
false
end
end
def self.perform(category, action, data)
@@log.info("starting (#{category}, #{action})")
raise "no google analytics tracking ID" unless APP_CONFIG.ga_ua
params = {
v: APP_CONFIG.ga_ua_version,
tid: APP_CONFIG.ga_ua,
cid: APP_CONFIG.ga_anonymous_client_id,
t: "event",
ec: category,
ea: action
}
ea: action,
el: 'data',
ev: data.to_s
}
RestClient.post(APP_CONFIG.ga_endpoint, params: params, timeout: 8, open_timeout: 8)
@@log.info("done (#{category}, #{action})")
end
RestClient.post(APP_CONFIG.ga_endpoint, params: params, timeout: 8, open_timeout: 8)
end
end
end

View File

@ -0,0 +1,49 @@
require 'spec_helper'
# these tests avoid the use of ActiveRecord and FactoryGirl to do blackbox, non test-instrumented tests
describe GoogleAnalyticsEvent do
let(:ga) { GoogleAnalyticsEvent.new }
describe "report session participant" do
it "queues job when session participant joins" do
pending
end
end
describe "track session duration" do
it "queues jobs for session duration intervals" do
pending
end
it "stop queueing jobs if session is deleted" do
pending
end
end
describe "track band real session" do
it "queues jobs for band real session tracking" do
pending
end
it "stop queueing jobs if band session is deleted" do
pending
end
it "updates band real session attributes" do
pending
end
end
describe "report band recording" do
it "queues job when first band recording is made" do
pending
end
it "does not queues job when band has a recording already" do
pending
end
end
end

View File

@ -64,6 +64,7 @@ Spork.prefork do
#
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
RSpec.configure do |config|
config.color_enabled = true
config.treat_symbols_as_metadata_keys_with_true_values = true
config.run_all_when_everything_filtered = true
@ -101,6 +102,32 @@ Spork.prefork do
# the seed, which is printed after each run.
# --seed 1234
config.order = 'random'
REDIS_PID = "#{Rails.root}/tmp/pids/redis-test.pid"
REDIS_CACHE_PATH = "#{Rails.root}/tmp/cache/"
config.before(:suite) do
redis_options = {
"daemonize" => 'yes',
"pidfile" => REDIS_PID,
"port" => 9736,
"timeout" => 300,
"save 900" => 1,
"save 300" => 1,
"save 60" => 10000,
"dbfilename" => "dump.rdb",
"dir" => REDIS_CACHE_PATH,
"loglevel" => "debug",
"logfile" => "stdout",
"databases" => 16
}.map { |k, v| "#{k} #{v}" }.join("\n")
`echo '#{redis_options}' | redis-server -`
end
config.after(:suite) do
%x{
cat #{REDIS_PID} | xargs kill -QUIT
rm -f #{REDIS_CACHE_PATH}dump.rdb
}
end
end
end