what 0.0.7 → 0.0.8
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/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
|