* wip
This commit is contained in:
parent
7ca3acb676
commit
786486026b
|
|
@ -72,6 +72,8 @@ gem 'iso-639'
|
||||||
gem 'rubyzip'
|
gem 'rubyzip'
|
||||||
gem 'sanitize'
|
gem 'sanitize'
|
||||||
gem 'slim'
|
gem 'slim'
|
||||||
|
gem 'influxdb', '0.1.8'
|
||||||
|
gem 'influxdb-rails', '0.1.10'
|
||||||
|
|
||||||
group :libv8 do
|
group :libv8 do
|
||||||
gem 'libv8', "~> 3.11.8"
|
gem 'libv8', "~> 3.11.8"
|
||||||
|
|
|
||||||
|
|
@ -139,5 +139,13 @@ module JamAdmin
|
||||||
config.recurly_private_api_key = '7d623daabfc2434fa2a893bb008eb3e6'
|
config.recurly_private_api_key = '7d623daabfc2434fa2a893bb008eb3e6'
|
||||||
# Use Public Keys to identify your site when using Recurly.js. See https://docs.recurly.com/js/#include to learn more.
|
# Use Public Keys to identify your site when using Recurly.js. See https://docs.recurly.com/js/#include to learn more.
|
||||||
config.recurly_public_api_key = 'sc-SZlO11shkeA1WMGuISLGg5'
|
config.recurly_public_api_key = 'sc-SZlO11shkeA1WMGuISLGg5'
|
||||||
|
|
||||||
|
# these values work out of the box with default settings of an influx install (you do have to add a development database by hand though)
|
||||||
|
config.influxdb_database = "development"
|
||||||
|
config.influxdb_username = "root"
|
||||||
|
config.influxdb_password = "root"
|
||||||
|
config.influxdb_hosts = ["localhost"]
|
||||||
|
config.influxdb_port = 8086
|
||||||
|
config.influxdb_ignored_environments = ENV["INFLUXDB_ENABLED"] == '1' ? ['test', 'cucumber'] : ['test', 'cucumber', 'development']
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
require File.expand_path('../application', __FILE__)
|
require File.expand_path('../application', __FILE__)
|
||||||
|
|
||||||
APP_CONFIG = Rails.application.config
|
APP_CONFIG = Rails.application.config
|
||||||
|
Stats.client = InfluxDB::Rails.client
|
||||||
|
|
||||||
# Initialize the rails application
|
# Initialize the rails application
|
||||||
JamAdmin::Application.initialize!
|
JamAdmin::Application.initialize!
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
InfluxDB::Rails.configure do |config|
|
||||||
|
config.influxdb_database = Rails.application.config.influxdb_database
|
||||||
|
config.influxdb_username = Rails.application.config.influxdb_username
|
||||||
|
config.influxdb_password = Rails.application.config.influxdb_password
|
||||||
|
config.influxdb_hosts = Rails.application.config.influxdb_hosts
|
||||||
|
config.influxdb_port = Rails.application.config.influxdb_port
|
||||||
|
config.ignored_environments = Rails.application.config.influxdb_ignored_environments
|
||||||
|
config.async = true
|
||||||
|
config.debug = false
|
||||||
|
config.logger = Logging.logger['InfluxDB']
|
||||||
|
|
||||||
|
config.series_name_for_controller_runtimes = "admin.rails.controller"
|
||||||
|
config.series_name_for_view_runtimes = "admin.rails.view"
|
||||||
|
config.series_name_for_db_runtimes = "admin.rails.db"
|
||||||
|
end
|
||||||
|
|
@ -91,6 +91,7 @@ Logging::Rails.configure do |config|
|
||||||
#
|
#
|
||||||
Logging.logger.root.level = config.log_level
|
Logging.logger.root.level = config.log_level
|
||||||
Logging.logger.root.appenders = config.log_to unless config.log_to.empty?
|
Logging.logger.root.appenders = config.log_to unless config.log_to.empty?
|
||||||
|
Logging.logger['InfluxDB'].level = :warn
|
||||||
|
|
||||||
# Under Phusion Passenger smart spawning, we need to reopen all IO streams
|
# Under Phusion Passenger smart spawning, we need to reopen all IO streams
|
||||||
# after workers have forked.
|
# after workers have forked.
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,7 @@ gem 'rest-client'
|
||||||
gem 'iso-639'
|
gem 'iso-639'
|
||||||
gem 'rubyzip'
|
gem 'rubyzip'
|
||||||
gem 'sanitize'
|
gem 'sanitize'
|
||||||
|
gem 'influxdb', '0.1.8'
|
||||||
|
|
||||||
group :test do
|
group :test do
|
||||||
gem 'simplecov', '~> 0.7.1'
|
gem 'simplecov', '~> 0.7.1'
|
||||||
|
|
|
||||||
|
|
@ -38,10 +38,10 @@ require "jam_ruby/lib/json_validator"
|
||||||
require "jam_ruby/lib/em_helper"
|
require "jam_ruby/lib/em_helper"
|
||||||
require "jam_ruby/lib/nav"
|
require "jam_ruby/lib/nav"
|
||||||
require "jam_ruby/lib/html_sanitize"
|
require "jam_ruby/lib/html_sanitize"
|
||||||
|
require "jam_ruby/resque/resque_hooks"
|
||||||
require "jam_ruby/resque/audiomixer"
|
require "jam_ruby/resque/audiomixer"
|
||||||
require "jam_ruby/resque/quick_mixer"
|
require "jam_ruby/resque/quick_mixer"
|
||||||
require "jam_ruby/resque/icecast_config_writer"
|
require "jam_ruby/resque/icecast_config_writer"
|
||||||
require "jam_ruby/resque/resque_hooks"
|
|
||||||
require "jam_ruby/resque/scheduled/audiomixer_retry"
|
require "jam_ruby/resque/scheduled/audiomixer_retry"
|
||||||
require "jam_ruby/resque/scheduled/icecast_config_retry"
|
require "jam_ruby/resque/scheduled/icecast_config_retry"
|
||||||
require "jam_ruby/resque/scheduled/icecast_source_check"
|
require "jam_ruby/resque/scheduled/icecast_source_check"
|
||||||
|
|
@ -55,6 +55,7 @@ require "jam_ruby/resque/scheduled/active_music_session_cleaner"
|
||||||
require "jam_ruby/resque/scheduled/score_history_sweeper"
|
require "jam_ruby/resque/scheduled/score_history_sweeper"
|
||||||
require "jam_ruby/resque/scheduled/scheduled_music_session_cleaner"
|
require "jam_ruby/resque/scheduled/scheduled_music_session_cleaner"
|
||||||
require "jam_ruby/resque/scheduled/recordings_cleaner"
|
require "jam_ruby/resque/scheduled/recordings_cleaner"
|
||||||
|
require "jam_ruby/resque/scheduled/stats_maker"
|
||||||
require "jam_ruby/resque/google_analytics_event"
|
require "jam_ruby/resque/google_analytics_event"
|
||||||
require "jam_ruby/resque/batch_email_job"
|
require "jam_ruby/resque/batch_email_job"
|
||||||
require "jam_ruby/mq_router"
|
require "jam_ruby/mq_router"
|
||||||
|
|
@ -78,6 +79,7 @@ require "jam_ruby/app/uploaders/max_mind_release_uploader"
|
||||||
require "jam_ruby/lib/desk_multipass"
|
require "jam_ruby/lib/desk_multipass"
|
||||||
require "jam_ruby/lib/ip"
|
require "jam_ruby/lib/ip"
|
||||||
require "jam_ruby/lib/subscription_message"
|
require "jam_ruby/lib/subscription_message"
|
||||||
|
require "jam_ruby/lib/stats.rb"
|
||||||
require "jam_ruby/amqp/amqp_connection_manager"
|
require "jam_ruby/amqp/amqp_connection_manager"
|
||||||
require "jam_ruby/database"
|
require "jam_ruby/database"
|
||||||
require "jam_ruby/message_factory"
|
require "jam_ruby/message_factory"
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,61 @@
|
||||||
|
require 'influxdb'
|
||||||
|
|
||||||
|
module JamRuby
|
||||||
|
class Stats
|
||||||
|
|
||||||
|
class << self
|
||||||
|
attr_accessor :client, :host
|
||||||
|
@@log = Logging.logger[JamRuby::Stats]
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.destroy!
|
||||||
|
if @client
|
||||||
|
@client.stop!
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.init(options)
|
||||||
|
influxdb_database = options[:influxdb_database]
|
||||||
|
influxdb_username = options[:influxdb_username]
|
||||||
|
influxdb_password = options[:influxdb_password]
|
||||||
|
influxdb_hosts = options[:influxdb_hosts]
|
||||||
|
influxdb_port = options[:influxdb_port]
|
||||||
|
influxdb_async = options[:influxdb_async].nil? ? true : options[:influxdb_async]
|
||||||
|
|
||||||
|
|
||||||
|
if influxdb_database && influxdb_database.length > 0
|
||||||
|
@client = InfluxDB::Client.new influxdb_database,
|
||||||
|
username: influxdb_username,
|
||||||
|
password: influxdb_password,
|
||||||
|
time_precision: 's',
|
||||||
|
hosts: influxdb_hosts,
|
||||||
|
port: influxdb_port,
|
||||||
|
async:influxdb_async,
|
||||||
|
retry: -1
|
||||||
|
@host = `hostname`.strip
|
||||||
|
else
|
||||||
|
@@log.debug("stats client not initiated")
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.write(name, data)
|
||||||
|
if @client && data && data.length > 0
|
||||||
|
data['host'] = @host
|
||||||
|
data['time'] = Time.now.to_i
|
||||||
|
@client.write_point(name, data)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.timer(name)
|
||||||
|
start = Time.now
|
||||||
|
begin
|
||||||
|
yield
|
||||||
|
Stats.write(name, result: 'success', duration: Time.now - start)
|
||||||
|
rescue Exception => e
|
||||||
|
Stats.write(name, result: 'failure', duration: Time.now - start, error: e.to_s)
|
||||||
|
raise e
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -8,6 +8,7 @@ module JamRuby
|
||||||
TYPE_CLIENT = 'client'
|
TYPE_CLIENT = 'client'
|
||||||
TYPE_BROWSER = 'browser'
|
TYPE_BROWSER = 'browser'
|
||||||
TYPE_LATENCY_TESTER = 'latency_tester'
|
TYPE_LATENCY_TESTER = 'latency_tester'
|
||||||
|
CLIENT_TYPES = [TYPE_CLIENT, TYPE_BROWSER, TYPE_LATENCY_TESTER]
|
||||||
|
|
||||||
attr_accessor :joining_session
|
attr_accessor :joining_session
|
||||||
|
|
||||||
|
|
@ -20,7 +21,7 @@ module JamRuby
|
||||||
has_many :video_sources, :class_name => "JamRuby::VideoSource", :inverse_of => :connection, :foreign_key => 'connection_id', :dependent => :delete_all
|
has_many :video_sources, :class_name => "JamRuby::VideoSource", :inverse_of => :connection, :foreign_key => 'connection_id', :dependent => :delete_all
|
||||||
|
|
||||||
validates :as_musician, :inclusion => {:in => [true, false, nil]}
|
validates :as_musician, :inclusion => {:in => [true, false, nil]}
|
||||||
validates :client_type, :inclusion => {:in => [TYPE_CLIENT, TYPE_BROWSER, TYPE_LATENCY_TESTER]}
|
validates :client_type, :inclusion => {:in => CLIENT_TYPES}
|
||||||
validates_numericality_of :last_jam_audio_latency, greater_than:0, :allow_nil => true
|
validates_numericality_of :last_jam_audio_latency, greater_than:0, :allow_nil => true
|
||||||
validate :can_join_music_session, :if => :joining_session?
|
validate :can_join_music_session, :if => :joining_session?
|
||||||
validate :user_or_latency_tester_present
|
validate :user_or_latency_tester_present
|
||||||
|
|
@ -222,6 +223,28 @@ module JamRuby
|
||||||
update_locidispids
|
update_locidispids
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def self.stats
|
||||||
|
stats = {}
|
||||||
|
|
||||||
|
CLIENT_TYPES.each do |type|
|
||||||
|
stats[type] = 0
|
||||||
|
end
|
||||||
|
Connection.select('count(client_type) AS client_type_count, client_type') do |result|
|
||||||
|
stats[result['client_type']] = result['client_type_count']
|
||||||
|
end
|
||||||
|
|
||||||
|
result = Connection.select('count(id) AS total, count(scoring_timeout) AS scoring_timeout_count, count(music_session_id) AS in_session, count(as_musician) AS musicians, count(udp_reachable) AS udp_reachable_count, count(is_network_testing) AS is_network_testing_count').first
|
||||||
|
|
||||||
|
stats['count'] = result['total'].to_i
|
||||||
|
stats['scoring_timeout'] = result['scoring_timeout_count'].to_i
|
||||||
|
stats['in_session'] = result['in_session'].to_i
|
||||||
|
stats['musicians'] = result['musicians'].to_i
|
||||||
|
stats['udp_reachable'] = result['udp_reachable_count'].to_i
|
||||||
|
stats['networking_testing'] = result['is_network_testing_count'].to_i
|
||||||
|
|
||||||
|
stats
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def require_at_least_one_track_when_in_session
|
def require_at_least_one_track_when_in_session
|
||||||
|
|
|
||||||
|
|
@ -1465,8 +1465,24 @@ module JamRuby
|
||||||
|
|
||||||
!approved_slots.blank?
|
!approved_slots.blank?
|
||||||
end
|
end
|
||||||
|
|
||||||
# end devise compatibility
|
# end devise compatibility
|
||||||
|
|
||||||
|
def self.stats
|
||||||
|
stats = {}
|
||||||
|
result = User.select('count(CASE WHEN musician THEN 1 ELSE null END) as musician_count, count(CASE WHEN musician = FALSE THEN 1 ELSE null END) as fan_count, count(first_downloaded_client_at) first_downloaded_client_at_count, count(first_ran_client_at) first_ran_client_at_count, count(first_certified_gear_at) first_certified_gear_at_count, count(first_music_session_at) as first_music_session_at_count, count(first_invited_at) first_invited_at_count, count(first_friended_at) as first_friended_at_count, count(first_social_promoted_at) first_social_promoted_at_count, avg(last_jam_audio_latency) last_jam_audio_latency_avg').first
|
||||||
|
puts "result #{result['musician_count']}"
|
||||||
|
stats['musicians'] = result['musician_count'].to_i
|
||||||
|
stats['fans'] = result['fan_count'].to_i
|
||||||
|
stats['downloaded_client'] = result['first_downloaded_client_at_count'].to_i
|
||||||
|
stats['ran_client'] = result['first_ran_client_at_count'].to_i
|
||||||
|
stats['certified_gear'] = result['first_certified_gear_at_count'].to_i
|
||||||
|
stats['jammed'] = result['first_music_session_at_count'].to_i
|
||||||
|
stats['invited'] = result['first_invited_at_count'].to_i
|
||||||
|
stats['friended'] = result['first_friended_at_count'].to_i
|
||||||
|
stats['social_promoted'] = result['first_social_promoted_at_count'].to_i
|
||||||
|
stats['audio_latency_avg'] = result['last_jam_audio_latency_avg'].to_f
|
||||||
|
stats
|
||||||
|
end
|
||||||
private
|
private
|
||||||
def create_remember_token
|
def create_remember_token
|
||||||
self.remember_token = SecureRandom.urlsafe_base64
|
self.remember_token = SecureRandom.urlsafe_base64
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ module JamRuby
|
||||||
|
|
||||||
# executes a mix of tracks, creating a final output mix
|
# executes a mix of tracks, creating a final output mix
|
||||||
class AudioMixer
|
class AudioMixer
|
||||||
|
extend JamRuby::ResqueStats
|
||||||
|
|
||||||
@queue = :audiomixer
|
@queue = :audiomixer
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ require 'resque'
|
||||||
# more info on Measurement Protocol https://developers.google.com/analytics/devguides/collection/protocol/v1/
|
# more info on Measurement Protocol https://developers.google.com/analytics/devguides/collection/protocol/v1/
|
||||||
module JamRuby
|
module JamRuby
|
||||||
class GoogleAnalyticsEvent
|
class GoogleAnalyticsEvent
|
||||||
|
extend ResqueStats
|
||||||
|
|
||||||
@queue = :google_analytics_event
|
@queue = :google_analytics_event
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ module JamRuby
|
||||||
|
|
||||||
# executes a mix of tracks, creating a final output mix
|
# executes a mix of tracks, creating a final output mix
|
||||||
class QuickMixer
|
class QuickMixer
|
||||||
|
extend JamRuby::ResqueStats
|
||||||
|
|
||||||
@queue = :quick_mixer
|
@queue = :quick_mixer
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,54 @@
|
||||||
|
require 'resque'
|
||||||
|
|
||||||
# https://devcenter.heroku.com/articles/forked-pg-connections
|
# https://devcenter.heroku.com/articles/forked-pg-connections
|
||||||
Resque.before_fork do
|
Resque.before_fork do
|
||||||
defined?(ActiveRecord::Base) and
|
defined?(ActiveRecord::Base) and
|
||||||
ActiveRecord::Base.connection.disconnect!
|
ActiveRecord::Base.connection.disconnect!
|
||||||
|
|
||||||
|
JamRuby::Stats.destroy!
|
||||||
end
|
end
|
||||||
|
|
||||||
Resque.after_fork do
|
Resque.after_fork do
|
||||||
defined?(ActiveRecord::Base) and
|
defined?(ActiveRecord::Base) and
|
||||||
ActiveRecord::Base.establish_connection
|
ActiveRecord::Base.establish_connection
|
||||||
end
|
|
||||||
|
config = {
|
||||||
|
influxdb_database: APP_CONFIG.influxdb_database,
|
||||||
|
influxdb_username: APP_CONFIG.influxdb_username,
|
||||||
|
influxdb_password: APP_CONFIG.influxdb_password,
|
||||||
|
influxdb_hosts: APP_CONFIG.influxdb_hosts,
|
||||||
|
influxdb_port: APP_CONFIG.influxdb_port,
|
||||||
|
influxdb_async: false # if we use async=true, the forked job will die before the stat is sent
|
||||||
|
}
|
||||||
|
JamRuby::Stats.init(config)
|
||||||
|
end
|
||||||
|
|
||||||
|
# for jobs that do not extend lonely job, just extend this module and get stats
|
||||||
|
module JamRuby
|
||||||
|
module ResqueStats
|
||||||
|
def around_perform(*args)
|
||||||
|
Stats.timer('job.stats') do
|
||||||
|
begin
|
||||||
|
yield
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# for jobs that extend lonely job, we override around_perform already implemented in LonelyJob, and call into it
|
||||||
|
module Resque
|
||||||
|
module Plugins
|
||||||
|
module LonelyJob
|
||||||
|
def around_perform(*args)
|
||||||
|
Stats.timer('job.stats') do
|
||||||
|
begin
|
||||||
|
yield
|
||||||
|
ensure
|
||||||
|
unlock_queue(*args)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,9 @@
|
||||||
module JamRuby
|
module JamRuby
|
||||||
class CleanupFacebookSignup
|
class CleanupFacebookSignup
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@queue = :scheduled_cleanup_facebook_signup
|
@queue = :scheduled_cleanup_facebook_signup
|
||||||
|
|
||||||
@@log = Logging.logger[CleanupFacebookSignup]
|
@@log = Logging.logger[CleanupFacebookSignup]
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
require 'json'
|
||||||
|
require 'resque'
|
||||||
|
require 'resque-retry'
|
||||||
|
require 'net/http'
|
||||||
|
require 'digest/md5'
|
||||||
|
|
||||||
|
module JamRuby
|
||||||
|
|
||||||
|
# creates stats to send to influx periodically
|
||||||
|
class StatsMaker
|
||||||
|
extend Resque::Plugins::LonelyJob
|
||||||
|
|
||||||
|
@queue = :stats_maker
|
||||||
|
|
||||||
|
@@log = Logging.logger['StatsMaker']
|
||||||
|
|
||||||
|
def self.perform
|
||||||
|
Stats.write('connection', Connection.stats)
|
||||||
|
Stats.write('users', User.stats)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
require 'spec_helper'
|
||||||
|
|
||||||
|
describe Stats do
|
||||||
|
|
||||||
|
before(:each) do
|
||||||
|
Stats.client = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
after(:all) do
|
||||||
|
Stats.client = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "not-inited" do
|
||||||
|
it "write" do
|
||||||
|
Stats.write('bleh', time: Time.now.to_i)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "inited" do
|
||||||
|
before(:each) do
|
||||||
|
Stats.init(influxdb_database: 'test')
|
||||||
|
end
|
||||||
|
|
||||||
|
it "write" do
|
||||||
|
# this can't pass unless there is an actual db listening
|
||||||
|
Stats.write('bleh', time: Time.now.to_i)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
|
@ -178,4 +178,20 @@ describe JamRuby::Connection do
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "stats" do
|
||||||
|
|
||||||
|
it "no connections" do
|
||||||
|
stats = Connection.stats
|
||||||
|
stats[Connection::TYPE_CLIENT].should eq(0)
|
||||||
|
stats[Connection::TYPE_BROWSER].should eq(0)
|
||||||
|
stats[Connection::TYPE_LATENCY_TESTER].should eq(0)
|
||||||
|
stats['count'].should eq(0)
|
||||||
|
stats['scoring_timeout'].should eq(0)
|
||||||
|
stats['in_session'].should eq(0)
|
||||||
|
stats['musicians'].should eq(0)
|
||||||
|
stats['udp_reachable'].should eq(0)
|
||||||
|
stats['networking_testing'].should eq(0)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,39 @@ describe User do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "stats" do
|
||||||
|
|
||||||
|
it "no user" do
|
||||||
|
stats = User.stats
|
||||||
|
stats['musicians'].should == 0
|
||||||
|
stats['fans'].should == 0
|
||||||
|
stats['downloaded_client'].should == 0
|
||||||
|
stats['ran_client'].should == 0
|
||||||
|
stats['certified_gear'].should == 0
|
||||||
|
stats['invited'].should == 0
|
||||||
|
stats['friended'].should == 0
|
||||||
|
stats['social_promoted'].should == 0
|
||||||
|
stats['audio_latency_avg'].should == 0
|
||||||
|
end
|
||||||
|
|
||||||
|
it "single user" do
|
||||||
|
@user.musician = true
|
||||||
|
@user.last_jam_audio_latency = 5
|
||||||
|
@user.save!
|
||||||
|
stats = User.stats
|
||||||
|
@user.musician.should be_true
|
||||||
|
stats['musicians'].should == 1
|
||||||
|
stats['fans'].should == 0
|
||||||
|
stats['downloaded_client'].should == 0
|
||||||
|
stats['ran_client'].should == 0
|
||||||
|
stats['certified_gear'].should == 0
|
||||||
|
stats['invited'].should == 0
|
||||||
|
stats['friended'].should == 0
|
||||||
|
stats['social_promoted'].should == 0
|
||||||
|
stats['audio_latency_avg'].should == 5
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe "with admin attribute set to 'true'" do
|
describe "with admin attribute set to 'true'" do
|
||||||
before do
|
before do
|
||||||
@user.save!
|
@user.save!
|
||||||
|
|
|
||||||
|
|
@ -85,7 +85,8 @@ gem 'htmlentities'
|
||||||
gem 'sanitize'
|
gem 'sanitize'
|
||||||
gem 'recurly'
|
gem 'recurly'
|
||||||
gem 'guard', '2.7.3'
|
gem 'guard', '2.7.3'
|
||||||
gem 'influxdb-rails'
|
gem 'influxdb', '0.1.8'
|
||||||
|
gem 'influxdb-rails', '0.1.10'
|
||||||
|
|
||||||
group :development, :test do
|
group :development, :test do
|
||||||
gem 'rspec-rails', '2.14.2'
|
gem 'rspec-rails', '2.14.2'
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@
|
||||||
//= require fakeJamClientRecordings
|
//= require fakeJamClientRecordings
|
||||||
//= require backend_alerts
|
//= require backend_alerts
|
||||||
//= require stun
|
//= require stun
|
||||||
|
//= requre influxdb-latest
|
||||||
|
|
||||||
(function (context, $) {
|
(function (context, $) {
|
||||||
|
|
||||||
|
|
@ -26,6 +27,8 @@
|
||||||
context.JK.initJamClient(app);
|
context.JK.initJamClient(app);
|
||||||
|
|
||||||
updateScoringIntervals();
|
updateScoringIntervals();
|
||||||
|
|
||||||
|
initializeInfluxDB();
|
||||||
})
|
})
|
||||||
|
|
||||||
$(document).on('JAMKAZAM_READY', function() {
|
$(document).on('JAMKAZAM_READY', function() {
|
||||||
|
|
@ -156,6 +159,17 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function initializeInfluxDB() {
|
||||||
|
context.stats = new InfluxDB({
|
||||||
|
"host" : gon.global.influxdb_host,
|
||||||
|
"port" : gon.global.influxdb_port,
|
||||||
|
"username" : gon.global.influxdb_username,
|
||||||
|
"password" : gon.global.influxdb_password,
|
||||||
|
"database" : gon.global.influxdb_database
|
||||||
|
});
|
||||||
|
|
||||||
|
context.stats.write = context.stats.write_point;
|
||||||
|
}
|
||||||
function initializeStun(app) {
|
function initializeStun(app) {
|
||||||
stun = new context.JK.Stun(app);
|
stun = new context.JK.Stun(app);
|
||||||
context.JK.StunInstance = stun;
|
context.JK.StunInstance = stun;
|
||||||
|
|
|
||||||
|
|
@ -289,11 +289,14 @@ if defined?(Bundler)
|
||||||
|
|
||||||
config.jam_tracks_available = false
|
config.jam_tracks_available = false
|
||||||
|
|
||||||
# these values work out of the box with default settings of an influx install
|
# these values work out of the box with default settings of an influx install (you do have to add a development database by hand though)
|
||||||
config.influxdb_database = "development"
|
config.influxdb_database = 'development'
|
||||||
config.influxdb_username = "root"
|
config.influxdb_username = "root"
|
||||||
config.influxdb_password = "root"
|
config.influxdb_password = "root"
|
||||||
|
config.influxdb_unsafe_username = "root" # these are exposed to JavaScript
|
||||||
|
config.influxdb_unsafe_password = "root" # these are exposed to JavaScript
|
||||||
config.influxdb_hosts = ["localhost"]
|
config.influxdb_hosts = ["localhost"]
|
||||||
config.influxdb_port = 8086
|
config.influxdb_port = 8086
|
||||||
|
config.influxdb_ignored_environments = ENV["INFLUXDB_ENABLED"] == '1' ? ['test', 'cucumber'] : ['test', 'cucumber', 'development']
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,10 @@ require File.expand_path('../application', __FILE__)
|
||||||
|
|
||||||
Mime::Type.register "audio/ogg", :audio_ogg
|
Mime::Type.register "audio/ogg", :audio_ogg
|
||||||
|
|
||||||
|
# assign globals
|
||||||
APP_CONFIG = Rails.application.config
|
APP_CONFIG = Rails.application.config
|
||||||
|
Stats.client = InfluxDB::Rails.client
|
||||||
|
|
||||||
# Initialize the rails application
|
# Initialize the rails application
|
||||||
SampleApp::Application.initialize!
|
SampleApp::Application.initialize!
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,11 @@ unless $rails_rake_task
|
||||||
:connect_time_stale_browser => APP_CONFIG.websocket_gateway_connect_time_stale_browser,
|
:connect_time_stale_browser => APP_CONFIG.websocket_gateway_connect_time_stale_browser,
|
||||||
:connect_time_expire_browser => APP_CONFIG.websocket_gateway_connect_time_expire_browser,
|
:connect_time_expire_browser => APP_CONFIG.websocket_gateway_connect_time_expire_browser,
|
||||||
:max_connections_per_user => APP_CONFIG.websocket_gateway_max_connections_per_user,
|
:max_connections_per_user => APP_CONFIG.websocket_gateway_max_connections_per_user,
|
||||||
|
:influxdb_database => APP_CONFIG.influxdb_database,
|
||||||
|
:influxdb_username => APP_CONFIG.influxdb_username,
|
||||||
|
:influxdb_password => APP_CONFIG.influxdb_password,
|
||||||
|
:influxdb_hosts => APP_CONFIG.influxdb_hosts,
|
||||||
|
:influxdb_port => APP_CONFIG.influxdb_port,
|
||||||
:rabbitmq_host => APP_CONFIG.rabbitmq_host,
|
:rabbitmq_host => APP_CONFIG.rabbitmq_host,
|
||||||
:rabbitmq_port => APP_CONFIG.rabbitmq_port,
|
:rabbitmq_port => APP_CONFIG.rabbitmq_port,
|
||||||
:calling_thread => current,
|
:calling_thread => current,
|
||||||
|
|
|
||||||
|
|
@ -5,4 +5,9 @@ Gon.global.twitter_public_account = Rails.application.config.twitter_public_acco
|
||||||
Gon.global.scoring_get_work_interval = Rails.application.config.scoring_get_work_interval
|
Gon.global.scoring_get_work_interval = Rails.application.config.scoring_get_work_interval
|
||||||
Gon.global.scoring_get_work_backoff_interval = Rails.application.config.scoring_get_work_backoff_interval
|
Gon.global.scoring_get_work_backoff_interval = Rails.application.config.scoring_get_work_backoff_interval
|
||||||
Gon.global.ftue_network_test_min_wait_since_last_score = Rails.application.config.ftue_network_test_min_wait_since_last_score
|
Gon.global.ftue_network_test_min_wait_since_last_score = Rails.application.config.ftue_network_test_min_wait_since_last_score
|
||||||
|
Gon.global.influxdb_host = Rails.application.config.influxdb_hosts[0]
|
||||||
|
Gon.global.influxdb_port = Rails.application.config.influxdb_port
|
||||||
|
Gon.global.influxdb_database = Rails.application.config.influxdb_database
|
||||||
|
Gon.global.influxdb_username = Rails.application.config.influxdb_unsafe_username
|
||||||
|
Gon.global.influxdb_password = Rails.application.config.influxdb_unsafe_password
|
||||||
Gon.global.env = Rails.env
|
Gon.global.env = Rails.env
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,13 @@
|
||||||
InfluxDB::Rails.configure do |config|
|
InfluxDB::Rails.configure do |config|
|
||||||
config.influxdb_database = Rails.application.config.influxdb_database
|
config.influxdb_database = Rails.application.config.influxdb_database
|
||||||
config.influxdb_username = Rails.application.config.influxdb_username
|
config.influxdb_username = Rails.application.config.influxdb_username
|
||||||
config.influxdb_password = Rails.application.config.influxdb_password
|
config.influxdb_password = Rails.application.config.influxdb_password
|
||||||
config.influxdb_hosts = Rails.application.config.influxdb_hosts
|
config.influxdb_hosts = Rails.application.config.influxdb_hosts
|
||||||
config.influxdb_port = Rails.application.config.influxdb_port
|
config.influxdb_port = Rails.application.config.influxdb_port
|
||||||
|
config.ignored_environments = Rails.application.config.influxdb_ignored_environments
|
||||||
|
config.async = true
|
||||||
|
config.debug = false
|
||||||
|
config.logger = Logging.logger['InfluxDB']
|
||||||
|
|
||||||
config.series_name_for_controller_runtimes = "web.rails.controller"
|
config.series_name_for_controller_runtimes = "web.rails.controller"
|
||||||
config.series_name_for_view_runtimes = "web.rails.view"
|
config.series_name_for_view_runtimes = "web.rails.view"
|
||||||
|
|
|
||||||
|
|
@ -91,6 +91,9 @@ Logging::Rails.configure do |config|
|
||||||
#
|
#
|
||||||
Logging.logger.root.level = config.log_level
|
Logging.logger.root.level = config.log_level
|
||||||
Logging.logger.root.appenders = config.log_to unless config.log_to.empty?
|
Logging.logger.root.appenders = config.log_to unless config.log_to.empty?
|
||||||
|
Logging.logger['ActiveSupport::Cache::FileStore'].level = :info
|
||||||
|
Logging.logger['ActiveSupport::OrderedOptions'].level = :warn
|
||||||
|
Logging.logger['InfluxDB'].level = :warn
|
||||||
|
|
||||||
# Under Phusion Passenger smart spawning, we need to reopen all IO streams
|
# Under Phusion Passenger smart spawning, we need to reopen all IO streams
|
||||||
# after workers have forked.
|
# after workers have forked.
|
||||||
|
|
@ -101,10 +104,6 @@ Logging::Rails.configure do |config|
|
||||||
# the file descriptors after forking ensures that each worker has a unique
|
# the file descriptors after forking ensures that each worker has a unique
|
||||||
# file descriptor.
|
# file descriptor.
|
||||||
#
|
#
|
||||||
|
|
||||||
Logging.logger['ActiveSupport::Cache::FileStore'].level = :info
|
|
||||||
Logging.logger['ActiveSupport::OrderedOptions'].level = :warn
|
|
||||||
|
|
||||||
if defined?(PhusionPassenger)
|
if defined?(PhusionPassenger)
|
||||||
PhusionPassenger.on_event(:starting_worker_process) do |forked|
|
PhusionPassenger.on_event(:starting_worker_process) do |forked|
|
||||||
Logging.reopen if forked
|
Logging.reopen if forked
|
||||||
|
|
|
||||||
|
|
@ -63,4 +63,9 @@ ScoreHistorySweeper:
|
||||||
RecordingsCleaner:
|
RecordingsCleaner:
|
||||||
cron: 0 * * * *
|
cron: 0 * * * *
|
||||||
class: "JamRuby::RecordingsCleaner"
|
class: "JamRuby::RecordingsCleaner"
|
||||||
description: "Cleans up recordings that no one wants after 7 days"
|
description: "Cleans up recordings that no one wants after 7 days"
|
||||||
|
|
||||||
|
StatsMaker:
|
||||||
|
cron: "* * * * *"
|
||||||
|
class: "JamRuby::StatsMaker"
|
||||||
|
description: "Generates interesting stats from the database"
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -53,6 +53,7 @@ gem 'iso-639'
|
||||||
gem 'language_list'
|
gem 'language_list'
|
||||||
gem 'rubyzip'
|
gem 'rubyzip'
|
||||||
gem 'sanitize'
|
gem 'sanitize'
|
||||||
|
gem 'influxdb', '0.1.8'
|
||||||
|
|
||||||
group :development do
|
group :development do
|
||||||
gem 'pry'
|
gem 'pry'
|
||||||
|
|
|
||||||
|
|
@ -67,5 +67,10 @@ Server.new.run(:port => config["port"] + (jam_instance-1 ) * 2,
|
||||||
:max_connections_per_user => config["max_connections_per_user"],
|
:max_connections_per_user => config["max_connections_per_user"],
|
||||||
:rabbitmq_host => config['rabbitmq_host'],
|
:rabbitmq_host => config['rabbitmq_host'],
|
||||||
:rabbitmq_port => config['rabbitmq_port'],
|
:rabbitmq_port => config['rabbitmq_port'],
|
||||||
|
:influxdb_database => config['influxdb_database'],
|
||||||
|
:influxdb_username => config['influxdb_username'],
|
||||||
|
:influxdb_password => config['influxdb_password'],
|
||||||
|
:influxdb_hosts => config['influxdb_hosts'],
|
||||||
|
:influxdb_port => config['influxdb_port'],
|
||||||
:cidr => config['cidr'],
|
:cidr => config['cidr'],
|
||||||
:gateway_name => gateway_name)
|
:gateway_name => gateway_name)
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,11 @@ Defaults: &defaults
|
||||||
connect_time_expire_browser: 60
|
connect_time_expire_browser: 60
|
||||||
cidr: [0.0.0.0/0]
|
cidr: [0.0.0.0/0]
|
||||||
max_connections_per_user: 20
|
max_connections_per_user: 20
|
||||||
|
influxdb_database: "development"
|
||||||
|
influxdb_username: "root"
|
||||||
|
influxdb_password: "root"
|
||||||
|
influxdb_hosts: ["localhost"]
|
||||||
|
influxdb_port: 8086
|
||||||
|
|
||||||
development:
|
development:
|
||||||
port: 6767
|
port: 6767
|
||||||
|
|
|
||||||
|
|
@ -54,6 +54,11 @@ module JamWebsockets
|
||||||
@gateway_name = nil
|
@gateway_name = nil
|
||||||
@ar_base_logger = ::Logging::Repository.instance[ActiveRecord::Base]
|
@ar_base_logger = ::Logging::Repository.instance[ActiveRecord::Base]
|
||||||
@message_stats = {}
|
@message_stats = {}
|
||||||
|
|
||||||
|
@login_success_count = 0
|
||||||
|
@login_fail_count = 0
|
||||||
|
@connected_count = 0
|
||||||
|
@disconnected_count = 0
|
||||||
end
|
end
|
||||||
|
|
||||||
def start(connect_time_stale_client, connect_time_expire_client, connect_time_stale_browser, connect_time_expire_browser, options={:host => "localhost", :port => 5672, :max_connections_per_user => 10, :gateway => 'default'}, &block)
|
def start(connect_time_stale_client, connect_time_expire_client, connect_time_stale_browser, connect_time_expire_browser, options={:host => "localhost", :port => 5672, :max_connections_per_user => 10, :gateway => 'default'}, &block)
|
||||||
|
|
@ -368,6 +373,8 @@ module JamWebsockets
|
||||||
|
|
||||||
client.onopen { |handshake|
|
client.onopen { |handshake|
|
||||||
|
|
||||||
|
stats_connected
|
||||||
|
|
||||||
# a unique ID for this TCP connection, to aid in debugging
|
# a unique ID for this TCP connection, to aid in debugging
|
||||||
client.channel_id = handshake.query["channel_id"]
|
client.channel_id = handshake.query["channel_id"]
|
||||||
|
|
||||||
|
|
@ -584,6 +591,7 @@ module JamWebsockets
|
||||||
})
|
})
|
||||||
if latency_tester.errors.any?
|
if latency_tester.errors.any?
|
||||||
@log.warn "unable to log in latency_tester with errors: #{latency_tester.errors.inspect}"
|
@log.warn "unable to log in latency_tester with errors: #{latency_tester.errors.inspect}"
|
||||||
|
stats_logged_in_failed
|
||||||
raise SessionError, "invalid login: #{latency_tester.errors.inspect}"
|
raise SessionError, "invalid login: #{latency_tester.errors.inspect}"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -604,6 +612,7 @@ module JamWebsockets
|
||||||
false,
|
false,
|
||||||
latency_tester.id,
|
latency_tester.id,
|
||||||
connection_expire_time)
|
connection_expire_time)
|
||||||
|
stats_logged_in
|
||||||
send_to_client(client, login_ack)
|
send_to_client(client, login_ack)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
@ -640,6 +649,7 @@ module JamWebsockets
|
||||||
# protect against this user swamping the server
|
# protect against this user swamping the server
|
||||||
if user && Connection.where(user_id: user.id).count >= @max_connections_per_user
|
if user && Connection.where(user_id: user.id).count >= @max_connections_per_user
|
||||||
@log.warn "user #{user.id}/#{user.email} unable to connect due to max_connections_per_user #{@max_connections_per_user}"
|
@log.warn "user #{user.id}/#{user.email} unable to connect due to max_connections_per_user #{@max_connections_per_user}"
|
||||||
|
stats_logged_in_failed
|
||||||
raise SessionError, 'max_user_connections', 'max_user_connections'
|
raise SessionError, 'max_user_connections', 'max_user_connections'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -760,9 +770,11 @@ module JamWebsockets
|
||||||
user.id,
|
user.id,
|
||||||
connection_expire_time,
|
connection_expire_time,
|
||||||
client_update)
|
client_update)
|
||||||
|
stats_logged_in
|
||||||
send_to_client(client, login_ack)
|
send_to_client(client, login_ack)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
|
stats_logged_in_failed
|
||||||
raise SessionError.new('invalid login', 'invalid_login')
|
raise SessionError.new('invalid login', 'invalid_login')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
@ -1089,7 +1101,23 @@ module JamWebsockets
|
||||||
stats.map { |i| i[1] = (i[1] / 60.0).round(2) }
|
stats.map { |i| i[1] = (i[1] / 60.0).round(2) }
|
||||||
|
|
||||||
@log.info("msg/s: " + stats.map { |i| i.join('=>') }.join(', '));
|
@log.info("msg/s: " + stats.map { |i| i.join('=>') }.join(', '));
|
||||||
|
|
||||||
|
|
||||||
|
# stuff in extra stats into the @message_stats and send it all off
|
||||||
|
@message_stats['gateway_name'] = @gateway_name
|
||||||
|
@message_stats['login'] = @login_success_count
|
||||||
|
@message_stats['login_fail'] = @login_fail_count
|
||||||
|
@message_stats['connected'] = @connected_count
|
||||||
|
@message_stats['disconnected'] = @disconnected_count
|
||||||
|
|
||||||
|
Stats.write('gateway.stats', @message_stats)
|
||||||
|
|
||||||
|
# clear out stats
|
||||||
@message_stats.clear
|
@message_stats.clear
|
||||||
|
@login_success_count = 0
|
||||||
|
@login_fail_count = 0
|
||||||
|
@connected_count = 0
|
||||||
|
@disconnected_count = 0
|
||||||
end
|
end
|
||||||
|
|
||||||
def cleanup_clients_with_ids(expired_connections)
|
def cleanup_clients_with_ids(expired_connections)
|
||||||
|
|
@ -1161,6 +1189,7 @@ module JamWebsockets
|
||||||
|
|
||||||
if pending
|
if pending
|
||||||
@log.debug "cleaned up not-logged-in client #{client}"
|
@log.debug "cleaned up not-logged-in client #{client}"
|
||||||
|
stats_disconnected
|
||||||
else
|
else
|
||||||
@log.debug "cleanup up logged-in client #{client}"
|
@log.debug "cleanup up logged-in client #{client}"
|
||||||
|
|
||||||
|
|
@ -1169,6 +1198,7 @@ module JamWebsockets
|
||||||
if context
|
if context
|
||||||
remove_client(client.client_id)
|
remove_client(client.client_id)
|
||||||
remove_user(context)
|
remove_user(context)
|
||||||
|
stats_disconnected
|
||||||
else
|
else
|
||||||
@log.warn "skipping duplicate cleanup attempt of logged-in client"
|
@log.warn "skipping duplicate cleanup attempt of logged-in client"
|
||||||
end
|
end
|
||||||
|
|
@ -1176,6 +1206,21 @@ module JamWebsockets
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def stats_logged_in
|
||||||
|
@login_success_count = @login_success_count + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
def stats_logged_in_failed
|
||||||
|
@login_fail_count = @login_fail_count + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
def stats_connected
|
||||||
|
@connected_count = @connected_count + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
def stats_disconnected
|
||||||
|
@disconnected_count = @disconnected_count + 1
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,9 @@ module JamWebsockets
|
||||||
gateway_name = options[:gateway_name]
|
gateway_name = options[:gateway_name]
|
||||||
rabbitmq_host = options[:rabbitmq_host]
|
rabbitmq_host = options[:rabbitmq_host]
|
||||||
rabbitmq_port = options[:rabbitmq_port].to_i
|
rabbitmq_port = options[:rabbitmq_port].to_i
|
||||||
|
|
||||||
|
Stats::init(options)
|
||||||
|
|
||||||
calling_thread = options[:calling_thread]
|
calling_thread = options[:calling_thread]
|
||||||
trust_check = TrustCheck.new(trust_port, options[:cidr])
|
trust_check = TrustCheck.new(trust_port, options[:cidr])
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue