Extend dashboard stats

This PR includes the following changes:

  - everything at the /dashboard/stats/vmpooler/numbers API endpoint has
  been moved to /status, and stats-vmpooler-numbers.js is now looking to
  /status for it's metrics

  - added '.extra'-classed metrics to stats-vmpooler-numbers.js to pull
  in daily clone totals, average clone time, etc.

  - dashboard.css includes an @media query to display the extra metrics
  if the dashboard's max-width exceeds 1500px
This commit is contained in:
Scott Schneider 2015-02-20 11:23:48 -08:00
parent 351bd07d91
commit 0253008a3f
3 changed files with 148 additions and 30 deletions

View file

@ -43,31 +43,6 @@ module Vmpooler
} }
end end
get '/dashboard/stats/vmpooler/numbers/?' do
result = Hash.new
result['pending'] = 0
result['cloning'] = 0
result['booting'] = 0
result['ready'] = 0
result['running'] = 0
result['completed'] = 0
$config[:pools].each do |pool|
result['pending'] += $redis.scard('vmpooler__pending__' + pool['name'])
result['ready'] += $redis.scard('vmpooler__ready__' + pool['name'])
result['running'] += $redis.scard('vmpooler__running__' + pool['name'])
result['completed'] += $redis.scard('vmpooler__completed__' + pool['name'])
end
result['cloning'] = $redis.get('vmpooler__tasks__clone')
result['booting'] = result['pending'].to_i - result['cloning'].to_i
result['booting'] = 0 if result['booting'] < 0
result['total'] = result['pending'].to_i + result['ready'].to_i + result['running'].to_i + result['completed'].to_i
content_type :json
JSON.pretty_generate(result)
end
get '/dashboard/stats/vmpooler/pool/?' do get '/dashboard/stats/vmpooler/pool/?' do
result = Hash.new result = Hash.new
@ -178,11 +153,18 @@ module Vmpooler
result = {} result = {}
result['status'] = 1
result['pending'] = 0
result['cloning'] = 0
result['booting'] = 0
result['ready'] = 0
result['running'] = 0
result['completed'] = 0
result['capacity_current'] = 0 result['capacity_current'] = 0
result['capacity_total'] = 0 result['capacity_total'] = 0
result['status'] = 1
$config[:pools].each do |pool| $config[:pools].each do |pool|
pool['capacity_current'] = $redis.scard('vmpooler__ready__' + pool['name']).to_i pool['capacity_current'] = $redis.scard('vmpooler__ready__' + pool['name']).to_i
@ -193,6 +175,11 @@ module Vmpooler
result['empty'] ||= [] result['empty'] ||= []
result['empty'].push(pool['name']) result['empty'].push(pool['name'])
end end
result['pending'] += $redis.scard('vmpooler__pending__' + pool['name'])
result['ready'] += $redis.scard('vmpooler__ready__' + pool['name'])
result['running'] += $redis.scard('vmpooler__running__' + pool['name'])
result['completed'] += $redis.scard('vmpooler__completed__' + pool['name'])
end end
if result['empty'] if result['empty']
@ -201,12 +188,17 @@ module Vmpooler
result['capacity_percent'] = (result['capacity_current'].to_f / result['capacity_total'].to_f) * 100.0 result['capacity_percent'] = (result['capacity_current'].to_f / result['capacity_total'].to_f) * 100.0
result['cloning'] = $redis.get('vmpooler__tasks__clone')
result['booting'] = result['pending'].to_i - result['cloning'].to_i
result['booting'] = 0 if result['booting'] < 0
result['total'] = result['pending'].to_i + result['ready'].to_i + result['running'].to_i + result['completed'].to_i
result['clone_total'] = $redis.hlen('vmpooler__clone__' + Date.today.to_s) result['clone_total'] = $redis.hlen('vmpooler__clone__' + Date.today.to_s)
if result['clone_total'] > 0 if result['clone_total'] > 0
result['clone_average'] = $redis.hvals('vmpooler__clone__' + Date.today.to_s).map(&:to_f).reduce(:+) / result['clone_total'] result['clone_average'] = $redis.hvals('vmpooler__clone__' + Date.today.to_s).map(&:to_f).reduce(:+) / result['clone_total']
end end
result['uptime'] = Time.now - $config[:uptime] result['uptime'] = Time.now - $config[:uptime] if $config[:uptime]
JSON.pretty_generate(Hash[result.sort_by { |k, _v| k }]) JSON.pretty_generate(Hash[result.sort_by { |k, _v| k }])
end end

View file

@ -1,3 +1,9 @@
@media screen and (max-width:1500px) {
#stats-vmpooler-numbers .extra {
display: none;
}
}
body, body,
#content { #content {
background: #fff; background: #fff;

View file

@ -1,4 +1,4 @@
var numbers_url = '/dashboard/stats/vmpooler/numbers'; var numbers_url = '/status';
var numbers_width = 110; var numbers_width = 110;
var numbers_height = 50; var numbers_height = 50;
@ -29,6 +29,126 @@ d3.json( numbers_url,
$( '#stats-vmpooler-numbers' ).empty(); $( '#stats-vmpooler-numbers' ).empty();
stats_vmpooler_numbers__svg[ 'clone_total' ] = d3.select( '#stats-vmpooler-numbers' )
.append( 'svg' )
.style( 'margin', '15px 0px 0px 0px' )
.style( 'padding', '0px 10px 20px 10px' )
.style( 'float', 'right' )
.attr( 'class', 'extra' )
.attr( 'width', numbers_width + 'px' )
.attr( 'height', numbers_height + 'px' );
stats_vmpooler_numbers__svg[ 'clone_total' ]
.append( 'text' )
.text(
( 'cloned today' )
)
.attr( {
'text-anchor': 'end',
'x': numbers_width,
'y': numbers_height,
'font-face': '\'PT Sans\', sans-serif',
'font-size': '12px',
'font-weight': 'bold',
'fill': '#888'
} );
stats_vmpooler_numbers__svg[ 'clone_total' ]
.append( 'text' )
.text(
( stats_vmpooler_numbers__data__live[ 'clone_total' ] )
)
.attr( {
'text-anchor': 'end',
'x': numbers_width,
'y': '36',
'font-face': '\'PT Sans\', sans-serif',
'font-weight': 'bold',
'font-size': '50px',
'letter-spacing': '-0.05em',
'fill': '#444'
} );
stats_vmpooler_numbers__svg[ 'clone_average' ] = d3.select( '#stats-vmpooler-numbers' )
.append( 'svg' )
.style( 'margin', '15px 0px 0px 0px' )
.style( 'padding', '0px 10px 20px 10px' )
.style( 'float', 'right' )
.attr( 'class', 'extra' )
.attr( 'width', numbers_width + 'px' )
.attr( 'height', numbers_height + 'px' );
stats_vmpooler_numbers__svg[ 'clone_average' ]
.append( 'text' )
.text(
( 'clone time average' )
)
.attr( {
'text-anchor': 'end',
'x': numbers_width,
'y': numbers_height,
'font-face': '\'PT Sans\', sans-serif',
'font-size': '12px',
'font-weight': 'bold',
'fill': '#888'
} );
stats_vmpooler_numbers__svg[ 'clone_average' ]
.append( 'text' )
.text(
( stats_vmpooler_numbers__data__live[ 'clone_average' ].toFixed(1) + 's' )
)
.attr( {
'text-anchor': 'end',
'x': numbers_width,
'y': '36',
'font-face': '\'PT Sans\', sans-serif',
'font-weight': 'bold',
'font-size': '50px',
'letter-spacing': '-0.05em',
'fill': '#444'
} );
stats_vmpooler_numbers__svg[ 'capacity' ] = d3.select( '#stats-vmpooler-numbers' )
.append( 'svg' )
.style( 'margin', '15px 0px 0px 0px' )
.style( 'padding', '0px 10px 20px 10px' )
.style( 'float', 'right' )
.attr( 'class', 'extra' )
.attr( 'width', numbers_width + 'px' )
.attr( 'height', numbers_height + 'px' );
stats_vmpooler_numbers__svg[ 'capacity' ]
.append( 'text' )
.text(
( 'capacity percent' )
)
.attr( {
'text-anchor': 'end',
'x': numbers_width,
'y': numbers_height,
'font-face': '\'PT Sans\', sans-serif',
'font-size': '12px',
'font-weight': 'bold',
'fill': '#888'
} );
stats_vmpooler_numbers__svg[ 'capacity' ]
.append( 'text' )
.text(
( stats_vmpooler_numbers__data__live[ 'capacity_percent' ] )
)
.attr( {
'text-anchor': 'end',
'x': numbers_width,
'y': '36',
'font-face': '\'PT Sans\', sans-serif',
'font-weight': 'bold',
'font-size': '50px',
'letter-spacing': '-0.05em',
'fill': '#444'
} );
stats_vmpooler_numbers__svg[ 'total' ] = d3.select( '#stats-vmpooler-numbers' ) stats_vmpooler_numbers__svg[ 'total' ] = d3.select( '#stats-vmpooler-numbers' )
.append( 'svg' ) .append( 'svg' )
.style( 'margin', '15px 0px 0px 0px' ) .style( 'margin', '15px 0px 0px 0px' )
@ -40,7 +160,7 @@ d3.json( numbers_url,
stats_vmpooler_numbers__svg[ 'total' ] stats_vmpooler_numbers__svg[ 'total' ]
.append( 'text' ) .append( 'text' )
.text( .text(
( 'total VMs' ) ( 'total # of VMs' )
) )
.attr( { .attr( {
'text-anchor': 'end', 'text-anchor': 'end',