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.
Files changed (41) hide show
  1. data/Rakefile +1 -0
  2. data/bin/setup_indexes +44 -0
  3. data/bin/wackamole +8 -6
  4. data/config.ru +18 -0
  5. data/lib/app.rb +8 -5
  6. data/lib/controllers/dashboard.rb +13 -1
  7. data/lib/controllers/features.rb +4 -0
  8. data/lib/controllers/logs.rb +14 -5
  9. data/lib/controllers/mission.rb +19 -12
  10. data/lib/controllers/users.rb +7 -0
  11. data/lib/helpers/dashboard_helper.rb +7 -7
  12. data/lib/helpers/logs_helper.rb +29 -12
  13. data/lib/helpers/mission_helper.rb +21 -7
  14. data/lib/wackamole.rb +1 -1
  15. data/lib/wackamole/models/control.rb +45 -22
  16. data/lib/wackamole/models/log.rb +6 -4
  17. data/lib/wackamole/models/mission.rb +44 -132
  18. data/lib/wackamole/models/mole_info.rb +21 -15
  19. data/lib/wackamole/models/search_filter.rb +25 -11
  20. data/public/images/browsers_sprite.png +0 -0
  21. data/public/images/fault_small.png +0 -0
  22. data/public/images/perf_small.png +0 -0
  23. data/public/stylesheets/wackamole.css +135 -111
  24. data/spec/models/log_spec.rb +4 -4
  25. data/spec/models/mission_spec.rb +13 -192
  26. data/spec/models/search_filter_spec.rb +37 -9
  27. data/views/dashboard/_report.erb +2 -2
  28. data/views/dashboard/index.erb +2 -0
  29. data/views/features/index.erb +3 -1
  30. data/views/layout.erb +7 -7
  31. data/views/logs/_rows.erb +4 -3
  32. data/views/logs/index.erb +3 -1
  33. data/views/logs/show.erb +4 -8
  34. data/views/mission/_report.erb +66 -40
  35. data/views/mission/index.erb +1 -3
  36. data/views/mission/refresh_js.erb +5 -2
  37. data/views/mission/trash.txt +50 -0
  38. data/views/shared/_filter.erb +8 -9
  39. data/views/shared/_search.erb +2 -2
  40. data/views/users/index.erb +3 -1
  41. metadata +18 -2
data/Rakefile CHANGED
@@ -37,6 +37,7 @@ depend_on "mongo_rack" , ">= 0.0.1"
37
37
  depend_on "main" , ">= 4.2.0"
38
38
  depend_on "sinatra" , ">= 0.9.4"
39
39
  depend_on "mongo_rack" , ">= 0.0.3"
40
+ depend_on "rackamole" , ">= 0.0.3"
40
41
 
41
42
  # Rake
42
43
  task :default => ['fixtures:load','spec:run']
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
- environment( 'RACK_ENV' ) {
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['RACK_ENV'].value
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}/mission" )
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 => 'production'
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 => "%s:%d/%s/%s" % [@@options[:host], @@options[:port], @@options[:db_name], @@options[:cltn_name]]
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, :server => "%s:%d/%s/%s" % ['localhost', '27017', 'wackamole_ses', 'sessions']
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 = 60
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
@@ -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
@@ -2,12 +2,11 @@ module Logs
2
2
 
3
3
  # ---------------------------------------------------------------------------
4
4
  get "/logs/:page" do
5
- page = params[:page] ? params[:page].to_i : 1
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
- @logs = Wackamole::Log.paginate( @filter.to_conds )
47
- erb :"logs/filter.js", :layout => false
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
@@ -1,27 +1,34 @@
1
1
  require 'chronic'
2
2
 
3
- module Mission
4
-
3
+ module Mission
5
4
  # ---------------------------------------------------------------------------
6
- get '/mission' do
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
- load_report
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
- load_report
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
- Wackamole::Mission.reset!( params[:app], params[:env], params[:type] )
23
- load_report
24
- erb :'/mission/refresh_js', :layout => false
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
@@ -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
- Wackamole::Log.ensure_indexes!
9
- Wackamole::User.ensure_indexes!
10
- Wackamole::Feature.ensure_indexes!
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...
@@ -2,18 +2,30 @@ module LogsHelper
2
2
 
3
3
  helpers do
4
4
  # ---------------------------------------------------------------------------
5
- def user_name_for( user_id )
6
- user = Wackamole::User.users_cltn.find_one( user_id )
7
- user['una']
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
- feature = Wackamole::Feature.features_cltn.find_one( feature_id )
14
- return "Unknown" unless feature
15
- return "#{feature['ctl']}##{feature['act']}" if feature['ctl']
16
- feature['ctx']
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 browser_icon( browser )
101
- img_name = browser
102
- img_name = "unknown_browser" if img_name.nil? or img_name == "N/A"
103
- image_tag "browsers/#{img_name.to_s.downcase.gsub( /\\/, '')}.png", :size => "20x20"
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
- @reports = Wackamole::Mission.rollups( last_tick.utc, reset )
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, diff )
32
+ def assign_class( type, count )
23
33
  clazz = case type
24
- when "faults" : (diff > 0 ? "fault" : "")
25
- when "perfs" : (diff > 0 ? "perf" : "")
26
- when "features" : (diff > 0 ? "active" : "inactive")
27
- else ""
28
- end
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