what 0.0.7 → 0.0.8
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +1 -1
- data/example/modules/custom_module.rb +52 -0
- data/example/what.yml +8 -4
- data/lib/what/config.rb +17 -3
- data/lib/what/formatter.rb +3 -3
- data/lib/what/formatters.rb +4 -4
- data/lib/what/helpers.rb +15 -0
- data/lib/what/modules/base.rb +4 -2
- data/lib/what/modules/unicorn.rb +5 -0
- data/lib/what/modules.rb +13 -8
- data/lib/what/monitor.rb +8 -14
- data/lib/what/server.rb +6 -6
- data/lib/what/version.rb +1 -1
- metadata +5 -4
data/README.md
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
What? A simple server monitoring tool.
|
2
2
|
======================================
|
3
3
|
|
4
|
-
|
4
|
+
<img src="http://rwfitzge.github.com/what.png" title="WHAT !">
|
5
5
|
|
6
6
|
What is a modular, easily-extensible server monitoring tool which is still in
|
7
7
|
the early stages of development.
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# This is an example custom module.
|
2
|
+
class What::Modules::CustomModule < What::Modules::Base
|
3
|
+
# You can provide defaults for any settings you're expecting the config file
|
4
|
+
# to provide.
|
5
|
+
# (optional)
|
6
|
+
DEFAULTS = {
|
7
|
+
'hello' => 'hello',
|
8
|
+
'world' => 'world'
|
9
|
+
}
|
10
|
+
|
11
|
+
# You can use the initialize method to set up any data structures you'll be
|
12
|
+
# using. If you do write an initialize, make sure to call super to populate
|
13
|
+
# the @config object.
|
14
|
+
# (optional)
|
15
|
+
def initialize
|
16
|
+
super
|
17
|
+
@hellos = 1
|
18
|
+
end
|
19
|
+
|
20
|
+
# The check! method is called every Config['interval'] seconds. It should
|
21
|
+
# collect whatever information is needed and put it into instance vars.
|
22
|
+
# (optional)
|
23
|
+
def check!
|
24
|
+
@hellos = Kernel.rand(4) + 1
|
25
|
+
end
|
26
|
+
|
27
|
+
# The health and details methods are called whenever the server receives
|
28
|
+
# an HTTP request.
|
29
|
+
|
30
|
+
# health should return one of the following symbols:
|
31
|
+
# :ok Everything's fine.
|
32
|
+
# :warning There's a problem, but it's not critical.
|
33
|
+
# :alert I need to get out of bed to fix this.
|
34
|
+
# (mandatory)
|
35
|
+
def health
|
36
|
+
:ok
|
37
|
+
end
|
38
|
+
|
39
|
+
# details can return a hash containing any additional information
|
40
|
+
# that might be interesting to the consumer of the status updates.
|
41
|
+
# (optional)
|
42
|
+
def details
|
43
|
+
greeting = []
|
44
|
+
@hellos.times do
|
45
|
+
greeting << @config['hello']
|
46
|
+
end
|
47
|
+
@hellos.times do
|
48
|
+
greeting << @config['world']
|
49
|
+
end
|
50
|
+
{:greeting => greeting.join(' ') + '!'}
|
51
|
+
end
|
52
|
+
end
|
data/example/what.yml
CHANGED
@@ -3,20 +3,24 @@
|
|
3
3
|
### Choose between JSON and YAML formatting. (default: json)
|
4
4
|
formatter: yaml
|
5
5
|
|
6
|
-
### Set the polling interval for all services.
|
7
|
-
interval: 10
|
6
|
+
### Set the polling interval for all services, in seconds. (default: 10)
|
7
|
+
# interval: 10
|
8
8
|
|
9
9
|
### Specify paths containing custom modules to load, relative to this file.
|
10
|
-
|
11
|
-
|
10
|
+
module_paths:
|
11
|
+
- modules
|
12
12
|
|
13
13
|
### List all modules to be monitored.
|
14
14
|
modules:
|
15
15
|
- unicorn
|
16
|
+
- custom_module
|
16
17
|
#- processes
|
17
18
|
|
18
19
|
### Pass parameters into modules.
|
19
20
|
module_config:
|
21
|
+
custom_module:
|
22
|
+
hello: world
|
23
|
+
world: hello
|
20
24
|
unicorn:
|
21
25
|
# minimum number of workers before warning and alert statuses
|
22
26
|
warning: 1
|
data/lib/what/config.rb
CHANGED
@@ -1,4 +1,13 @@
|
|
1
1
|
class What::Config
|
2
|
+
DEFAULTS = {
|
3
|
+
'interval' => 10,
|
4
|
+
'formatter' => 'json',
|
5
|
+
'configs' => [],
|
6
|
+
'module_paths' => [],
|
7
|
+
'modules' => [],
|
8
|
+
'module_config' => {}
|
9
|
+
}
|
10
|
+
|
2
11
|
@config = {}
|
3
12
|
|
4
13
|
def self.load(fn)
|
@@ -7,7 +16,7 @@ class What::Config
|
|
7
16
|
end
|
8
17
|
|
9
18
|
def self.load_primary(fn)
|
10
|
-
@config = YAML.load_file(fn)
|
19
|
+
@config = DEFAULTS.merge(YAML.load_file(fn))
|
11
20
|
@config['base'] ||= File.expand_path(File.dirname(fn))
|
12
21
|
@loaded = true
|
13
22
|
end
|
@@ -16,12 +25,17 @@ class What::Config
|
|
16
25
|
return if !fns
|
17
26
|
|
18
27
|
fns.each do |fn|
|
19
|
-
path = if fn.match(
|
28
|
+
path = if fn.match(%r(^/))
|
20
29
|
fn
|
21
30
|
else
|
22
31
|
File.join(@config['base'], fn)
|
23
32
|
end
|
24
|
-
|
33
|
+
begin
|
34
|
+
opts = YAML.load_file(path)
|
35
|
+
@config.merge!(opts)
|
36
|
+
rescue Exception => e
|
37
|
+
puts "Error loading config file #{path}: #{e}"
|
38
|
+
end
|
25
39
|
end
|
26
40
|
end
|
27
41
|
|
data/lib/what/formatter.rb
CHANGED
@@ -2,11 +2,11 @@ class What::Formatter
|
|
2
2
|
def self.use(name)
|
3
3
|
@formatter = case name
|
4
4
|
when 'json'
|
5
|
-
|
5
|
+
Formatters::JSON.new
|
6
6
|
when 'yaml'
|
7
|
-
|
7
|
+
Formatters::YAML.new
|
8
8
|
else
|
9
|
-
|
9
|
+
raise "Unknown formatter #{name}"
|
10
10
|
end
|
11
11
|
end
|
12
12
|
|
data/lib/what/formatters.rb
CHANGED
@@ -6,9 +6,9 @@ module What::Formatters
|
|
6
6
|
|
7
7
|
globs = [File.join(File.dirname(__FILE__), 'formatters', '*.rb')]
|
8
8
|
|
9
|
-
if
|
10
|
-
|
11
|
-
globs << File.join(
|
9
|
+
if Config['formatter_paths']
|
10
|
+
Config['formatter_paths'].each do |formatter_path|
|
11
|
+
globs << File.join(Config['base'], formatter_path, '*.rb')
|
12
12
|
end
|
13
13
|
end
|
14
14
|
|
@@ -18,6 +18,6 @@ module What::Formatters
|
|
18
18
|
end
|
19
19
|
end
|
20
20
|
|
21
|
-
|
21
|
+
Formatter.use(Config['formatter'])
|
22
22
|
end
|
23
23
|
end
|
data/lib/what/helpers.rb
CHANGED
@@ -1,4 +1,19 @@
|
|
1
1
|
module What::Helpers
|
2
|
+
# Take an array of healths and determine overall health, on
|
3
|
+
# the principle that overall health == the worst sub-health.
|
4
|
+
def self.overall_health(healths)
|
5
|
+
healths.reduce(:ok) do |overall, current|
|
6
|
+
case current
|
7
|
+
when :ok
|
8
|
+
overall
|
9
|
+
when :warning
|
10
|
+
:warning if overall != :alert
|
11
|
+
else
|
12
|
+
:alert
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
2
17
|
# Stolen from Rails (http://api.rubyonrails.org/classes/ActiveSupport/Inflector.html)
|
3
18
|
def self.camelize(lower_case_and_underscored_word, first_letter_in_uppercase = true)
|
4
19
|
if first_letter_in_uppercase
|
data/lib/what/modules/base.rb
CHANGED
@@ -1,10 +1,12 @@
|
|
1
1
|
class What::Modules::Base
|
2
|
+
DEFAULTS = {}
|
3
|
+
|
2
4
|
def initialize
|
3
|
-
@config =
|
5
|
+
@config = DEFAULTS.merge(Config['module_config'][self.name] || {})
|
4
6
|
end
|
5
7
|
|
6
8
|
def name
|
7
|
-
|
9
|
+
Helpers.underscore(self.class.name.split('::').last)
|
8
10
|
end
|
9
11
|
|
10
12
|
def check!
|
data/lib/what/modules/unicorn.rb
CHANGED
data/lib/what/modules.rb
CHANGED
@@ -4,18 +4,23 @@ module What::Modules
|
|
4
4
|
def self.load_all
|
5
5
|
require 'what/modules/base'
|
6
6
|
|
7
|
-
|
7
|
+
default_modules_path = File.join(File.dirname(__FILE__), 'modules')
|
8
|
+
require_dir(included_modules_path)
|
8
9
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
10
|
+
Config['module_paths'].each do |module_path|
|
11
|
+
path = if module_path.match(%r(^/))
|
12
|
+
module_path
|
13
|
+
else
|
14
|
+
File.join(Config['base'], module_path)
|
15
|
+
end
|
16
|
+
require_dir(path)
|
13
17
|
end
|
18
|
+
end
|
14
19
|
|
15
|
-
|
16
|
-
|
20
|
+
private
|
21
|
+
def require_dir(path)
|
22
|
+
Dir[File.join(path, '*.rb')].each do |fn|
|
17
23
|
require fn
|
18
24
|
end
|
19
25
|
end
|
20
|
-
end
|
21
26
|
end
|
data/lib/what/monitor.rb
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
class What::Monitor
|
2
2
|
# don't worry, these method names are ironic
|
3
3
|
def self.go!
|
4
|
-
@modules =
|
5
|
-
name =
|
6
|
-
|
4
|
+
@modules = Config['modules'].map do |m|
|
5
|
+
name = Helpers.camelize(m)
|
6
|
+
Modules.const_get(name).new
|
7
7
|
end
|
8
8
|
|
9
9
|
Thread.abort_on_exception = true
|
@@ -12,20 +12,14 @@ class What::Monitor
|
|
12
12
|
|
13
13
|
def self.do_it(modules)
|
14
14
|
loop do
|
15
|
-
|
15
|
+
healths = []
|
16
16
|
modules.each do |mod|
|
17
17
|
mod.check!
|
18
|
-
|
19
|
-
|
20
|
-
when :warning
|
21
|
-
overall = :warning if overall != :alert
|
22
|
-
else
|
23
|
-
overall = :alert
|
24
|
-
end
|
25
|
-
What::Status[mod.name] = mod.status
|
18
|
+
healths << mod.health
|
19
|
+
Status[mod.name] = mod.status
|
26
20
|
end
|
27
|
-
|
28
|
-
sleep
|
21
|
+
Status[:health] = Helpers.overall_health(healths)
|
22
|
+
sleep Config['interval']
|
29
23
|
end
|
30
24
|
end
|
31
25
|
end
|
data/lib/what/server.rb
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
class What::Server
|
2
2
|
def initialize
|
3
|
-
|
4
|
-
|
5
|
-
|
3
|
+
Modules.load_all
|
4
|
+
Formatters.load_all
|
5
|
+
Monitor.go!
|
6
6
|
end
|
7
7
|
|
8
8
|
def call(_)
|
9
9
|
[
|
10
|
-
|
11
|
-
{'Content-Type' =>
|
12
|
-
|
10
|
+
Status[:health] != :alert ? 200 : 503,
|
11
|
+
{'Content-Type' => Formatter.mime},
|
12
|
+
Formatter.format(Status.all)
|
13
13
|
]
|
14
14
|
end
|
15
15
|
end
|
data/lib/what/version.rb
CHANGED
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: what
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 15
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
9
|
+
- 8
|
10
|
+
version: 0.0.8
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Ryan Lower
|
@@ -16,7 +16,7 @@ autorequire:
|
|
16
16
|
bindir: bin
|
17
17
|
cert_chain: []
|
18
18
|
|
19
|
-
date: 2011-05-
|
19
|
+
date: 2011-05-17 00:00:00 -07:00
|
20
20
|
default_executable:
|
21
21
|
dependencies:
|
22
22
|
- !ruby/object:Gem::Dependency
|
@@ -65,6 +65,7 @@ files:
|
|
65
65
|
- README.md
|
66
66
|
- Rakefile
|
67
67
|
- bin/what
|
68
|
+
- example/modules/custom_module.rb
|
68
69
|
- example/what.yml
|
69
70
|
- lib/what.rb
|
70
71
|
- lib/what/config.rb
|