wackamole 0.0.1
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/.bnsignore +16 -0
- data/.gitignore +2 -0
- data/History.txt +4 -0
- data/README.rdoc +88 -0
- data/Rakefile +42 -0
- data/aa.rb +25 -0
- data/aaa.txt +13 -0
- data/bin/wackamole +77 -0
- data/lib/app.rb +63 -0
- data/lib/controllers/dashboard.rb +30 -0
- data/lib/controllers/features.rb +41 -0
- data/lib/controllers/logs.rb +49 -0
- data/lib/controllers/mission.rb +27 -0
- data/lib/controllers/users.rb +41 -0
- data/lib/helpers/dashboard_helper.rb +32 -0
- data/lib/helpers/features_helper.rb +13 -0
- data/lib/helpers/flash_helper.rb +16 -0
- data/lib/helpers/logs_helper.rb +116 -0
- data/lib/helpers/main_helper.rb +182 -0
- data/lib/helpers/mission_helper.rb +59 -0
- data/lib/helpers/rails_helper.rb +7 -0
- data/lib/wackamole.rb +47 -0
- data/lib/wackamole/core_ext/date_time.rb +8 -0
- data/lib/wackamole/core_ext/time.rb +9 -0
- data/lib/wackamole/models/control.rb +132 -0
- data/lib/wackamole/models/feature.rb +74 -0
- data/lib/wackamole/models/log.rb +45 -0
- data/lib/wackamole/models/mission.rb +164 -0
- data/lib/wackamole/models/mole_info.rb +94 -0
- data/lib/wackamole/models/search_filter.rb +192 -0
- data/lib/wackamole/models/user.rb +46 -0
- data/public/favicon.ico +0 -0
- data/public/images/.DS_Store +0 -0
- data/public/images/browsers/.DS_Store +0 -0
- data/public/images/browsers/MSIE 6.png +0 -0
- data/public/images/browsers/MSIE 8.0 +0 -0
- data/public/images/browsers/MSIE 8.0.png +0 -0
- data/public/images/browsers/chrome.png +0 -0
- data/public/images/browsers/firefox.png +0 -0
- data/public/images/browsers/ie 6.0.png +0 -0
- data/public/images/browsers/ie6.jpg +0 -0
- data/public/images/browsers/ie7.jpg +0 -0
- data/public/images/browsers/ie7.png +0 -0
- data/public/images/browsers/msie 6.0.png +0 -0
- data/public/images/browsers/msie 7.0.png +0 -0
- data/public/images/browsers/opera.jpg +0 -0
- data/public/images/browsers/opera.png +0 -0
- data/public/images/browsers/safari.jpg +0 -0
- data/public/images/browsers/safari.png +0 -0
- data/public/images/browsers/unknown_browser.png +0 -0
- data/public/images/close.png +0 -0
- data/public/images/error.png +0 -0
- data/public/images/fade.png +0 -0
- data/public/images/fault_big.png +0 -0
- data/public/images/fault_small.png +0 -0
- data/public/images/feature.png +0 -0
- data/public/images/h300.png +0 -0
- data/public/images/hori_large.png +0 -0
- data/public/images/info_big.png +0 -0
- data/public/images/info_small.png +0 -0
- data/public/images/loading.gif +0 -0
- data/public/images/loading1.gif +0 -0
- data/public/images/mole_error.png +0 -0
- data/public/images/more.gif +0 -0
- data/public/images/next.png +0 -0
- data/public/images/perf_big.png +0 -0
- data/public/images/perf_small.png +0 -0
- data/public/images/powered_by.png +0 -0
- data/public/images/prev.png +0 -0
- data/public/images/row_fade.png +0 -0
- data/public/images/search.png +0 -0
- data/public/images/small_logo.png +0 -0
- data/public/images/spaceball.gif +0 -0
- data/public/images/tick.png +0 -0
- data/public/images/users.png +0 -0
- data/public/images/wackamole_logo.png +0 -0
- data/public/javascripts/.DS_Store +0 -0
- data/public/javascripts/application.js +28 -0
- data/public/javascripts/g.dot.min.js +7 -0
- data/public/javascripts/g.raphael.min.js +7 -0
- data/public/javascripts/jit.js +9052 -0
- data/public/javascripts/jit.min.js +1 -0
- data/public/javascripts/jquery-ui.js +188 -0
- data/public/javascripts/jquery.example.js +160 -0
- data/public/javascripts/jquery.js +19 -0
- data/public/javascripts/jquery.tools.min.js +38 -0
- data/public/javascripts/jquery_ba-url.js +9 -0
- data/public/javascripts/jquery_min.js +19 -0
- data/public/javascripts/jquery_ui_min.js +298 -0
- data/public/javascripts/raphael.min.js +7 -0
- data/public/stylesheets/tabs-slideshow.css +95 -0
- data/public/stylesheets/wackamole.css +684 -0
- data/spec/config/bogus_test.yml +3 -0
- data/spec/config/test.yml +3 -0
- data/spec/core_ext/date_time_spec.rb +8 -0
- data/spec/core_ext/time_spec.rb +12 -0
- data/spec/data/fixtures.rb +92 -0
- data/spec/models/control_spec.rb +98 -0
- data/spec/models/feature_spec.rb +52 -0
- data/spec/models/log_spec.rb +43 -0
- data/spec/models/mission_spec.rb +225 -0
- data/spec/models/moled_info_spec.rb +30 -0
- data/spec/models/search_filter_spec.rb +151 -0
- data/spec/models/user_spec.rb +44 -0
- data/spec/spec_helper.rb +14 -0
- data/spec/wackamole_spec.rb +20 -0
- data/tasks/bones.rake +20 -0
- data/tasks/fixtures.rake +13 -0
- data/tasks/gem.rake +201 -0
- data/tasks/git.rake +40 -0
- data/tasks/notes.rake +27 -0
- data/tasks/post_load.rake +32 -0
- data/tasks/rdoc.rake +54 -0
- data/tasks/rubyforge.rake +55 -0
- data/tasks/setup.rb +290 -0
- data/tasks/spec.rake +54 -0
- data/tasks/svn.rake +46 -0
- data/views/dashboard/_report.erb +118 -0
- data/views/dashboard/index.erb +4 -0
- data/views/dashboard/refresh_js.erb +3 -0
- data/views/features/_rows.erb +26 -0
- data/views/features/filter.js.erb +2 -0
- data/views/features/index.erb +24 -0
- data/views/features/index.js.erb +2 -0
- data/views/layout.erb +47 -0
- data/views/logs/_array.erb +12 -0
- data/views/logs/_hash.erb +14 -0
- data/views/logs/_rows.erb +65 -0
- data/views/logs/filter.js.erb +4 -0
- data/views/logs/index.erb +13 -0
- data/views/logs/index.js.erb +2 -0
- data/views/logs/show.erb +66 -0
- data/views/mission/_report.erb +49 -0
- data/views/mission/index.erb +7 -0
- data/views/mission/refresh_js.erb +3 -0
- data/views/shared/_filter.erb +63 -0
- data/views/shared/_flash.erb +3 -0
- data/views/shared/_search.erb +25 -0
- data/views/shared/_timestamp.erb +1 -0
- data/views/shared/_wait.erb +1 -0
- data/views/shared/flash.js.erb +10 -0
- data/views/users/_rows.erb +26 -0
- data/views/users/filter.js.erb +4 -0
- data/views/users/index.erb +24 -0
- data/views/users/index.js.erb +2 -0
- metadata +347 -0
data/lib/wackamole.rb
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
module Wackamole
|
|
2
|
+
|
|
3
|
+
# :stopdoc:
|
|
4
|
+
VERSION = '0.0.1' unless defined? Wackamole::VERSION
|
|
5
|
+
LIBPATH = ::File.expand_path(::File.dirname(__FILE__)) + ::File::SEPARATOR unless defined? Wackamole::LIBPATH
|
|
6
|
+
PATH = ::File.dirname(LIBPATH) + ::File::SEPARATOR unless defined? Wackamole::PATH
|
|
7
|
+
# :startdoc:
|
|
8
|
+
|
|
9
|
+
# Returns the version string for the library.
|
|
10
|
+
def self.version
|
|
11
|
+
VERSION
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
# Returns the library path for the module. If any arguments are given,
|
|
15
|
+
# they will be joined to the end of the libray path using
|
|
16
|
+
# <tt>File.join</tt>.
|
|
17
|
+
def self.libpath( *args )
|
|
18
|
+
args.empty? ? LIBPATH : ::File.join(LIBPATH, args.flatten)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# Returns the lpath for the module. If any arguments are given,
|
|
22
|
+
# they will be joined to the end of the path using
|
|
23
|
+
# <tt>File.join</tt>.
|
|
24
|
+
def self.path( *args )
|
|
25
|
+
args.empty? ? PATH : ::File.join(PATH, args.flatten)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Utility method used to require all files ending in .rb that lie in the
|
|
29
|
+
# directory below this file that has the same name as the filename passed
|
|
30
|
+
# in. Optionally, a specific _directory_ name can be passed in such that
|
|
31
|
+
# the _filename_ does not have to be equivalent to the directory.
|
|
32
|
+
def self.require_all_libs_relative_to( fname, dir = nil )
|
|
33
|
+
dir ||= ::File.basename(fname, '.*')
|
|
34
|
+
search_me = ::File.expand_path(::File.join(::File.dirname(fname), dir, '**', '*.rb'))
|
|
35
|
+
Dir.glob(search_me).sort.each {|rb| require rb}
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Utility to force class load
|
|
39
|
+
def self.load_all_libs_relative_to( fname, dir = nil )
|
|
40
|
+
dir ||= ::File.basename(fname, '.*')
|
|
41
|
+
search_me = ::File.expand_path(::File.join(::File.dirname(fname), dir, '**', '*.rb'))
|
|
42
|
+
Dir.glob(search_me).sort.each {|rb| load rb}
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
Wackamole.require_all_libs_relative_to(__FILE__)
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
require 'mongo'
|
|
2
|
+
require 'logger'
|
|
3
|
+
|
|
4
|
+
module Wackamole
|
|
5
|
+
class Control
|
|
6
|
+
|
|
7
|
+
# -------------------------------------------------------------------------
|
|
8
|
+
# Defines mole db identity
|
|
9
|
+
def self.molex() @molex || /mole_(.*)?_(.*)?_mdb/; end
|
|
10
|
+
|
|
11
|
+
# -------------------------------------------------------------------------
|
|
12
|
+
# Fetch a collection on a given database by name
|
|
13
|
+
def self.collection( cltn_name, db_name=nil, opts={:strict => true} )
|
|
14
|
+
# reset_db!( db_name ) if db_name
|
|
15
|
+
db( db_name, opts ).collection( cltn_name )
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# -------------------------------------------------------------------------
|
|
19
|
+
# extract app_name + env from db_name
|
|
20
|
+
def self.extract_app_info( db_name )
|
|
21
|
+
raise "Invalid mole db specification #{db_name}" unless db_name =~ molex
|
|
22
|
+
db_name.match( molex ).captures
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# -------------------------------------------------------------------------
|
|
26
|
+
# Switch db instance given db_name
|
|
27
|
+
# NOTE : This assumes mole db naming convention
|
|
28
|
+
# ie mole_{app_name in lower case}_{env}_mdb
|
|
29
|
+
def self.switch_mole_db!( app_name, env )
|
|
30
|
+
raise "You must specify an app name and environment" unless app_name and env
|
|
31
|
+
app = app_name.gsub( /\s/, '_' ).downcase
|
|
32
|
+
db_name = to_mole_db( app_name, env )
|
|
33
|
+
raise "Invalid mole database #{db_name}" unless mole_db?( db_name )
|
|
34
|
+
reset_db!( db_name )
|
|
35
|
+
@db
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# -------------------------------------------------------------------------
|
|
39
|
+
# Inspect current connection databases and weed out mole_xxx databases
|
|
40
|
+
def self.mole_databases
|
|
41
|
+
connection.database_names.select do |db_name|
|
|
42
|
+
db_name if mole_db?( db_name )
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# =========================================================================
|
|
47
|
+
private
|
|
48
|
+
|
|
49
|
+
# -----------------------------------------------------------------------
|
|
50
|
+
# Computes mole_db name from app and env
|
|
51
|
+
def self.to_mole_db( app_name, env )
|
|
52
|
+
"mole_%s_%s_mdb" % [app_name, env]
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# -----------------------------------------------------------------------
|
|
56
|
+
# Reset connection. For testing only!
|
|
57
|
+
def self.reset!
|
|
58
|
+
@connection.close if @connection
|
|
59
|
+
@connection = nil
|
|
60
|
+
@config = nil
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# -----------------------------------------------------------------------
|
|
64
|
+
# Checks if this is a mole database
|
|
65
|
+
def self.mole_db?( db_name )
|
|
66
|
+
return false unless db_name =~ molex
|
|
67
|
+
db = connection.db( db_name )
|
|
68
|
+
cltns = db.collection_names
|
|
69
|
+
return ((%w[users features logs] & cltns).size == 3)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# -----------------------------------------------------------------------
|
|
73
|
+
# Ensures we have the right db connection
|
|
74
|
+
def self.reset_db!( db_name )
|
|
75
|
+
return if @db and @db.name == db_name
|
|
76
|
+
@db = nil
|
|
77
|
+
db( db_name )
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# -----------------------------------------------------------------------
|
|
81
|
+
# Initialize app by reading off mongo configuration parameters if necessary
|
|
82
|
+
# BOZO !!
|
|
83
|
+
# File.join( ENV['HOME'], %w[.wackamole wackamole.yml] )
|
|
84
|
+
#
|
|
85
|
+
def self.init_config( config_file, env )
|
|
86
|
+
begin
|
|
87
|
+
config = YAML.load_file( config_file )
|
|
88
|
+
@config = config[env]
|
|
89
|
+
raise "Invalid environment `#{env}" unless @config
|
|
90
|
+
raise "Unable to find host in - #{@config.inspect}" unless @config.has_key?('host')
|
|
91
|
+
raise "Unable to find port in - #{@config.inspect}" unless @config.has_key?('port')
|
|
92
|
+
rescue => boom
|
|
93
|
+
@config = nil
|
|
94
|
+
raise "Hoy! An error occur loading the config file `#{config_file} -- #{boom}"
|
|
95
|
+
end
|
|
96
|
+
@config
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def self.config
|
|
100
|
+
raise "You must call init_config before using this object" unless @config
|
|
101
|
+
@config
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# -----------------------------------------------------------------------
|
|
105
|
+
# Connects to mongo instance if necessary...
|
|
106
|
+
def self.connection( log=false )
|
|
107
|
+
logger = nil
|
|
108
|
+
if log
|
|
109
|
+
logger = Logger.new($stdout)
|
|
110
|
+
logger.level = Logger::DEBUG
|
|
111
|
+
end
|
|
112
|
+
@connection ||= Mongo::Connection.new( config['host'], config['port'], :logger => logger )
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
# -----------------------------------------------------------------------
|
|
116
|
+
# Fetch database instance
|
|
117
|
+
def self.db( db_name=nil, opts={:strict => true} )
|
|
118
|
+
# puts "#{db_name} -- #{@db.inspect}"
|
|
119
|
+
return @db if @db and !db_name
|
|
120
|
+
return @db if @db and @db.name == db_name
|
|
121
|
+
raise "No database specified" unless db_name
|
|
122
|
+
@db = connection.db( db_name, opts )
|
|
123
|
+
ensure_indexes
|
|
124
|
+
@db
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
# -----------------------------------------------------------------------
|
|
128
|
+
# Make sure the right indexes are set
|
|
129
|
+
def self.ensure_indexes
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
end
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
module Wackamole
|
|
2
|
+
class Feature
|
|
3
|
+
|
|
4
|
+
def self.logs_cltn() Wackamole::Control.collection( 'logs' ) ; end
|
|
5
|
+
def self.features_cltn() Wackamole::Control.collection( 'features' ); end
|
|
6
|
+
|
|
7
|
+
# Pagination size
|
|
8
|
+
def self.default_page_size() @page_size ||= 20; end
|
|
9
|
+
|
|
10
|
+
# ---------------------------------------------------------------------------
|
|
11
|
+
# Find the app name and env for the features collection
|
|
12
|
+
# NOTE: Assumes 1 moled app per db...
|
|
13
|
+
def self.get_app_info
|
|
14
|
+
feature = features_cltn.find_one( {}, :fields => [:app, :env] )
|
|
15
|
+
raise "Unable to find a single feature in db `#{features_cltn.db.name}" unless feature
|
|
16
|
+
{ :app_name => feature['app'], :stage => feature['env'] }
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# ---------------------------------------------------------------------------
|
|
20
|
+
# Paginate top features
|
|
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}', true )
|
|
23
|
+
|
|
24
|
+
features = []
|
|
25
|
+
tops.sort{ |a,b| b['count'] <=> a['count'] }.each do |row|
|
|
26
|
+
features << { :fid => row['fid'], :total => row['count'].to_i }
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
WillPaginate::Collection.create( page, page_size, features.size ) do |pager|
|
|
30
|
+
offset = (page-1)*page_size
|
|
31
|
+
result = features[offset...(offset+page_size)]
|
|
32
|
+
result.each do |u|
|
|
33
|
+
feature = features_cltn.find_one( u[:fid] )
|
|
34
|
+
u[:name] = feature
|
|
35
|
+
end
|
|
36
|
+
pager.replace( result )
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# ---------------------------------------------------------------------------
|
|
41
|
+
# Make sure indexes are setup for users
|
|
42
|
+
def self.ensure_indexes!
|
|
43
|
+
indexes = features_cltn.index_information
|
|
44
|
+
created_count = 0
|
|
45
|
+
|
|
46
|
+
[:ctx].each do |name|
|
|
47
|
+
unless indexes.has_key?( "#{name}_1" )
|
|
48
|
+
features_cltn.create_index( name )
|
|
49
|
+
created_count += 1
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
unless indexes.has_key?( 'app_1_env_1' )
|
|
53
|
+
features_cltn.create_index(
|
|
54
|
+
[
|
|
55
|
+
[:app, Mongo::ASCENDING],
|
|
56
|
+
[:env, Mongo::ASCENDING]
|
|
57
|
+
]
|
|
58
|
+
)
|
|
59
|
+
created_count += 1
|
|
60
|
+
end
|
|
61
|
+
unless indexes.has_key?( 'ctl_1_act_1' )
|
|
62
|
+
features_cltn.create_index(
|
|
63
|
+
[
|
|
64
|
+
[:ctl, Mongo::ASCENDING],
|
|
65
|
+
[:act, Mongo::ASCENDING]
|
|
66
|
+
],
|
|
67
|
+
true
|
|
68
|
+
)
|
|
69
|
+
created_count += 1
|
|
70
|
+
end
|
|
71
|
+
created_count
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
require 'forwardable'
|
|
2
|
+
|
|
3
|
+
module Wackamole
|
|
4
|
+
class Log
|
|
5
|
+
extend ::SingleForwardable
|
|
6
|
+
|
|
7
|
+
def self.logs_cltn() Wackamole::Control.collection( 'logs' ); end
|
|
8
|
+
|
|
9
|
+
def_delegators :logs_cltn, :find, :find_one
|
|
10
|
+
|
|
11
|
+
# Pagination size
|
|
12
|
+
def self.default_page_size() @page_size ||= 20; end
|
|
13
|
+
|
|
14
|
+
# ---------------------------------------------------------------------------
|
|
15
|
+
# Fetch all logs matching the given condition
|
|
16
|
+
def self.paginate( conds, page=1, page_size=default_page_size )
|
|
17
|
+
matching = logs_cltn.find( conds )
|
|
18
|
+
WillPaginate::Collection.create( page, page_size, matching.count ) do |pager|
|
|
19
|
+
pager.replace( logs_cltn.find( conds,
|
|
20
|
+
:sort => [ ['did', 'desc'], ['tid', 'desc'] ],
|
|
21
|
+
:skip => (page-1)*page_size,
|
|
22
|
+
:limit => page_size ).to_a )
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# ---------------------------------------------------------------------------
|
|
27
|
+
# Makes sure the correct indexes are set
|
|
28
|
+
def self.ensure_indexes!
|
|
29
|
+
indexes = logs_cltn.index_information
|
|
30
|
+
created_count = 0
|
|
31
|
+
|
|
32
|
+
[:fid, :uid, :did, :tid].each do |name|
|
|
33
|
+
unless indexes.has_key?( "#{name}_1" )
|
|
34
|
+
logs_cltn.create_index( name )
|
|
35
|
+
created_count += 1
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
unless indexes.has_key?( 'did_-1_tid_-1' )
|
|
39
|
+
logs_cltn.create_index( [ [:did, Mongo::DESCENDING], [:tid, Mongo::DESCENDING] ] )
|
|
40
|
+
created_count += 1
|
|
41
|
+
end
|
|
42
|
+
created_count
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
require 'forwardable'
|
|
2
|
+
|
|
3
|
+
module Wackamole
|
|
4
|
+
class Mission
|
|
5
|
+
extend ::SingleForwardable
|
|
6
|
+
|
|
7
|
+
def self.rollups_cltn() @rollups ||= Wackamole::Control.collection( 'rollups', 'wackamole_mdb', :strict => false ); end
|
|
8
|
+
|
|
9
|
+
def_delegators :rollups_cltn, :find, :find_one
|
|
10
|
+
|
|
11
|
+
# -------------------------------------------------------------------------
|
|
12
|
+
# Allows user to clear out perf or fault state til the next tick...
|
|
13
|
+
def self.reset!( app, env, type )
|
|
14
|
+
rollups_cltn.update( { :app => app }, { '$set' => { "envs.#{env}.#{type}" => 0 } } )
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# -------------------------------------------------------------------------
|
|
18
|
+
# Clean up rollups. Check if mole_db is still around
|
|
19
|
+
def self.clean_up!
|
|
20
|
+
databases = Wackamole::Control.mole_databases
|
|
21
|
+
con = Wackamole::Control.connection
|
|
22
|
+
rollups = rollups_cltn.find( {} )
|
|
23
|
+
delete_list = []
|
|
24
|
+
rollups.each do |rollup|
|
|
25
|
+
app = rollup['app']
|
|
26
|
+
envs_info = rollup[envs].keys
|
|
27
|
+
envs_info.each do |env|
|
|
28
|
+
db_name = Wackamole::Control.to_mole_db( app, env )
|
|
29
|
+
delete_list << env unless databases.include?( db_name )
|
|
30
|
+
end
|
|
31
|
+
# if app is no longer around blow away the rollup
|
|
32
|
+
if delete_list.size == envs_info.size
|
|
33
|
+
rollups_cltn.remove( { :_id => rollup['_id'] } )
|
|
34
|
+
else
|
|
35
|
+
delete_list.each do |env|
|
|
36
|
+
rollup[envs].delete( env )
|
|
37
|
+
end
|
|
38
|
+
rollups_cltn.save( rollup, :safe => true ) unless delete_list.empty?
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# -------------------------------------------------------------------------
|
|
44
|
+
# Retrieve reports if any...
|
|
45
|
+
# BOZO !! Handle case where report is no longer valid - ie no mole db
|
|
46
|
+
def self.rollups( now, reset )
|
|
47
|
+
clean_up!
|
|
48
|
+
rollups = comb_applications( now, reset )
|
|
49
|
+
rollups.each_pair do |app_name, env_info|
|
|
50
|
+
env_info[envs].each_pair do |env, info|
|
|
51
|
+
info.each_pair do |mole_type, count|
|
|
52
|
+
rollup = rollups_cltn.find_one( { :app => app_name } )
|
|
53
|
+
type_name = to_type_name( mole_type )
|
|
54
|
+
if rollup
|
|
55
|
+
rollup_info = rollup[envs]
|
|
56
|
+
if rollup_info and rollup_info[env]
|
|
57
|
+
(rollup_info[env][type_name] and !reset) ? rollup_info[env][type_name] += count : rollup_info[env][type_name] = count
|
|
58
|
+
elsif rollup_info
|
|
59
|
+
rollup_info[env] = { type_name => count }
|
|
60
|
+
# else
|
|
61
|
+
# rollup_info[envs] = { env => { type_name => count } }
|
|
62
|
+
end
|
|
63
|
+
rollups_cltn.save( rollup, :safe => true )
|
|
64
|
+
else
|
|
65
|
+
row = { :app => app_name, envs => { env => { type_name => count } } }
|
|
66
|
+
rollups_cltn.insert( row, :safe => true )
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
find( {}, :sort => [ [:app, Mongo::ASCENDING], [:env, Mongo::ASCENDING] ] ).to_a
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# =========================================================================
|
|
75
|
+
private
|
|
76
|
+
|
|
77
|
+
# -----------------------------------------------------------------------
|
|
78
|
+
# Map rackamole types to report types
|
|
79
|
+
def self.to_type_name( type )
|
|
80
|
+
case type
|
|
81
|
+
when Rackamole.perf
|
|
82
|
+
"perfs"
|
|
83
|
+
when Rackamole.fault
|
|
84
|
+
"faults"
|
|
85
|
+
when Rackamole.feature
|
|
86
|
+
"features"
|
|
87
|
+
else
|
|
88
|
+
raise "Invalid mole log type `#{type}"
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# ---------------------------------------------------------------------------
|
|
93
|
+
# Check moled apps status - reports any perf/excep that occurred since the
|
|
94
|
+
# last check
|
|
95
|
+
def self.comb_applications( now, reset )
|
|
96
|
+
report = {}
|
|
97
|
+
Wackamole::Control.mole_databases.each do |db_name|
|
|
98
|
+
db = Wackamole::Control.db( db_name )
|
|
99
|
+
|
|
100
|
+
app_name, env = Wackamole::Control.extract_app_info( db_name )
|
|
101
|
+
totals = analyse_logs( db, now, reset )
|
|
102
|
+
|
|
103
|
+
if report[app_name]
|
|
104
|
+
report[app_name][envs][env] = totals
|
|
105
|
+
else
|
|
106
|
+
report[app_name] = { envs => { env => totals } }
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
report
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
# -------------------------------------------------------------------------
|
|
113
|
+
# Report on possible application issues
|
|
114
|
+
def self.amend_report( report, app_name, env, log )
|
|
115
|
+
type = log['typ']
|
|
116
|
+
|
|
117
|
+
if report[app_name]
|
|
118
|
+
env_info = report[app_name][envs]
|
|
119
|
+
if env_info[env]
|
|
120
|
+
env_info[env][type] ? env_info[env][type] += 1 : env_info[env][type] = 1
|
|
121
|
+
else
|
|
122
|
+
env_info[ env ] = { type => 1 }
|
|
123
|
+
end
|
|
124
|
+
else
|
|
125
|
+
report[app_name] = { envs => { env => { type => 1 } } }
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
# -------------------------------------------------------------------------
|
|
130
|
+
# envs key
|
|
131
|
+
def self.envs() @envs ||= 'envs'; end
|
|
132
|
+
|
|
133
|
+
# -------------------------------------------------------------------------
|
|
134
|
+
# computes counts for each mole types
|
|
135
|
+
def self.analyse_logs( db, now, reset )
|
|
136
|
+
check_types = [Rackamole.perf, Rackamole.fault, Rackamole.feature]
|
|
137
|
+
date_id = now.to_date_id.to_s
|
|
138
|
+
time_id = now.to_time_id
|
|
139
|
+
|
|
140
|
+
if reset
|
|
141
|
+
conds = {
|
|
142
|
+
:did => date_id,
|
|
143
|
+
:typ => { '$in' => check_types }
|
|
144
|
+
}
|
|
145
|
+
else
|
|
146
|
+
conds = {
|
|
147
|
+
:did => { '$gte' => date_id },
|
|
148
|
+
:tid => { '$gte' => time_id },
|
|
149
|
+
:typ => { '$in' => check_types }
|
|
150
|
+
}
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
logs = db['logs'].find( conds, :fields => ['typ', 'rti', 'fault', 'fid'] )
|
|
154
|
+
totals =
|
|
155
|
+
{
|
|
156
|
+
Rackamole.feature => 0,
|
|
157
|
+
Rackamole.perf => 0,
|
|
158
|
+
Rackamole.fault => 0
|
|
159
|
+
}
|
|
160
|
+
logs.each { |log| totals[log['typ']] += 1 }
|
|
161
|
+
totals
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
end
|