This commit is contained in:
Seth Call 2015-12-09 11:32:24 -06:00
parent a5e9ca18b5
commit 6314748225
14 changed files with 225 additions and 19 deletions

View File

@ -1,28 +1,27 @@
ActiveAdmin.register JamRuby::CrashDump, :as => 'Crash Dump' do
# Note: a lame thing is it's not obvious how to make it search on email instead of user_id.
filter :timestamp
filter :user_email, :as => :string
filter :client_id
filter :user_id
menu :parent => 'Misc'
config.sort_order = 'created_at DESC'
index do
column 'User' do |oo| oo.user ? link_to(oo.user.email, oo.user.admin_url, {:title => oo.user.email}) : '' end
column "Client Version", :client_version
column "Client Type", :client_type
column "Download" do |post|
link_to 'Link', post.sign_url
end
column "Timestamp" do |post|
(post.timestamp || post.created_at).strftime('%b %d %Y, %H:%M')
end
column "Client Type", :client_type
column "Dump URL" do |post|
link_to post.uri, post.uri
column "Description" do |post|
post.description
end
column "User ID", :user_id
# FIXME (?): This isn't performant (though it likely doesn't matter). Could probably do a join.
column "User Email" do |post|
unless post.user_id.nil?
post.user_email
end
end
column "Client ID", :client_id
actions
end
end

View File

@ -10,10 +10,11 @@ ActiveAdmin.register JamRuby::DownloadTracker, :as => 'DownloadTrackers' do
index do
column 'User' do |oo| oo.user ? link_to(oo.user.email, oo.user.admin_url, {:title => oo.user.email}) : '' end
column 'Remote IP' do |oo| oo.remote_ip end
column 'Created' do |oo| oo.created_at end
column 'JamTrack' do |oo| oo.jam_track end
column 'Paid' do |oo| oo.paid end
column 'Blacklisted?' do |oo| IpBlacklist.listed(oo.remote_ip) ? 'Yes' : 'No' end
column 'Remote IP' do |oo| oo.remote_ip end
column "" do |oo|
link_to 'Blacklist This IP', "download_trackers/#{oo.id}/blacklist_by_ip"
end

View File

@ -1,6 +1,8 @@
module JamRuby
class CrashDump < ActiveRecord::Base
include JamRuby::S3ManagerMixin
self.table_name = "crash_dumps"
self.primary_key = 'id'
@ -23,5 +25,8 @@ module JamRuby
self.user.email
end
def sign_url(expiration_time = 3600 * 24 * 7, secure=true)
s3_manager.sign_url(self[:ri], {:expires => expiration_time, :secure => secure})
end
end
end

View File

@ -111,10 +111,10 @@ module JamRuby
# the idea is that this is used when a user who has the rights to this tries to download this JamTrack
# we would verify their rights (can_download?), and generates a URL in response to the click so that they can download
# but the url is short lived enough so that it wouldn't be easily shared
def sign_url(expiration_time = 120, bitrate=48, secure=true)
field_name = (bitrate==48) ? "url_48" : "url_44"
s3_manager.sign_url(self[field_name], {:expires => expiration_time, :secure => secure})
end
def sign_url(expiration_time = 120, bitrate=48, secure=true)
field_name = (bitrate==48) ? "url_48" : "url_44"
s3_manager.sign_url(self[field_name], {:expires => expiration_time, :secure => secure})
end
def delete_s3_files
remove_url_48!

View File

@ -7,6 +7,7 @@
//= require ./react-components/stores/RecordingStore
//= require ./react-components/stores/VideoStore
//= require ./react-components/stores/SessionStore
//= require ./react-components/stores/SessionStatsStore
//= require ./react-components/stores/MixerStore
//= require ./react-components/stores/JamTrackStore
//= require ./react-components/stores/SessionNotificationStore

View File

@ -4,6 +4,11 @@ MixerActions = @MixerActions
@SessionOtherTrack = React.createClass({
mixins: [Reflux.listenTo(@SessionStatsStore,"onStatsChanged")]
onStatsChanged: (stats) ->
@setState({stats: stats})
handleMute: (e) ->
e.preventDefault()
@ -48,6 +53,10 @@ MixerActions = @MixerActions
WebkitTransform: "rotate(#{pan}deg)"
}
connectionState = @state.stats.clientState(this.props.participant.client_id)
connectionStateClasses = { 'track-connection-state': true}
connectionStateClasses[connectionState] = true
`<div className={componentClasses}>
<div className="disabled-track-overlay" />
<div className="session-track-contents">
@ -59,6 +68,7 @@ MixerActions = @MixerActions
<div className="track-buttons">
<div className={classes} data-control="mute" data-mixer-id={muteMixerId} onClick={this.handleMute}/>
<div className="track-icon-pan" style={panStyle}/>
<div className={classNames()}/>
</div>
<br className="clearall"/>
</div>

View File

@ -0,0 +1,30 @@
context = window
ChannelGroupIds = context.JK.ChannelGroupIds
MixerActions = @MixerActions
ptrCount = 0
@SessionStatsHover = React.createClass({
propTypes: {
clientId: React.PropTypes.string
}
mixins: [Reflux.listenTo(@SessionStatsStore, "onStatsChanged")]
render: () ->
`<div>
</div>`
onStatsChanged: (stats) ->
@setState({stats: stats})
getInitialState: () ->
{stats: window.SessionStatsStore.stats}
closeHover: (e) ->
e.preventDefault()
$container = $(this.getDOMNode()).closest('.react-holder')
$container.data('bt').btOff()
})

View File

@ -0,0 +1,5 @@
context = window
@SessionStatsActions = Reflux.createActions({
pushStats: {}
})

View File

@ -0,0 +1,110 @@
$ = jQuery
context = window
logger = context.JK.logger
rest = context.JK.Rest()
EVENTS = context.JK.EVENTS
MIX_MODES = context.JK.MIX_MODES
SessionActions = @SessionActions
SessionStatThresholds = gon.session_stat_thresholds
NetworkThresholds = SessionStatThresholds.network
SystemThresholds = SessionStatThresholds.system
AudioThresholds = SessionStatThresholds.audio
@SessionStatsStore = Reflux.createStore(
rawStats: null
onPushStats: (stats) ->
logger.debug("connection stats", connectionStats)
@rawStats = stats
@changed()
classify: (holder, field, threshold) ->
value = holder[field]
fieldLevel = field = '-level'
fieldThreshold = threshold[field]
if value? && fieldThreshold?
if fieldThreshold.inverse
if value <= threshold.poor
holder[fieldLevel] = 'poor'
else if value <= threshold.warn
holder[fieldLevel] = 'warn'
else
holder[fieldLevel] = 'good'
else if fieldThreshold.eql
if value == threshold.poor
holder[fieldLevel] = 'poor'
else if value == threshold.warn
holder[fieldLevel] = 'warn'
else
holder[fieldLevel] = 'good'
else
if value >= threshold.poor
holder[fieldLevel] = 'poor'
else if value >= threshold.warn
holder[fieldLevel] = 'warn'
else
holder[fieldLevel] = 'good'
changed: () ->
for participant in @rawStats
# CPU is 0-100
if participant.cpu?
@classify(participant, 'cpu', SystemThresholds)
network = participant.network
if network?
# audio_bitrate: 256
# net_bitrate: 286.19244384765625
# ping: 0.08024691045284271
# ping_var: 0.6403124332427979
# pkt_loss: 100
# wifi: false
@classify(network, 'audio_bitrate', NetworkThresholds)
@classify(network, 'ping', NetworkThresholds)
@classify(network, 'pkt_loss', NetworkThresholds)
@classify(network, 'wifi', NetworkThresholds)
audio = participant.audio
if audio?
# acpu: 5.148329734802246
# audio_in: "Fast Track"
# audio_in_type: "Core Audio"
# cpu: 22.44668960571289
# framesize: 2.5
# in_latency: 5.020833492279053
# input_iio_jitter: -0.0015926361083984375
# input_jitter: 0.2977011799812317
# input_median: 400.16632080078125
# io_out_latency: "Expected Latency = 9.54 +/- 1.00 ms [Raw/PaBuff/PaRing Latency: 9.54 / 12.04 / 0.00 ms]"
# out_latency: 4.520833492279053
# output_iio_jitter: -0.07366180419921875
# output_jitter: 0.40290364623069763
# output_median: 400.0581970214844
# output_name: 4
# samplerate: 48000
if audio.in_latency? and audio.out_latency?
audio.latency = in_latency + out_latency
@classify(audio, 'audio_in_type', AudioThresholds)
@classify(audio, 'framesize', AudioThresholds)
@classify(audio, 'latency', AudioThresholds)
@classify(audio, 'input_jitter', AudioThresholds)
@classify(audio, 'output_jitter', AudioThresholds)
@stats = @rawStats
@trigger(@stats)
)

View File

@ -731,6 +731,8 @@ VideoActions = @VideoActions
$(document).trigger(EVENTS.SESSION_STARTED, {session: {id: @currentSessionId}}) if document
@handleAutoOpenJamTrack()
@watchBackendStats()
)
.fail((xhr) =>
@updateCurrentSession(null)
@ -762,6 +764,13 @@ VideoActions = @VideoActions
@app.notifyServerError(xhr, 'Unable to Join Session');
)
watchBackendStats: () ->
@backendStatsInterval = window.setInterval((() => (@updateBackendStats())), 1000)
updateBackendStats: () ->
connectionStats = window.jamClient.getConnectionDetail('')
SessionStatsActions.pushStats(connectionStats)
trackChanges: (header, payload) ->
if @currentTrackChanges < payload.track_changes_counter
# we don't have the latest info. try and go get it
@ -1050,6 +1059,10 @@ VideoActions = @VideoActions
@userTracks = null;
@startTime = null;
if @backendStatsInterval?
window.clearInterval(@backendStatsInterval)
@backendStatsInterval = null
if @joinDeferred?.state() == 'resolved'
$(document).trigger(EVENTS.SESSION_ENDED, {session: {id: @currentSessionId}})

View File

@ -119,6 +119,19 @@
}
}
.track-connection-state {
width:20px;
height:20px;
float:left;
cursor:pointer;
text-align: center;
margin-left:10px;
}
.circle {
}
.track-icon-equalizer {
float:left;
cursor: pointer;

View File

@ -69,6 +69,7 @@ module ClientHelper
gon.ftue_maximum_gear_latency = Rails.application.config.ftue_maximum_gear_latency
gon.musician_search_meta = MusicianSearch.search_filter_meta
gon.band_search_meta = BandSearch.search_filter_meta
gon.session_stat_thresholds = Rails.application.config.session_stat_thresholds
# is this the native client or browser?
@nativeClient = is_native_client?

View File

@ -377,5 +377,23 @@ if defined?(Bundler)
config.download_tracker_day_range = 30
config.max_user_ip_address = 10
config.max_multiple_users_same_ip = 2
config.session_stat_thresholds = {
network: {
wifi: {warn: true, poor: true, eql: true},
audio_bitrate: {warn: 200, poor: 135, inverse:true},
ping: {warn: 40, poor: 70},
pkt_loss: {warn: 3, poor: 10}
},
system: {
cpu: {warn: 70, poor:85}
},
audio: {
audio_in_type: {warn: 'WDM', poor: 'WDM', eql: true},
framesize: {warn: 2.6, poor: 2.6},
latency: {warn: 10, poor: 20},
input_jitter: {warn: 0.5, poor: 1},
output_jitter: {warn: 0.5, poor: 1},
}
}
end
end