wackamole 0.0.3 → 0.0.4
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/Rakefile +1 -0
- data/bin/setup_indexes +44 -0
- data/bin/wackamole +8 -6
- data/config.ru +18 -0
- data/lib/app.rb +8 -5
- data/lib/controllers/dashboard.rb +13 -1
- data/lib/controllers/features.rb +4 -0
- data/lib/controllers/logs.rb +14 -5
- data/lib/controllers/mission.rb +19 -12
- data/lib/controllers/users.rb +7 -0
- data/lib/helpers/dashboard_helper.rb +7 -7
- data/lib/helpers/logs_helper.rb +29 -12
- data/lib/helpers/mission_helper.rb +21 -7
- data/lib/wackamole.rb +1 -1
- data/lib/wackamole/models/control.rb +45 -22
- data/lib/wackamole/models/log.rb +6 -4
- data/lib/wackamole/models/mission.rb +44 -132
- data/lib/wackamole/models/mole_info.rb +21 -15
- data/lib/wackamole/models/search_filter.rb +25 -11
- data/public/images/browsers_sprite.png +0 -0
- data/public/images/fault_small.png +0 -0
- data/public/images/perf_small.png +0 -0
- data/public/stylesheets/wackamole.css +135 -111
- data/spec/models/log_spec.rb +4 -4
- data/spec/models/mission_spec.rb +13 -192
- data/spec/models/search_filter_spec.rb +37 -9
- data/views/dashboard/_report.erb +2 -2
- data/views/dashboard/index.erb +2 -0
- data/views/features/index.erb +3 -1
- data/views/layout.erb +7 -7
- data/views/logs/_rows.erb +4 -3
- data/views/logs/index.erb +3 -1
- data/views/logs/show.erb +4 -8
- data/views/mission/_report.erb +66 -40
- data/views/mission/index.erb +1 -3
- data/views/mission/refresh_js.erb +5 -2
- data/views/mission/trash.txt +50 -0
- data/views/shared/_filter.erb +8 -9
- data/views/shared/_search.erb +2 -2
- data/views/users/index.erb +3 -1
- metadata +18 -2
data/Rakefile
CHANGED
data/bin/setup_indexes
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'rubygems'
|
3
|
+
require 'main'
|
4
|
+
require 'mongo'
|
5
|
+
require File.expand_path( File.join(File.dirname(__FILE__), %w[.. lib wackamole]))
|
6
|
+
|
7
|
+
Main {
|
8
|
+
option('reset', 'r') {
|
9
|
+
default false
|
10
|
+
description "Reset all indexes"
|
11
|
+
}
|
12
|
+
|
13
|
+
option('set', 's') {
|
14
|
+
default false
|
15
|
+
description "Set all indexes"
|
16
|
+
}
|
17
|
+
|
18
|
+
option('clear', 'c') {
|
19
|
+
default false
|
20
|
+
description "Clear all indexes"
|
21
|
+
}
|
22
|
+
|
23
|
+
option( 'verbose', 'v') {
|
24
|
+
default false
|
25
|
+
description "Show verbose information"
|
26
|
+
}
|
27
|
+
|
28
|
+
environment( 'WACKAMOLE_ENV' ) {
|
29
|
+
default 'production'
|
30
|
+
description 'Wackamole env to choose from in landscape yml'
|
31
|
+
}
|
32
|
+
|
33
|
+
# Enter main loop
|
34
|
+
def run
|
35
|
+
config_file = File.join( ENV['HOME'], %w[.wackamole wackamole.yml] )
|
36
|
+
Wackamole::Control.init_config( config_file, params['WACKAMOLE_ENV'].value )
|
37
|
+
Wackamole::Control.ensure_indexes!(
|
38
|
+
params[:set].value,
|
39
|
+
params[:reset].value,
|
40
|
+
params[:verbose].value,
|
41
|
+
params[:clear].value
|
42
|
+
)
|
43
|
+
end
|
44
|
+
}
|
data/bin/wackamole
CHANGED
@@ -9,8 +9,10 @@ Main {
|
|
9
9
|
validate { |pool| pool =~ URI_MATCH }
|
10
10
|
description "specify session server uri. Must be of the form {[mongo|memcache]}://{host}:{port}/{[database_name|namespace]}[/{collection_name}]"
|
11
11
|
}
|
12
|
-
|
12
|
+
option( 'environment', 'e' ) {
|
13
|
+
argument :required
|
13
14
|
default 'production'
|
15
|
+
description 'Specifies the env to run wackamole in'
|
14
16
|
}
|
15
17
|
|
16
18
|
@@options = {}
|
@@ -18,9 +20,9 @@ Main {
|
|
18
20
|
# Enter main loop
|
19
21
|
def run
|
20
22
|
require File.expand_path( File.join(File.dirname(__FILE__), %w[.. lib wackamole]))
|
21
|
-
|
23
|
+
|
22
24
|
@@options = parse_args( params[:pool].value )
|
23
|
-
ENV['RACK_ENV'] = params['
|
25
|
+
ENV['RACK_ENV'] = params['environment'].value
|
24
26
|
|
25
27
|
Thread.new do
|
26
28
|
puts "-"*100
|
@@ -33,19 +35,19 @@ Main {
|
|
33
35
|
puts "\n"*2
|
34
36
|
puts ">>> Opening console..."
|
35
37
|
puts "\n"*2
|
36
|
-
open( "http://localhost:#{default_port}
|
38
|
+
open( "http://localhost:#{default_port}" )
|
37
39
|
end
|
38
40
|
|
39
41
|
# Clearing args for franky!
|
40
42
|
ARGV.clear
|
41
43
|
require 'sinatra'
|
42
44
|
require File.join(File.dirname(__FILE__), %w[.. lib app.rb])
|
43
|
-
Sinatra::Application.run! :port => default_port, :environment => '
|
45
|
+
Sinatra::Application.run! :port => default_port, :environment => params['environment'].value
|
44
46
|
end
|
45
47
|
|
46
48
|
# default wackamole port
|
47
49
|
def default_port() 7777; end
|
48
|
-
|
50
|
+
|
49
51
|
# sleepy time...
|
50
52
|
def sleep_time() 3; end
|
51
53
|
|
data/config.ru
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
#------------
|
2
|
+
# Wackamole Sessions Options
|
3
|
+
#
|
4
|
+
# @@options defines where Wackamole puts its sessions, which can be either mongo or memcache
|
5
|
+
# if @@options is not defined mongo at localhost:27017 is used
|
6
|
+
#
|
7
|
+
# For customized sessions with Mongo uncomment and modify this line:
|
8
|
+
# @@options={:protocol=>"mongo", :host=>"localhost", :port=>"11211", :db_name=>"wackamole_session", :cltn_name=>"sessions"}
|
9
|
+
#
|
10
|
+
# For Memcache session uncomment and modify this line:
|
11
|
+
# @@options={:protocol=>"memcached", :host=>"localhost", :port=>"11211", :namespace=>"wackamole_session"}
|
12
|
+
#
|
13
|
+
#------------
|
14
|
+
|
15
|
+
require 'rubygems'
|
16
|
+
require 'sinatra'
|
17
|
+
require File.join(File.dirname(__FILE__), %w[lib app.rb])
|
18
|
+
run Sinatra::Application
|
data/lib/app.rb
CHANGED
@@ -24,6 +24,7 @@ end
|
|
24
24
|
|
25
25
|
configure do
|
26
26
|
set :sessions, false
|
27
|
+
set :logging, true
|
27
28
|
|
28
29
|
Wackamole.load_all_libs_relative_to(__FILE__, 'helpers' )
|
29
30
|
Wackamole.load_all_libs_relative_to(__FILE__, 'controllers' )
|
@@ -32,7 +33,8 @@ configure do
|
|
32
33
|
if defined? @@options and @@options
|
33
34
|
if @@options[:protocol] == 'mongo'
|
34
35
|
use Rack::Session::Mongo,
|
35
|
-
:server
|
36
|
+
:server => "%s:%d/%s/%s" % [@@options[:host], @@options[:port], @@options[:db_name], @@options[:cltn_name]],
|
37
|
+
:log_level => :debug
|
36
38
|
else
|
37
39
|
use Rack::Session::Memcache,
|
38
40
|
:memcache_server => "%s:%d" % [@@options[:host], @@options[:port]],
|
@@ -40,7 +42,9 @@ configure do
|
|
40
42
|
end
|
41
43
|
else
|
42
44
|
# Default is a mongo session store
|
43
|
-
use Rack::Session::Mongo,
|
45
|
+
use Rack::Session::Mongo,
|
46
|
+
:server => "%s:%d/%s/%s" % ['localhost', '27017', 'wackamole_ses', 'sessions'],
|
47
|
+
:log_level => :error
|
44
48
|
end
|
45
49
|
set :con, Wackamole::Control.init_config( default_config, Sinatra::Application.environment.to_s )
|
46
50
|
end
|
@@ -55,13 +59,12 @@ before do
|
|
55
59
|
session[:filter] = @filter
|
56
60
|
end
|
57
61
|
@updated_on = Time.now
|
58
|
-
@refresh_rate =
|
59
|
-
|
62
|
+
@refresh_rate = 30
|
60
63
|
@app_info = session[:app_info]
|
61
64
|
begin
|
62
65
|
Wackamole::Control.switch_mole_db!( @app_info[:app_name].downcase, @app_info[:stage] ) if @app_info
|
63
66
|
rescue => boom
|
64
|
-
puts boom
|
67
|
+
$stderr.puts boom
|
65
68
|
@app_info = nil
|
66
69
|
session[:app_info] = nil
|
67
70
|
end
|
@@ -8,7 +8,6 @@ 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
|
-
ensure_indexes!
|
12
11
|
load_app_details
|
13
12
|
|
14
13
|
# Reset app info
|
@@ -27,4 +26,17 @@ module Dashboard
|
|
27
26
|
erb :'dashboard/refresh_js', :layout => false
|
28
27
|
end
|
29
28
|
|
29
|
+
# ---------------------------------------------------------------------------
|
30
|
+
get '/dashboard/logs/:app_name/:stage/:type' do
|
31
|
+
Wackamole::Control.switch_mole_db!( params[:app_name].downcase, params[:stage] )
|
32
|
+
load_app_details
|
33
|
+
load_app_info
|
34
|
+
|
35
|
+
filter = Wackamole::SearchFilter.new
|
36
|
+
filter.mole_type( params[:type].to_i )
|
37
|
+
puts "SETTING FILTER", filter.inspect
|
38
|
+
session[:filter] = filter
|
39
|
+
redirect '/logs/1'
|
40
|
+
end
|
41
|
+
|
30
42
|
end
|
data/lib/controllers/features.rb
CHANGED
@@ -5,6 +5,8 @@ module Features
|
|
5
5
|
get "/features/:page" do
|
6
6
|
page = params[:page] ? params[:page].to_i : 1
|
7
7
|
|
8
|
+
puts @filter.inspect
|
9
|
+
|
8
10
|
@features = Wackamole::Feature.paginate_tops( @filter.to_conds, page )
|
9
11
|
@search_path = "/features/search"
|
10
12
|
@filter_path = "/features/filter"
|
@@ -35,6 +37,8 @@ module Features
|
|
35
37
|
# Filter
|
36
38
|
post "/features/filter" do
|
37
39
|
@filter.from_options( params[:filter] )
|
40
|
+
session[:filter] = @filter
|
41
|
+
puts "Setting #{session[:filter].inspect}"
|
38
42
|
@features = Wackamole::Feature.paginate_tops( @filter.to_conds )
|
39
43
|
erb :"features/filter.js", :layout => false
|
40
44
|
end
|
data/lib/controllers/logs.rb
CHANGED
@@ -2,12 +2,11 @@ module Logs
|
|
2
2
|
|
3
3
|
# ---------------------------------------------------------------------------
|
4
4
|
get "/logs/:page" do
|
5
|
-
page
|
6
|
-
|
5
|
+
page = params[:page] ? params[:page].to_i : 1
|
7
6
|
@logs = Wackamole::Log.paginate( @filter.to_conds, page)
|
8
7
|
@search_path = "/logs/search"
|
9
8
|
@filter_path = "/logs/filter"
|
10
|
-
|
9
|
+
|
11
10
|
if request.xhr?
|
12
11
|
erb :'logs/index.js', :layout => false
|
13
12
|
else
|
@@ -43,7 +42,17 @@ module Logs
|
|
43
42
|
@filter = Wackamole::SearchFilter.new
|
44
43
|
@filter.from_options( params[:filter] )
|
45
44
|
session[:filter] = @filter
|
46
|
-
|
47
|
-
|
45
|
+
|
46
|
+
# elapsed = Benchmark.realtime do
|
47
|
+
@logs = Wackamole::Log.paginate( @filter.to_conds )
|
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
|
48
57
|
end
|
49
58
|
end
|
data/lib/controllers/mission.rb
CHANGED
@@ -1,27 +1,34 @@
|
|
1
1
|
require 'chronic'
|
2
2
|
|
3
|
-
module Mission
|
4
|
-
|
3
|
+
module Mission
|
5
4
|
# ---------------------------------------------------------------------------
|
6
|
-
get '/
|
5
|
+
get '/' do
|
7
6
|
# reset app info
|
8
7
|
session[:app_info] = @app_info = nil
|
8
|
+
|
9
|
+
last_tick = session[:last_tick]
|
10
|
+
last_tick ||= Chronic.parse( "#{@refresh_rate} seconds ago" )
|
11
|
+
session[:last_tick] = Time.now
|
9
12
|
|
10
|
-
|
13
|
+
@pulse = Wackamole::Mission.pulse( last_tick.utc )
|
14
|
+
|
11
15
|
erb :'mission/index'
|
12
16
|
end
|
13
17
|
|
14
18
|
# ---------------------------------------------------------------------------
|
15
19
|
get '/mission/refresh' do
|
16
|
-
|
20
|
+
last_tick = session[:last_tick]
|
21
|
+
last_tick ||= Chronic.parse( "#{@refresh_rate} seconds ago" )
|
22
|
+
session[:last_tick] = Time.now
|
23
|
+
|
24
|
+
@pulse = Wackamole::Mission.pulse( last_tick.utc )
|
25
|
+
|
17
26
|
erb :'/mission/refresh_js', :layout => false
|
18
27
|
end
|
19
28
|
|
20
|
-
# ---------------------------------------------------------------------------
|
21
|
-
get '/mission/fixed/:app/:env/:type' do
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
end
|
26
|
-
|
29
|
+
# # ---------------------------------------------------------------------------
|
30
|
+
# get '/mission/fixed/:app/:env/:type' do
|
31
|
+
# Wackamole::Mission.reset!( params[:app], params[:env], params[:type] )
|
32
|
+
# erb :'/mission/refresh_js', :layout => false
|
33
|
+
# end
|
27
34
|
end
|
data/lib/controllers/users.rb
CHANGED
@@ -5,7 +5,12 @@ module Users
|
|
5
5
|
get "/users/:page" do
|
6
6
|
page = params[:page] ? params[:page].to_i : 1
|
7
7
|
|
8
|
+
puts "User filter", @filter.inspect
|
9
|
+
elapsed = Benchmark.realtime do
|
8
10
|
@users = Wackamole::User.paginate_tops( @filter.to_conds, page )
|
11
|
+
end
|
12
|
+
puts "Find users %5.4f" % elapsed
|
13
|
+
|
9
14
|
@search_path = "/users/search"
|
10
15
|
@filter_path = "/users/filter"
|
11
16
|
|
@@ -35,6 +40,8 @@ module Users
|
|
35
40
|
# Filter
|
36
41
|
post "/users/filter" do
|
37
42
|
@filter.from_options( params[:filter] )
|
43
|
+
session[:filter] = @filter
|
44
|
+
puts "Setting user filter #{session[:filter].inspect}"
|
38
45
|
@users = Wackamole::User.paginate_tops( @filter.to_conds )
|
39
46
|
erb :"users/filter.js", :layout => false
|
40
47
|
end
|
@@ -2,13 +2,13 @@ module DashboardHelper
|
|
2
2
|
|
3
3
|
helpers do
|
4
4
|
|
5
|
-
# -------------------------------------------------------------------------
|
6
|
-
# Make sure all indexes are set
|
7
|
-
def ensure_indexes!
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
end
|
5
|
+
# # -------------------------------------------------------------------------
|
6
|
+
# # Make sure all indexes are set
|
7
|
+
# def ensure_indexes!
|
8
|
+
# Wackamole::Log.ensure_indexes!
|
9
|
+
# Wackamole::User.ensure_indexes!
|
10
|
+
# Wackamole::Feature.ensure_indexes!
|
11
|
+
# end
|
12
12
|
|
13
13
|
# -------------------------------------------------------------------------
|
14
14
|
# Retrieve moled app info...
|
data/lib/helpers/logs_helper.rb
CHANGED
@@ -2,18 +2,30 @@ module LogsHelper
|
|
2
2
|
|
3
3
|
helpers do
|
4
4
|
# ---------------------------------------------------------------------------
|
5
|
-
def user_name_for( user_id )
|
6
|
-
|
7
|
-
user[
|
5
|
+
def user_name_for( ctx, user_id )
|
6
|
+
return ctx[user_id] if ctx[user_id]
|
7
|
+
user = Wackamole::User.users_cltn.find_one( user_id, :fields => [:una] )
|
8
|
+
value = user['una']
|
9
|
+
ctx[user_id] = value
|
10
|
+
value
|
8
11
|
end
|
9
12
|
|
10
13
|
# ---------------------------------------------------------------------------
|
11
14
|
# Find feature context for log entry
|
12
|
-
def context_for( feature_id )
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
15
|
+
def context_for( ctx, feature_id )
|
16
|
+
return ctx[feature_id] if ctx[feature_id]
|
17
|
+
feature = Wackamole::Feature.features_cltn.find_one( feature_id, :fields => [:ctl, :act, :ctx] )
|
18
|
+
if feature
|
19
|
+
if feature['ctl']
|
20
|
+
value = "#{feature['ctl']}##{feature['act']}"
|
21
|
+
else
|
22
|
+
value = feature['ctx']
|
23
|
+
end
|
24
|
+
else
|
25
|
+
value = "Unknown"
|
26
|
+
end
|
27
|
+
ctx[feature_id] = value
|
28
|
+
value
|
17
29
|
end
|
18
30
|
|
19
31
|
# ---------------------------------------------------------------------------
|
@@ -97,10 +109,15 @@ module LogsHelper
|
|
97
109
|
|
98
110
|
# ---------------------------------------------------------------------------
|
99
111
|
# Setup browser icon indicator
|
100
|
-
def
|
101
|
-
|
102
|
-
|
103
|
-
|
112
|
+
def browser_class( browser )
|
113
|
+
class_name = browser['name'].downcase
|
114
|
+
if class_name == 'msie'
|
115
|
+
version = browser['version'].match( /(\d)\.\d/ ).captures.first
|
116
|
+
class_name = "ie_#{version.to_s}"
|
117
|
+
elsif class_name == "n/a"
|
118
|
+
class_name = 'unknown'
|
119
|
+
end
|
120
|
+
class_name
|
104
121
|
end
|
105
122
|
end
|
106
123
|
end
|
@@ -1,6 +1,12 @@
|
|
1
1
|
module MissionHelper
|
2
2
|
helpers do
|
3
3
|
|
4
|
+
def extract_applications( pulse )
|
5
|
+
apps = OrderedHash.new
|
6
|
+
pulse[:to_date].keys.sort.each { |app_name| apps[app_name] = pulse[:to_date][app_name].keys.sort }
|
7
|
+
apps
|
8
|
+
end
|
9
|
+
|
4
10
|
# -------------------------------------------------------------------------
|
5
11
|
def load_report
|
6
12
|
@old_reports = Wackamole::Mission.find( {}, :sort => [ [:app, Mongo::ASCENDING], [:env, Mongo::ASCENDING] ] ).to_a
|
@@ -8,7 +14,11 @@ module MissionHelper
|
|
8
14
|
reset = last_tick.nil?
|
9
15
|
last_tick = last_tick || Chronic.parse( '1 minute ago' )
|
10
16
|
session[:last_tick] = Time.now
|
11
|
-
|
17
|
+
|
18
|
+
elapsed = Benchmark.realtime do
|
19
|
+
@reports = Wackamole::Mission.rollups( last_tick.utc, reset )
|
20
|
+
end
|
21
|
+
puts "Rollups %5.4f" % elapsed
|
12
22
|
end
|
13
23
|
|
14
24
|
# -------------------------------------------------------------------------
|
@@ -19,13 +29,17 @@ module MissionHelper
|
|
19
29
|
|
20
30
|
# -------------------------------------------------------------------------
|
21
31
|
# Assign status fg for application
|
22
|
-
def assign_class( type, count
|
32
|
+
def assign_class( type, count )
|
23
33
|
clazz = case type
|
24
|
-
when
|
25
|
-
|
26
|
-
when
|
27
|
-
|
28
|
-
|
34
|
+
when Rackamole.fault
|
35
|
+
(count > 0 ? "fault" : "")
|
36
|
+
when Rackamole.perf
|
37
|
+
(count > 0 ? "perf" : "")
|
38
|
+
when Rackamole.feature
|
39
|
+
(count > 0 ? "feature" : "" )
|
40
|
+
else
|
41
|
+
""
|
42
|
+
end
|
29
43
|
clazz
|
30
44
|
end
|
31
45
|
|