wackamole 0.0.9 → 0.1.2
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 +4 -1
- data/README.rdoc +17 -17
- data/Rakefile +1 -1
- data/bin/wackamole +5 -3
- data/lib/app.rb +13 -13
- data/lib/controllers/dashboard.rb +7 -2
- data/lib/controllers/features.rb +1 -1
- data/lib/controllers/logs.rb +20 -1
- data/lib/controllers/mission.rb +7 -8
- data/lib/controllers/session.rb +0 -1
- data/lib/controllers/users.rb +5 -1
- data/lib/helpers/dashboard_helper.rb +7 -2
- data/lib/helpers/flash_helper.rb +0 -1
- data/lib/helpers/main_helper.rb +6 -0
- data/lib/helpers/session_helper.rb +9 -6
- data/lib/wackamole.rb +1 -1
- data/lib/wackamole/models/control.rb +58 -31
- data/lib/wackamole/models/feature.rb +1 -1
- data/lib/wackamole/models/log.rb +1 -2
- data/lib/wackamole/models/mission.rb +49 -46
- data/lib/wackamole/models/mole_info.rb +4 -5
- data/lib/wackamole/models/search_filter.rb +2 -2
- data/lib/wackamole/models/user.rb +1 -1
- data/public/stylesheets/wackamole.css +41 -14
- data/spec/config/test.yml +4 -3
- data/spec/data/fixtures.rb +92 -92
- data/spec/spec_helper.rb +2 -1
- data/spec/wackamole/models/control_spec.rb +27 -33
- data/spec/wackamole/models/feature_spec.rb +19 -20
- data/spec/wackamole/models/log_spec.rb +2 -3
- data/spec/wackamole/models/mission_spec.rb +16 -18
- data/spec/wackamole/models/moled_info_spec.rb +9 -10
- data/spec/wackamole/models/search_filter_spec.rb +4 -5
- data/spec/wackamole/models/user_spec.rb +2 -3
- data/views/features/_rows.erb +1 -1
- data/views/layout.erb +18 -26
- data/views/logs/show.erb +6 -4
- data/views/mission/_report.erb +39 -39
- data/views/users/_rows.erb +2 -2
- metadata +11 -11
@@ -19,7 +19,7 @@ module Wackamole
|
|
19
19
|
# ---------------------------------------------------------------------------
|
20
20
|
# Paginate top features
|
21
21
|
def self.paginate_tops( conds, page=1, page_size=default_page_size )
|
22
|
-
tops = logs_cltn.group( [:fid], conds, { :count => 0 }, 'function(obj,prev) { prev.count += 1}'
|
22
|
+
tops = logs_cltn.group( [:fid], conds, { :count => 0 }, 'function(obj,prev) { prev.count += 1}' )
|
23
23
|
|
24
24
|
all_features = features_cltn.find( {}, :fields => [:_id] )
|
25
25
|
feature_ids = all_features.map{ |f| f['_id'] }
|
data/lib/wackamole/models/log.rb
CHANGED
@@ -13,8 +13,7 @@ module Wackamole
|
|
13
13
|
|
14
14
|
# ---------------------------------------------------------------------------
|
15
15
|
# Fetch all logs matching the given condition
|
16
|
-
def self.paginate( conds, page=1, page_size=default_page_size )
|
17
|
-
puts conds.inspect
|
16
|
+
def self.paginate( conds, page=1, page_size=default_page_size )
|
18
17
|
matching = logs_cltn.find( conds )
|
19
18
|
WillPaginate::Collection.create( page, page_size, matching.count ) do |pager|
|
20
19
|
pager.replace( logs_cltn.find( conds,
|
@@ -7,60 +7,63 @@ module Wackamole
|
|
7
7
|
# -----------------------------------------------------------------------
|
8
8
|
# Pick up moled application pulse
|
9
9
|
def self.pulse( last_tick )
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
now = now.clone.utc
|
25
|
-
date_id = now.to_date_id.to_s
|
26
|
-
time_id = now.to_time_id
|
27
|
-
conds[:did] = { '$gte' => date_id }
|
28
|
-
conds[:tid] = { '$gte' => time_id }
|
10
|
+
zones = {}
|
11
|
+
Wackamole::Control.zones.each do |zone|
|
12
|
+
zones[zone] = {}
|
13
|
+
Wackamole::Control.mole_databases( zone ).each do |db_name|
|
14
|
+
db = Wackamole::Control.db( zone, db_name )
|
15
|
+
app_name, env = Wackamole::Control.extract_app_info( db_name )
|
16
|
+
logs_cltn = db['logs']
|
17
|
+
|
18
|
+
zones[zone][app_name] = {} unless zones[zone][app_name]
|
19
|
+
zones[zone][app_name][env] = {} unless zones[zone][app_name][env]
|
20
|
+
|
21
|
+
zones[zone][app_name][env][:to_date] = count_logs( logs_cltn )
|
22
|
+
zones[zone][app_name][env][:today] = count_logs( logs_cltn, last_tick, true )
|
23
|
+
zones[zone][app_name][env][:last_tick] = count_logs( logs_cltn, last_tick )
|
29
24
|
end
|
30
25
|
end
|
31
|
-
|
26
|
+
zones
|
32
27
|
end
|
33
|
-
|
34
|
-
#
|
35
|
-
|
36
|
-
def self.count_logs( now=nil, single_day=false )
|
37
|
-
counts = {}
|
38
|
-
conds = gen_conds( now, single_day )
|
28
|
+
|
29
|
+
# =========================================================================
|
30
|
+
private
|
39
31
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
totals = {
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
end
|
51
|
-
row = counts[app_name][env]
|
32
|
+
# -----------------------------------------------------------------------
|
33
|
+
# Compute mole counts for each moled apps
|
34
|
+
def self.count_logs( logs_cltn, now=nil, single_day=false )
|
35
|
+
conds = gen_conds( now, single_day )
|
36
|
+
# puts conds.inspect
|
37
|
+
totals = {
|
38
|
+
Rackamole.feature => 0,
|
39
|
+
Rackamole.perf => 0,
|
40
|
+
Rackamole.fault => 0
|
41
|
+
}
|
52
42
|
[Rackamole.feature, Rackamole.perf, Rackamole.fault].each do |t|
|
53
43
|
conds[:typ] = t
|
54
|
-
|
55
|
-
row[t] = logs.count
|
44
|
+
totals[t] = logs_cltn.find( conds, :fields => [:_id] ).count
|
56
45
|
end
|
46
|
+
totals
|
57
47
|
end
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
48
|
+
|
49
|
+
# -----------------------------------------------------------------------
|
50
|
+
# generates mole logs conditons
|
51
|
+
def self.gen_conds( now, single_day )
|
52
|
+
conds = {}
|
53
|
+
if now
|
54
|
+
if single_day
|
55
|
+
conds = SearchFilter.time_conds( now, 0 )
|
56
|
+
else
|
57
|
+
now = now.clone.utc
|
58
|
+
date_id = now.to_date_id.to_s
|
59
|
+
time_id = now.to_time_id
|
60
|
+
conds[:did] = { '$gte' => date_id }
|
61
|
+
conds[:tid] = { '$gte' => time_id }
|
62
|
+
end
|
63
|
+
end
|
64
|
+
conds
|
65
|
+
end
|
66
|
+
|
64
67
|
# -----------------------------------------------------------------------
|
65
68
|
# Map rackamole types to report types
|
66
69
|
def self.to_type_name( type )
|
@@ -9,7 +9,6 @@ module Wackamole
|
|
9
9
|
|
10
10
|
# ---------------------------------------------------------------------------
|
11
11
|
# Collect various data points to power up dashboard
|
12
|
-
# TODO - PERF - try just using cursor vs to_a
|
13
12
|
def self.collect_dashboard_info( now )
|
14
13
|
info = {}
|
15
14
|
|
@@ -20,13 +19,12 @@ module Wackamole
|
|
20
19
|
|
21
20
|
# Fetch day logs
|
22
21
|
utc_time = now.clone.utc
|
23
|
-
puts utc_time
|
24
22
|
conds = SearchFilter.time_conds( now, 0 )
|
23
|
+
# puts conds.inspect
|
25
24
|
day_logs = logs_cltn.find( conds,
|
26
25
|
:fields => [:typ, :fid, :tid, :did, :uid],
|
27
26
|
:sort => [ [:tid => Mongo::ASCENDING] ] )
|
28
|
-
puts
|
29
|
-
puts day_logs.count
|
27
|
+
# puts "Found logs #{day_logs.count}"
|
30
28
|
# Count all logs per hourly time period
|
31
29
|
users = Set.new
|
32
30
|
features = Set.new
|
@@ -36,7 +34,8 @@ puts day_logs.count
|
|
36
34
|
user_per_hour = {}
|
37
35
|
day_logs.each do |log|
|
38
36
|
date_tokens = log['did'].match( /(\d{4})(\d{2})(\d{2})/ ).captures
|
39
|
-
time_tokens = log['tid'].match( /(\d{2})(\d{2})(\d{2})/ ).captures
|
37
|
+
time_tokens = log['tid'].match( /(\d{2})(\d{2})(\d{2})/ ).captures
|
38
|
+
# puts "#{log['did']} - #{log['tid']} - #{log['uid']}"
|
40
39
|
log_utc = Time.utc( date_tokens[0], date_tokens[1], date_tokens[2], time_tokens[0], time_tokens[1], time_tokens[2] )
|
41
40
|
local = log_utc.clone.localtime
|
42
41
|
hour = local.hour
|
@@ -141,7 +141,7 @@ module Wackamole
|
|
141
141
|
to_utc = Time.local( local_now.year, local_now.month, local_now.day, 23, 59, 59 ).utc
|
142
142
|
|
143
143
|
from_date_id = from_utc.to_date_id.to_s
|
144
|
-
to_date_id = to_utc.to_date_id.to_s
|
144
|
+
to_date_id = to_utc.to_date_id.to_s
|
145
145
|
|
146
146
|
if from_date_id != to_date_id
|
147
147
|
from_time_id = from_utc.to_time_id.to_s
|
@@ -151,7 +151,7 @@ module Wackamole
|
|
151
151
|
conds[:did] = to_date_id
|
152
152
|
end
|
153
153
|
else
|
154
|
-
date = Chronic.parse( "#{days ==
|
154
|
+
date = Chronic.parse( "#{days == 0 ? "now" : "#{days} days ago"}" )
|
155
155
|
current = "%4d/%02d/%02d %02d:%02d:%02d" % [date.year, date.month, date.day, current_hour, 0, 1]
|
156
156
|
time = Chronic.parse( current ).utc
|
157
157
|
conds[:did] = { '$gte' => time.to_date_id.to_s }
|
@@ -12,7 +12,7 @@ module Wackamole
|
|
12
12
|
# ---------------------------------------------------------------------------
|
13
13
|
# Find all users matching criteria and returns pagination collection
|
14
14
|
def self.paginate_tops( conds, page=1, page_size=default_page_size )
|
15
|
-
tops = logs_cltn.group( [:uid], conds, { :count => 0 }, 'function(obj,prev) { prev.count += 1}'
|
15
|
+
tops = logs_cltn.group( [:uid], conds, { :count => 0 }, 'function(obj,prev) { prev.count += 1}' )
|
16
16
|
users = []
|
17
17
|
tops.sort{ |a,b| b['count'] <=> a['count'] }.each do |row|
|
18
18
|
users << { :uid => row['uid'], :total => row['count'].to_i, :details => [] }
|
@@ -32,6 +32,17 @@ div#logo {
|
|
32
32
|
margin-bottom: 5px;
|
33
33
|
}
|
34
34
|
|
35
|
+
span#version {
|
36
|
+
position: relative;
|
37
|
+
top: -12px;
|
38
|
+
left: 32px;
|
39
|
+
font-weight: bold;
|
40
|
+
color: #316071;
|
41
|
+
}
|
42
|
+
a.logout {
|
43
|
+
font-size: 0.8em;
|
44
|
+
}
|
45
|
+
|
35
46
|
div#main {
|
36
47
|
clear: both;
|
37
48
|
margin: 40px 10px 10px 20px;
|
@@ -63,6 +74,17 @@ div#navigation {
|
|
63
74
|
background: #c1c1c1 url(../images/fade.png) repeat-x;
|
64
75
|
}
|
65
76
|
|
77
|
+
a.nav_link {
|
78
|
+
color: #646464;
|
79
|
+
font-weight: bold;
|
80
|
+
text-decoration: none;
|
81
|
+
}
|
82
|
+
a.nav_link:hover {
|
83
|
+
color : #1779ff;
|
84
|
+
border-bottom: 1px #1779ff solid;
|
85
|
+
text-decoration: none;
|
86
|
+
}
|
87
|
+
|
66
88
|
a.site_link {
|
67
89
|
color: #646464;
|
68
90
|
font-weight: bold;
|
@@ -80,26 +102,31 @@ a.current {
|
|
80
102
|
border-bottom: 5px #646464 solid;
|
81
103
|
}
|
82
104
|
|
83
|
-
div#
|
105
|
+
div#links {
|
84
106
|
text-align: right;
|
85
|
-
font-size: 2em;
|
86
107
|
}
|
87
|
-
div#
|
88
|
-
|
108
|
+
div#links p {
|
109
|
+
text-align: right;
|
110
|
+
margin-top: 5px;
|
89
111
|
}
|
90
|
-
|
91
|
-
color:#666;
|
112
|
+
span#timestamp {
|
92
113
|
}
|
93
|
-
|
94
|
-
|
95
|
-
font-size:
|
96
|
-
|
114
|
+
|
115
|
+
ul#app_info {
|
116
|
+
font-size: 1.5em;
|
117
|
+
margin-top: 10px;
|
97
118
|
}
|
98
|
-
|
99
|
-
text-align: right;
|
100
|
-
font-size: 1.0em;
|
119
|
+
ul#app_info li {
|
101
120
|
}
|
102
|
-
|
121
|
+
ul#app_info span.zone {
|
122
|
+
color: #fe9500;
|
123
|
+
}
|
124
|
+
ul#app_info span.app {
|
125
|
+
color: #666;
|
126
|
+
}
|
127
|
+
ul#app_info span.stage {
|
128
|
+
color: #a1bf6d;
|
129
|
+
font-style: italic;
|
103
130
|
}
|
104
131
|
|
105
132
|
#header {
|
data/spec/config/test.yml
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
zones:
|
2
|
+
test:
|
3
|
+
host: localhost
|
4
|
+
port: 27099
|
data/spec/data/fixtures.rb
CHANGED
@@ -1,92 +1,92 @@
|
|
1
|
-
require 'rackamole'
|
2
|
-
|
3
|
-
class Fixtures
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
end
|
1
|
+
# require 'rackamole'
|
2
|
+
#
|
3
|
+
# class Fixtures
|
4
|
+
#
|
5
|
+
# def self.test_time_id() @test_time ||= 20100101; end
|
6
|
+
#
|
7
|
+
# def self.load_data
|
8
|
+
# puts "Loading fixture data..."
|
9
|
+
# Wackamole::Control.init_config( File.join(File.dirname(__FILE__), %w[.. config test.yml]), 'test' )
|
10
|
+
# load_test_dbs
|
11
|
+
# load_bogus_dbs
|
12
|
+
# end
|
13
|
+
#
|
14
|
+
# def self.load_test_dbs
|
15
|
+
# con = Wackamole::Control.connection( 'test' )
|
16
|
+
# %w[development test production].each{ |env| create_valid_mole_db( con, "fred", env) }
|
17
|
+
# end
|
18
|
+
#
|
19
|
+
# def self.load_bogus_dbs
|
20
|
+
# con = Wackamole::Control.connection( 'test' )
|
21
|
+
# %w[mole_blee_mdb zorg_blee_dev_mdb].each do |db_name|
|
22
|
+
# create_db( con, db_name )
|
23
|
+
# end
|
24
|
+
# # create mole db with wrong cltns
|
25
|
+
# # BOZO !! An empty db does not show up?
|
26
|
+
# db = create_db( con, "mole_zorg_wrong_mdb" )
|
27
|
+
# %w[features1 logs1 users1].each { |cltn| db.drop_collection( cltn );db.create_collection( cltn ) }
|
28
|
+
# # missing cltn
|
29
|
+
# db = create_db( con, "mole_zorg_missing_mdb" )
|
30
|
+
# %w[features logs].each { |cltn| db.drop_collection( cltn );db.create_collection( cltn ) }
|
31
|
+
# end
|
32
|
+
#
|
33
|
+
# def self.create_db( con, db_name )
|
34
|
+
# # if con.database_names.include?( db_name )
|
35
|
+
# # con.drop_database( db_name )
|
36
|
+
# # end
|
37
|
+
# con.db( db_name, :strict => true )
|
38
|
+
# end
|
39
|
+
#
|
40
|
+
# def self.create_valid_mole_db( con, app_name, env )
|
41
|
+
# db_name = "mole_#{app_name}_#{env}_mdb"
|
42
|
+
# db = create_db( con, db_name )
|
43
|
+
# %w[users features logs].each do |cltn_name|
|
44
|
+
# db.drop_collection( cltn_name )
|
45
|
+
# cltn = db.create_collection( cltn_name ) # :capped => false, :size => 1_000_000, :limit => 100 )
|
46
|
+
# case cltn_name
|
47
|
+
# when 'users' : populate_users( cltn, app_name, env )
|
48
|
+
# when 'features' : populate_features( cltn, app_name, env )
|
49
|
+
# when 'logs' : populate_logs( cltn, app_name, env )
|
50
|
+
# end
|
51
|
+
# end
|
52
|
+
# end
|
53
|
+
#
|
54
|
+
# def self.populate_users( cltn, app_name, env )
|
55
|
+
# 10.times do |i|
|
56
|
+
# cltn.insert( { :una => "blee_#{i}@#{app_name}.#{env}", :did => test_time_id.to_s } )
|
57
|
+
# end
|
58
|
+
# end
|
59
|
+
#
|
60
|
+
# def self.populate_features( cltn, app_name, env )
|
61
|
+
# 10.times do |i|
|
62
|
+
# cltn.insert( { :env => env, :app => app_name, :did => test_time_id.to_s, :ctx => "feature_#{i}" } )
|
63
|
+
# end
|
64
|
+
# end
|
65
|
+
#
|
66
|
+
# def self.populate_logs( cltn, app_name, env )
|
67
|
+
# features = cltn.db['features'].find( {} ).to_a
|
68
|
+
# users = cltn.db['users'].find( {} ).to_a
|
69
|
+
# [Rackamole.feature, Rackamole.perf, Rackamole.fault].each do |type|
|
70
|
+
# 5.times do |i|
|
71
|
+
# cltn.insert({
|
72
|
+
# :typ => type,
|
73
|
+
# :fid => features[i]['_id'],
|
74
|
+
# :uid => users[i]['_id'],
|
75
|
+
# :did => test_time_id.to_s,
|
76
|
+
# :tid => "070000",
|
77
|
+
# :ip => "127.0.0.#{i}"
|
78
|
+
# })
|
79
|
+
# end
|
80
|
+
# 2.times do |i|
|
81
|
+
# cltn.insert({
|
82
|
+
# :typ => type,
|
83
|
+
# :fid => features[5+i]['_id'],
|
84
|
+
# :uid => users[5+i]['_id'],
|
85
|
+
# :did => test_time_id.to_s,
|
86
|
+
# :tid => "080000",
|
87
|
+
# :ip => "127.0.0.#{i}"
|
88
|
+
# })
|
89
|
+
# end
|
90
|
+
# end
|
91
|
+
# end
|
92
|
+
# end
|