wackamole 0.0.6 → 0.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/History.txt +8 -1
- data/lib/app.rb +1 -1
- data/lib/controllers/dashboard.rb +17 -9
- data/lib/controllers/features.rb +1 -5
- data/lib/controllers/logs.rb +3 -12
- data/lib/controllers/mission.rb +15 -0
- data/lib/controllers/users.rb +1 -7
- data/lib/helpers/mission_helper.rb +1 -4
- data/lib/wackamole/models/mission.rb +18 -20
- data/lib/wackamole/models/mole_info.rb +36 -59
- data/lib/wackamole/models/search_filter.rb +15 -2
- data/lib/wackamole.rb +1 -1
- data/public/javascripts/application.js +48 -7
- data/public/stylesheets/wackamole.css +4 -4
- data/spec/models/moled_info_spec.rb +1 -1
- data/views/dashboard/_report.erb +31 -48
- data/views/dashboard/index.erb +1 -1
- data/views/dashboard/refresh_js.erb +2 -1
- data/views/mission/_report.erb +2 -2
- data/views/shared/_filter.erb +17 -7
- data/views/shared/_timestamp.erb +1 -1
- metadata +2 -2
data/History.txt
CHANGED
@@ -17,4 +17,11 @@
|
|
17
17
|
* Add set_indexes script. Use to setup mole db indexes
|
18
18
|
|
19
19
|
=== 0.0.5 / 2010-02-08
|
20
|
-
* Added debug
|
20
|
+
* Added debug
|
21
|
+
|
22
|
+
=== 0.0.6 / 2010-02-08
|
23
|
+
* Bug fixes
|
24
|
+
|
25
|
+
=== 0.0.7 /2010-02-21
|
26
|
+
* Added drilldown on dashboard
|
27
|
+
* Bug fixes and clean up
|
data/lib/app.rb
CHANGED
@@ -46,7 +46,7 @@ configure do
|
|
46
46
|
:server => "%s:%d/%s/%s" % ['localhost', '27017', 'wackamole_ses', 'sessions'],
|
47
47
|
:log_level => :error
|
48
48
|
end
|
49
|
-
|
49
|
+
Wackamole::Control.init_config( default_config, Sinatra::Application.environment.to_s )
|
50
50
|
end
|
51
51
|
|
52
52
|
# -----------------------------------------------------------------------------
|
@@ -8,7 +8,7 @@ module Dashboard
|
|
8
8
|
get '/dashboard/:app_name/:stage' do
|
9
9
|
Wackamole::Control.switch_mole_db!( params[:app_name].downcase, params[:stage] )
|
10
10
|
|
11
|
-
|
11
|
+
@info = Wackamole::MoledInfo.collect_dashboard_info( @updated_on )
|
12
12
|
|
13
13
|
# Reset app info
|
14
14
|
load_app_info
|
@@ -22,21 +22,29 @@ module Dashboard
|
|
22
22
|
# ---------------------------------------------------------------------------
|
23
23
|
# Refresh dashboard
|
24
24
|
get '/dashboard/refresh' do
|
25
|
-
|
25
|
+
@info = Wackamole::MoledInfo.collect_dashboard_info( @updated_on )
|
26
|
+
|
26
27
|
erb :'dashboard/refresh_js', :layout => false
|
27
28
|
end
|
28
|
-
|
29
|
+
|
29
30
|
# ---------------------------------------------------------------------------
|
30
|
-
get '/dashboard/logs/:
|
31
|
-
|
32
|
-
load_app_details
|
33
|
-
load_app_info
|
34
|
-
|
31
|
+
get '/dashboard/logs/:type/:hour/' do
|
32
|
+
# Reset filter
|
35
33
|
filter = Wackamole::SearchFilter.new
|
36
34
|
filter.mole_type( params[:type].to_i )
|
37
|
-
|
35
|
+
filter.hour = params[:hour].to_i
|
38
36
|
session[:filter] = filter
|
37
|
+
|
39
38
|
redirect '/logs/1'
|
40
39
|
end
|
41
40
|
|
41
|
+
# ---------------------------------------------------------------------------
|
42
|
+
get '/dashboard/users/:hour/' do
|
43
|
+
# Reset filter
|
44
|
+
filter = Wackamole::SearchFilter.new
|
45
|
+
filter.hour = params[:hour].to_i
|
46
|
+
session[:filter] = filter
|
47
|
+
|
48
|
+
redirect '/users/1'
|
49
|
+
end
|
42
50
|
end
|
data/lib/controllers/features.rb
CHANGED
@@ -3,10 +3,7 @@ module Features
|
|
3
3
|
# ---------------------------------------------------------------------------
|
4
4
|
# paginate top features
|
5
5
|
get "/features/:page" do
|
6
|
-
page
|
7
|
-
|
8
|
-
puts @filter.inspect
|
9
|
-
|
6
|
+
page = params[:page] ? params[:page].to_i : 1
|
10
7
|
@features = Wackamole::Feature.paginate_tops( @filter.to_conds, page )
|
11
8
|
@search_path = "/features/search"
|
12
9
|
@filter_path = "/features/filter"
|
@@ -38,7 +35,6 @@ puts @filter.inspect
|
|
38
35
|
post "/features/filter" do
|
39
36
|
@filter.from_options( params[:filter] )
|
40
37
|
session[:filter] = @filter
|
41
|
-
puts "Setting #{session[:filter].inspect}"
|
42
38
|
@features = Wackamole::Feature.paginate_tops( @filter.to_conds )
|
43
39
|
erb :"features/filter.js", :layout => false
|
44
40
|
end
|
data/lib/controllers/logs.rb
CHANGED
@@ -21,7 +21,7 @@ module Logs
|
|
21
21
|
@filter.search_terms = params[:search_filter][:search_terms]
|
22
22
|
@logs = Wackamole::Log.paginate( @filter.to_conds )
|
23
23
|
rescue => boom
|
24
|
-
puts boom
|
24
|
+
# puts boom
|
25
25
|
flash_it!( :error, boom )
|
26
26
|
@logs = [].paginate
|
27
27
|
end
|
@@ -43,16 +43,7 @@ module Logs
|
|
43
43
|
@filter.from_options( params[:filter] )
|
44
44
|
session[:filter] = @filter
|
45
45
|
|
46
|
-
|
47
|
-
|
48
|
-
# end
|
49
|
-
# puts "Filter logs %5.4f" % elapsed
|
50
|
-
|
51
|
-
out = nil
|
52
|
-
# elapsed = Benchmark.realtime do
|
53
|
-
out = erb :"logs/filter.js", :layout => false
|
54
|
-
# end
|
55
|
-
# puts "Render logs %5.4f" % elapsed
|
56
|
-
out
|
46
|
+
@logs = Wackamole::Log.paginate( @filter.to_conds )
|
47
|
+
erb :"logs/filter.js", :layout => false
|
57
48
|
end
|
58
49
|
end
|
data/lib/controllers/mission.rb
CHANGED
@@ -26,6 +26,21 @@ module Mission
|
|
26
26
|
erb :'/mission/refresh_js', :layout => false
|
27
27
|
end
|
28
28
|
|
29
|
+
get '/mission/logs/:app_name/:stage/:type' do
|
30
|
+
Wackamole::Control.switch_mole_db!( params[:app_name].downcase, params[:stage] )
|
31
|
+
|
32
|
+
# Set app info
|
33
|
+
@app_info = Wackamole::Feature.get_app_info
|
34
|
+
session[:app_info] = @app_info
|
35
|
+
|
36
|
+
# Reset filter
|
37
|
+
filter = Wackamole::SearchFilter.new
|
38
|
+
filter.mole_type( params[:type].to_i )
|
39
|
+
session[:filter] = filter
|
40
|
+
|
41
|
+
redirect '/logs/1'
|
42
|
+
end
|
43
|
+
|
29
44
|
# # ---------------------------------------------------------------------------
|
30
45
|
# get '/mission/fixed/:app/:env/:type' do
|
31
46
|
# Wackamole::Mission.reset!( params[:app], params[:env], params[:type] )
|
data/lib/controllers/users.rb
CHANGED
@@ -4,12 +4,7 @@ module Users
|
|
4
4
|
# Paginate top users
|
5
5
|
get "/users/:page" do
|
6
6
|
page = params[:page] ? params[:page].to_i : 1
|
7
|
-
|
8
|
-
puts "User filter", @filter.inspect
|
9
|
-
elapsed = Benchmark.realtime do
|
10
|
-
@users = Wackamole::User.paginate_tops( @filter.to_conds, page )
|
11
|
-
end
|
12
|
-
puts "Find users %5.4f" % elapsed
|
7
|
+
@users = Wackamole::User.paginate_tops( @filter.to_conds, page )
|
13
8
|
|
14
9
|
@search_path = "/users/search"
|
15
10
|
@filter_path = "/users/filter"
|
@@ -41,7 +36,6 @@ puts "Find users %5.4f" % elapsed
|
|
41
36
|
post "/users/filter" do
|
42
37
|
@filter.from_options( params[:filter] )
|
43
38
|
session[:filter] = @filter
|
44
|
-
puts "Setting user filter #{session[:filter].inspect}"
|
45
39
|
@users = Wackamole::User.paginate_tops( @filter.to_conds )
|
46
40
|
erb :"users/filter.js", :layout => false
|
47
41
|
end
|
@@ -15,10 +15,7 @@ module MissionHelper
|
|
15
15
|
last_tick = last_tick || Chronic.parse( '1 minute ago' )
|
16
16
|
session[:last_tick] = Time.now
|
17
17
|
|
18
|
-
|
19
|
-
@reports = Wackamole::Mission.rollups( last_tick.utc, reset )
|
20
|
-
end
|
21
|
-
puts "Rollups %5.4f" % elapsed
|
18
|
+
@reports = Wackamole::Mission.rollups( last_tick.utc, reset )
|
22
19
|
end
|
23
20
|
|
24
21
|
# -------------------------------------------------------------------------
|
@@ -31,27 +31,25 @@ module Wackamole
|
|
31
31
|
def self.count_logs( now=nil, single_day=false )
|
32
32
|
counts = {}
|
33
33
|
conds = gen_conds( now, single_day )
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
end
|
46
|
-
row = counts[app_name][env]
|
47
|
-
[Rackamole.feature, Rackamole.perf, Rackamole.fault].each do |t|
|
48
|
-
conds[:typ] = t
|
49
|
-
logs = logs_cltn.find( conds, :fields => [:_id] )
|
50
|
-
row[t] = logs.count
|
51
|
-
end
|
34
|
+
|
35
|
+
Wackamole::Control.mole_databases.each do |db_name|
|
36
|
+
db = Wackamole::Control.db( db_name )
|
37
|
+
app_name, env = Wackamole::Control.extract_app_info( db_name )
|
38
|
+
logs_cltn = db['logs']
|
39
|
+
|
40
|
+
totals = { Rackamole.feature => 0, Rackamole.perf => 0, Rackamole.fault => 0 }
|
41
|
+
if counts[app_name]
|
42
|
+
counts[app_name][env] = totals
|
43
|
+
else
|
44
|
+
counts[app_name] = { env => totals }
|
52
45
|
end
|
53
|
-
|
54
|
-
|
46
|
+
row = counts[app_name][env]
|
47
|
+
[Rackamole.feature, Rackamole.perf, Rackamole.fault].each do |t|
|
48
|
+
conds[:typ] = t
|
49
|
+
logs = logs_cltn.find( conds, :fields => [:_id] )
|
50
|
+
row[t] = logs.count
|
51
|
+
end
|
52
|
+
end
|
55
53
|
counts
|
56
54
|
end
|
57
55
|
|
@@ -12,52 +12,40 @@ module Wackamole
|
|
12
12
|
# TODO - PERF - try just using cursor vs to_a
|
13
13
|
def self.collect_dashboard_info( now )
|
14
14
|
info = {}
|
15
|
-
|
16
|
-
|
17
|
-
|
15
|
+
|
16
|
+
info[:total_users] = users_cltn.count
|
17
|
+
info[:total_features] = features_cltn.count
|
18
|
+
info[:perf_load] = 0
|
19
|
+
info[:fault_load] = 0
|
18
20
|
|
19
|
-
# Fetch
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
end
|
24
|
-
info[:total_users] = users_cltn.count
|
25
|
-
info[:user_load] = users.size
|
21
|
+
# Fetch day logs
|
22
|
+
day_logs = logs_cltn.find( { :did => now.utc.to_date_id.to_s },
|
23
|
+
:fields => [:typ, :fid, :tid, :did, :uid],
|
24
|
+
:sort => [ [:tid => Mongo::ASCENDING] ] )
|
26
25
|
|
27
|
-
# Fetch features for this hour
|
28
|
-
features = day_logs.inject( Set.new ) do |set,log|
|
29
|
-
set << log['fid'].to_s if log['tid'] =~ /^#{"%02d" % now.hour}/
|
30
|
-
set
|
31
|
-
end
|
32
|
-
info[:total_features] = features_cltn.count
|
33
|
-
info[:feature_load] = features.size
|
34
|
-
|
35
|
-
info[:perf_load] = day_logs.inject(0) do |count,log|
|
36
|
-
if log['tid'] =~ /^#{"%02d" % now.hour}/
|
37
|
-
count += (log['typ'] == Rackamole.perf ? 1 : 0 )
|
38
|
-
end
|
39
|
-
count
|
40
|
-
end
|
41
|
-
info[:fault_load] = day_logs.inject(0) do |count,log|
|
42
|
-
if log['tid'] =~ /^#{"%02d" % now.hour}/
|
43
|
-
count += (log['typ'] == Rackamole.fault ? 1 : 0 )
|
44
|
-
end
|
45
|
-
count
|
46
|
-
end
|
47
|
-
|
48
26
|
# Count all logs per hourly time period
|
27
|
+
users = Set.new
|
28
|
+
features = Set.new
|
29
|
+
local_time = now.clone.localtime
|
49
30
|
hours = (0...24).to_a
|
50
31
|
hour_info = hours.inject(OrderedHash.new) { |res,hour| res[hour] = { :user => 0, :feature => 0, :perf => 0, :fault => 0 };res }
|
51
32
|
user_per_hour = {}
|
52
33
|
day_logs.each do |log|
|
53
34
|
date_tokens = log['did'].match( /(\d{4})(\d{2})(\d{2})/ ).captures
|
54
|
-
time_tokens = log['tid'].match( /(\d{2})(\d{2})(\d{2})/ ).captures
|
55
|
-
|
56
|
-
|
57
|
-
local = utc.localtime
|
35
|
+
time_tokens = log['tid'].match( /(\d{2})(\d{2})(\d{2})/ ).captures
|
36
|
+
log_utc = Time.utc( date_tokens[0], date_tokens[1], date_tokens[2], time_tokens[0], time_tokens[1], time_tokens[2] )
|
37
|
+
local = log_utc.clone.localtime
|
58
38
|
hour = local.hour
|
59
|
-
|
60
|
-
next if
|
39
|
+
|
40
|
+
next if hour > local_time.hour
|
41
|
+
|
42
|
+
if log_utc.hour == now.hour
|
43
|
+
users << log['uid']
|
44
|
+
features << log['fid']
|
45
|
+
info[:fault_load] += 1 if log['typ'] == Rackamole.fault
|
46
|
+
info[:perf_load] += 1 if log['typ'] == Rackamole.perf
|
47
|
+
end
|
48
|
+
|
61
49
|
if user_per_hour[hour]
|
62
50
|
unless user_per_hour[hour].include? log['uid']
|
63
51
|
hour_info[hour][:user] += 1
|
@@ -68,33 +56,22 @@ module Wackamole
|
|
68
56
|
hour_info[hour][:user] += 1
|
69
57
|
end
|
70
58
|
case log['typ']
|
71
|
-
when Rackamole.feature : hour_info[hour][:feature] += 1
|
59
|
+
when Rackamole.feature : hour_info[hour][:feature] += 1
|
72
60
|
when Rackamole.perf : hour_info[hour][:perf] += 1
|
73
61
|
when Rackamole.fault : hour_info[hour][:fault] += 1
|
74
62
|
end
|
75
63
|
end
|
76
|
-
|
77
|
-
|
78
|
-
info[:
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
info[:perf_series] << hash[:perf]
|
86
|
-
info[:feature_series] << hash[:feature]
|
64
|
+
|
65
|
+
info[:user_load] = users.size
|
66
|
+
info[:feature_load] = features.size
|
67
|
+
%w(user fault perf feature).each do |s|
|
68
|
+
k = "#{s}_series".to_sym
|
69
|
+
info[k] = []
|
70
|
+
hour_info.values.map do |hash|
|
71
|
+
info[k] << hash[s.to_sym]
|
72
|
+
end
|
87
73
|
end
|
88
74
|
info
|
89
|
-
end
|
90
|
-
|
91
|
-
# ===========================================================================
|
92
|
-
private
|
93
|
-
|
94
|
-
# -------------------------------------------------------------------------
|
95
|
-
# Makes sure we have some indexes set
|
96
|
-
# BOZO !! Create script to set these up ?
|
97
|
-
def self.ensure_indexes
|
98
|
-
end
|
75
|
+
end
|
99
76
|
end
|
100
77
|
end
|
@@ -3,7 +3,7 @@ require 'chronic'
|
|
3
3
|
module Wackamole
|
4
4
|
class SearchFilter
|
5
5
|
|
6
|
-
attr_accessor :time_frame, :feature_id, :type, :browser_type, :search_terms
|
6
|
+
attr_accessor :time_frame, :feature_id, :type, :browser_type, :search_terms, :hour
|
7
7
|
|
8
8
|
# ---------------------------------------------------------------------------
|
9
9
|
# Ctor
|
@@ -18,6 +18,7 @@ module Wackamole
|
|
18
18
|
@time_frame = SearchFilter.time_frames.first
|
19
19
|
@browser_type = SearchFilter.browser_types.first
|
20
20
|
@type = SearchFilter.mole_types.first
|
21
|
+
@hour = SearchFilter.hourlies.first
|
21
22
|
@search_terms = ""
|
22
23
|
end
|
23
24
|
|
@@ -33,6 +34,12 @@ module Wackamole
|
|
33
34
|
@time_frames ||= ['today', '2 days', '1 week', '2 weeks', '1 month', '3 months', '6 months', '1 year' ]
|
34
35
|
end
|
35
36
|
|
37
|
+
# ---------------------------------------------------------------------------
|
38
|
+
# Available hours
|
39
|
+
def self.hourlies
|
40
|
+
@hourlies ||= ['all'] + (1..23).to_a
|
41
|
+
end
|
42
|
+
|
36
43
|
# ---------------------------------------------------------------------------
|
37
44
|
# Collection of mole types
|
38
45
|
def self.mole_types
|
@@ -107,7 +114,6 @@ module Wackamole
|
|
107
114
|
def from_options( options )
|
108
115
|
return unless options
|
109
116
|
options.each_pair do |k,v|
|
110
|
-
# value = k.index( /_id$/) ? v.to_i : v
|
111
117
|
self.send( "#{k}=", v )
|
112
118
|
end
|
113
119
|
end
|
@@ -135,6 +141,13 @@ module Wackamole
|
|
135
141
|
time = Chronic.parse( time_frame + ( time_frame == SearchFilter.time_frames.first ? "" : " ago" ) )
|
136
142
|
conds[:did] = { '$gte' => time.to_date_id.to_s }
|
137
143
|
|
144
|
+
unless self.hour == 'all'
|
145
|
+
now = Time.now
|
146
|
+
current = "%4d/%02d/%02d %02d:%02d:%02d" % [now.year, now.month, now.day, self.hour, 0, 0]
|
147
|
+
time = Chronic.parse( current ).utc
|
148
|
+
conds[:tid] = /^#{"%02d"%time.hour}.+/
|
149
|
+
end
|
150
|
+
|
138
151
|
unless search_terms.empty?
|
139
152
|
tokens = search_terms.split( ":" ).collect{ |c| c.strip }
|
140
153
|
key = tokens.shift
|
data/lib/wackamole.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
module Wackamole
|
2
2
|
|
3
3
|
# :stopdoc:
|
4
|
-
VERSION = '0.0.
|
4
|
+
VERSION = '0.0.7' unless defined? Wackamole::VERSION
|
5
5
|
LIBPATH = ::File.expand_path(::File.dirname(__FILE__)) + ::File::SEPARATOR unless defined? Wackamole::LIBPATH
|
6
6
|
PATH = ::File.dirname(LIBPATH) + ::File::SEPARATOR unless defined? Wackamole::PATH
|
7
7
|
# :startdoc:
|
@@ -17,12 +17,53 @@ function truncate(str, limit)
|
|
17
17
|
return bits.join('');
|
18
18
|
}
|
19
19
|
|
20
|
-
|
21
|
-
function
|
20
|
+
// Graphs...
|
21
|
+
function gen_load( name, value, total )
|
22
22
|
{
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
23
|
+
var p = Raphael( name, 300, 20 );
|
24
|
+
var range = Math.ceil( ((value/total)*100)/10 );
|
25
|
+
var x = 2;
|
26
|
+
var y = 2;
|
27
|
+
var spacer = 5;
|
28
|
+
|
29
|
+
for( var i=1; i <= range; i++ )
|
30
|
+
{
|
31
|
+
var l = p.rect( x, y, 10, 16, 2 );
|
32
|
+
l.attr( 'fill', 'green' );
|
33
|
+
l.attr( 'gradient', '45-#0f0-#fff' );
|
34
|
+
l.attr( 'stroke-width', 0 );
|
35
|
+
x += 10 + spacer;
|
36
|
+
|
37
|
+
}
|
38
|
+
var text = p.text( 230, 10, Math.ceil((value/total)*100) + '% (' + value + " of " + total + ')' );
|
39
|
+
text.attr( 'fill' , '#434343' );
|
40
|
+
text.attr( 'font-size', 15 );
|
28
41
|
}
|
42
|
+
|
43
|
+
function gen_heat_map( url, id, series, symbol, xs, ys, axisx, axisy )
|
44
|
+
{
|
45
|
+
var r = Raphael( id );
|
46
|
+
var urls = [];
|
47
|
+
|
48
|
+
for( hour in xs ) {
|
49
|
+
var u = url + hour + "/";
|
50
|
+
urls[hour] = u;
|
51
|
+
}
|
52
|
+
|
53
|
+
var chart = r.g.dotchart(0, -10, 620, 60, xs, ys, series, {href: urls, symbol: symbol, max: 10, heat: true, axis: "0 0 1 0", axisxstep: 23, axisystep: 1, axisxlabels: axisx, axisxtype: " ", axisytype: " ", axisylabels: axisy})
|
54
|
+
|
55
|
+
chart.hover( function () {
|
56
|
+
this.tag = this.tag || r.g.tag(this.x, this.y, this.value, 0, this.r + 2).insertBefore(this);
|
57
|
+
this.tag.show();
|
58
|
+
},
|
59
|
+
function () {
|
60
|
+
this.tag && this.tag.hide();
|
61
|
+
}
|
62
|
+
);
|
63
|
+
|
64
|
+
chart.click( function() {
|
65
|
+
// this.tag = this.tag || r.g.tag(this.x, this.y, this.value, 0, this.r + 2).insertBefore(this);
|
66
|
+
// console.log( "Clicked url " + this.href );
|
67
|
+
// return false;
|
68
|
+
})
|
69
|
+
}
|
@@ -549,16 +549,16 @@ ul#summary li p{
|
|
549
549
|
|
550
550
|
|
551
551
|
p#perfs {
|
552
|
-
background: transparent url(/images/perf_small.png) no-repeat
|
552
|
+
background: transparent url(/images/perf_small.png) no-repeat 1px 2px;
|
553
553
|
}
|
554
554
|
p#faults {
|
555
|
-
background: transparent url(/images/fault_small.png) no-repeat
|
555
|
+
background: transparent url(/images/fault_small.png) no-repeat 1px 2px;
|
556
556
|
}
|
557
557
|
p#users {
|
558
|
-
background: transparent url(/images/users.png) no-repeat
|
558
|
+
background: transparent url(/images/users.png) no-repeat 1px 2px;
|
559
559
|
}
|
560
560
|
p#features {
|
561
|
-
background: transparent url(/images/feature.png) no-repeat
|
561
|
+
background: transparent url(/images/feature.png) no-repeat 1px 2px;
|
562
562
|
}
|
563
563
|
|
564
564
|
div.section ul li p.result {
|
@@ -6,7 +6,7 @@ describe Wackamole::MoledInfo do
|
|
6
6
|
Wackamole::Control.init_config( File.join(File.dirname(__FILE__), %w[.. config test.yml]), 'test' )
|
7
7
|
Wackamole::Control.connection.should_not be_nil
|
8
8
|
Wackamole::Control.db( "mole_fred_test_mdb" )
|
9
|
-
@test_time = Chronic.parse( "2010/01/01 01:00:00" )
|
9
|
+
@test_time = Chronic.parse( "2010/01/01 01:00:00" )
|
10
10
|
end
|
11
11
|
|
12
12
|
it "should gather dashboard info correctly" do
|
data/views/dashboard/_report.erb
CHANGED
@@ -10,11 +10,23 @@
|
|
10
10
|
<div id="feature_load" class="load"></div>
|
11
11
|
<li>
|
12
12
|
<p class="status">Performance</p>
|
13
|
-
<p class="result"
|
13
|
+
<p class="result">
|
14
|
+
<% if @info[:perf_load] > 0 %>
|
15
|
+
<%= link_to pluralize( @info[:perf_load], 'issue' ), "/dashboard/logs/#{Rackamole.perf}/", :class => "site_link" %>
|
16
|
+
<% else %>
|
17
|
+
<%=pluralize( @info[:perf_load], 'issue' )%>
|
18
|
+
<% end %>
|
19
|
+
</p>
|
14
20
|
</li>
|
15
21
|
<li>
|
16
22
|
<p class="status">Uncaught Exceptions</p>
|
17
|
-
<p class="result"
|
23
|
+
<p class="result">
|
24
|
+
<% if @info[:fault_load] > 0 %>
|
25
|
+
<%= link_to pluralize( @info[:fault_load], 'issue' ), "/dashboard/logs/#{Rackamole.fault}/", :class => "site_link" %>
|
26
|
+
<% else %>
|
27
|
+
<%=pluralize( @info[:fault_load], 'issue' )%>
|
28
|
+
<% end %>
|
29
|
+
</p>
|
18
30
|
</li>
|
19
31
|
</ul>
|
20
32
|
</div>
|
@@ -47,72 +59,43 @@
|
|
47
59
|
<% end %>
|
48
60
|
</li>
|
49
61
|
<li>
|
50
|
-
<p id="features">
|
62
|
+
<p id="features">Logs</p>
|
51
63
|
<% unless zeroed_series?( @info[:feature_series] ) %>
|
52
64
|
<div class="heat" id="svg_features"></div>
|
53
65
|
<% else %>
|
54
|
-
<p class="no_report">No
|
66
|
+
<p class="no_report">No Logs reported.</p>
|
55
67
|
<% end %>
|
56
68
|
</li>
|
57
69
|
</ul>
|
58
70
|
</div>
|
59
71
|
|
60
|
-
<script>
|
61
|
-
function
|
62
|
-
|
63
|
-
|
64
|
-
var
|
65
|
-
var x = 2;
|
66
|
-
var y = 2;
|
67
|
-
var spacer = 5;
|
68
|
-
|
69
|
-
for( var i=1; i <= range; i++ )
|
70
|
-
{
|
71
|
-
var l = p.rect( x, y, 10, 16, 2 );
|
72
|
-
l.attr( 'fill', 'green' );
|
73
|
-
l.attr( 'gradient', '45-#0f0-#fff' );
|
74
|
-
l.attr( 'stroke-width', 0 );
|
75
|
-
x += 10 + spacer;
|
76
|
-
|
77
|
-
}
|
78
|
-
var text = p.text( 230, 10, Math.ceil((value/total)*100) + '% (' + value + " of " + total + ')' );
|
79
|
-
text.attr( 'fill' , '#434343' );
|
80
|
-
text.attr( 'font-size', 15 );
|
81
|
-
}
|
82
|
-
|
83
|
-
function gen_heat_map( id, series, symbol )
|
84
|
-
{
|
85
|
-
var r = Raphael( id ),
|
86
|
-
xs = <%= (0..23).to_a.to_json %>,
|
72
|
+
<script>
|
73
|
+
$( function() {
|
74
|
+
$('a.dash').addClass( 'current' );
|
75
|
+
|
76
|
+
var xs = <%= (0..23).to_a.to_json %>,
|
87
77
|
ys = <%= y = [];24.times{ y << 1 };y.to_json %>,
|
88
78
|
axisy = <%= %w[Mon].to_json %>,
|
89
79
|
axisx = <%= %w[12am 1 2 3 4 5 6 7 8 9 10 11 12 1 2 3 4 5 6 7 8 9 10 11].to_json %>;
|
90
|
-
|
91
|
-
r.g.dotchart(0, -10, 620, 60, xs, ys, series, {symbol: symbol, max: 10, heat: true, axis: "0 0 1 0", axisxstep: 23, axisystep: 1, axisxlabels: axisx, axisxtype: " ", axisytype: " ", axisylabels: axisy}).hover(function () {
|
92
|
-
this.tag = this.tag || r.g.tag(this.x, this.y, this.value, 0, this.r + 2).insertBefore(this);
|
93
|
-
this.tag.show();
|
94
|
-
}, function () {
|
95
|
-
this.tag && this.tag.hide();
|
96
|
-
});
|
97
|
-
}
|
98
|
-
|
99
|
-
$( function() {
|
100
|
-
$('a.dash').addClass( 'current' );
|
101
80
|
|
102
81
|
gen_load( 'user_load' , <%=@info[:user_load]%>, <%=@info[:total_users]%> );
|
103
82
|
gen_load( 'feature_load', <%=@info[:feature_load]%>, <%=@info[:total_features]%> );
|
104
|
-
|
83
|
+
|
105
84
|
<% unless zeroed_series?( @info[:fault_series] ) %>
|
106
|
-
|
85
|
+
var url = "/dashboard/logs/<%=Rackamole.fault%>/";
|
86
|
+
gen_heat_map( url, 'svg_faults', <%=@info[:fault_series].to_json%>, 'cross' , xs, ys, axisx, axisy );
|
107
87
|
<% end %>
|
108
88
|
<% unless zeroed_series?( @info[:perf_series] ) %>
|
109
|
-
|
89
|
+
var url = "/dashboard/logs/<%=Rackamole.perf%>/";
|
90
|
+
gen_heat_map( url, 'svg_perf', <%=@info[:perf_series].to_json%>, 'diamond', xs, ys, axisx, axisy );
|
110
91
|
<% end %>
|
111
92
|
<% unless zeroed_series?( @info[:user_series] ) %>
|
112
|
-
|
93
|
+
var url = "/dashboard/users/";
|
94
|
+
gen_heat_map( url, 'svg_users', <%=@info[:user_series].to_json%>, 'disc', xs, ys, axisx, axisy );
|
113
95
|
<% end %>
|
114
|
-
<% unless zeroed_series?( @info[:
|
115
|
-
|
96
|
+
<% unless zeroed_series?( @info[:feature_series] ) %>
|
97
|
+
var url = "/dashboard/logs/<%=Rackamole.feature%>/";
|
98
|
+
gen_heat_map( url, 'svg_features', <%=@info[:feature_series].to_json%>, 'flower', xs, ys, axisx, axisy );
|
116
99
|
<% end %>
|
117
100
|
});
|
118
101
|
</script>
|
data/views/dashboard/index.erb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
-
$('
|
1
|
+
$('span#timestamp').html( "<%=escape_javascript(partial(:'shared/timestamp'))%>" );
|
2
|
+
$("span#timestamp").effect( 'pulsate', { times:1 }, 500 );
|
2
3
|
|
3
4
|
$('div#dash').html( "<%=escape_javascript(partial(:'dashboard/report'))%>" );
|
data/views/mission/_report.erb
CHANGED
@@ -28,7 +28,7 @@ table#mission tr.div {
|
|
28
28
|
<th width="25%">application</th>
|
29
29
|
<th width="10%">environment</th>
|
30
30
|
<th width="20%">to date</th>
|
31
|
-
<th width="20%">
|
31
|
+
<th width="20%">24 hours</th>
|
32
32
|
<th width="20%">last tick</th>
|
33
33
|
</tr>
|
34
34
|
</thead>
|
@@ -48,7 +48,7 @@ table#mission tr.div {
|
|
48
48
|
<% clazz = ( (count > 0 and %w(last_tick today).include?(period)) ? assign_class( type, count ) : nil) %>
|
49
49
|
<td width="25px">
|
50
50
|
<% if( %w(last_tick today).include?( period ) and count > 0 ) %>
|
51
|
-
<%= link_to Wackamole::Mission.to_type_name(type), "/
|
51
|
+
<%= link_to Wackamole::Mission.to_type_name(type), "/mission/logs/#{app_name}/#{env}/#{type}", :class => "site_link" %>:
|
52
52
|
<% else %>
|
53
53
|
<%=Wackamole::Mission.to_type_name(type)%>:
|
54
54
|
<% end %>
|
data/views/shared/_filter.erb
CHANGED
@@ -1,5 +1,13 @@
|
|
1
1
|
<div id="filters" class="corners">
|
2
2
|
<form id="filter_form">
|
3
|
+
<fieldset id="submit">
|
4
|
+
<label>
|
5
|
+
|
6
|
+
<input type="submit" name="commit" value="Filter"/>
|
7
|
+
<%= image_tag 'loading.gif', :border => '0', :size => '24x24', :id => 'loading' %>
|
8
|
+
</label>
|
9
|
+
</fieldset>
|
10
|
+
|
3
11
|
<fieldset class="inline">
|
4
12
|
<label for="time_frame">
|
5
13
|
Time range:
|
@@ -9,6 +17,15 @@
|
|
9
17
|
</label>
|
10
18
|
</fieldset>
|
11
19
|
|
20
|
+
<fieldset class="inline">
|
21
|
+
<label for="hourly_frame">
|
22
|
+
Hour of Day:
|
23
|
+
<select id="hourly_frame" name="filter[hour]">
|
24
|
+
<%= options_for_select Wackamole::SearchFilter.hourlies, @filter.hour %>
|
25
|
+
</select>
|
26
|
+
</label>
|
27
|
+
</fieldset>
|
28
|
+
|
12
29
|
<fieldset class="inline">
|
13
30
|
<label for="type">
|
14
31
|
Type:
|
@@ -35,13 +52,6 @@
|
|
35
52
|
</select>
|
36
53
|
</label>
|
37
54
|
</fieldset>
|
38
|
-
<fieldset id="submit">
|
39
|
-
<label>
|
40
|
-
|
41
|
-
<input type="submit" name="commit" value="Filter"/>
|
42
|
-
<%= image_tag 'loading.gif', :border => '0', :size => '24x24', :id => 'loading' %>
|
43
|
-
</label>
|
44
|
-
</fieldset>
|
45
55
|
</form>
|
46
56
|
</div>
|
47
57
|
|
data/views/shared/_timestamp.erb
CHANGED
@@ -1 +1 @@
|
|
1
|
-
<%= @updated_on.strftime( "%m/%d/%y %H:%M:%S") %>
|
1
|
+
<%= @updated_on.clone.localtime.strftime( "%m/%d/%y %H:%M:%S") %>
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: wackamole
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Fernand Galiana
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2010-02-
|
12
|
+
date: 2010-02-21 00:00:00 -07:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|