what 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/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in what.gemspec
4
+ gemspec
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
data/bin/what ADDED
@@ -0,0 +1,28 @@
1
+ require 'rubygems'
2
+ require 'optparse'
3
+ require 'what'
4
+
5
+ opts = OptionParser.new do |opts|
6
+ opts.banner = "Usage: what [options]"
7
+ opts.separator ""
8
+
9
+ opts.on('-c', '--config FILE', 'Specify the location of the YAML config file.') do |fn|
10
+ What::Config.load(fn)
11
+ end
12
+
13
+ opts.on_tail('-h', '--help', 'Show this message.') do
14
+ puts opts
15
+ exit
16
+ end
17
+ end
18
+ opts.parse!(ARGV)
19
+
20
+ unless What::Config.loaded?
21
+ puts opts
22
+ exit
23
+ end
24
+
25
+ Thin::Server.start('0.0.0.0', 8164) do
26
+ run What::Server.new
27
+ end
28
+
data/example/what.yml ADDED
@@ -0,0 +1,27 @@
1
+ # Config file for the What monitoring system.
2
+
3
+ ### Set the polling interval for all services.
4
+ interval: 10
5
+
6
+ ### Specify paths containing custom modules to load, relative to this file.
7
+ # module_paths:
8
+ # - modules
9
+
10
+ ### List all modules to be monitored.
11
+ modules:
12
+ - unicorn
13
+ # - ram
14
+ # - redis
15
+ # - dir
16
+ # - whatever
17
+
18
+ ### Pass parameters into modules.
19
+ # module_config:
20
+ # ram:
21
+ # min: nil
22
+ # dir:
23
+ # path: '/mnt/datastore'
24
+
25
+ ### Specify any other config files to load.
26
+ # configs:
27
+ # - more_config/stuff.yml
@@ -0,0 +1,43 @@
1
+ class What::Config
2
+ @config = {}
3
+
4
+ def self.load(fn)
5
+ load_primary(fn)
6
+ load_secondary(@config['configs'])
7
+ end
8
+
9
+ def self.load_primary(fn)
10
+ @config = YAML.load_file(fn)
11
+ @config['base'] ||= File.expand_path(File.dirname(fn))
12
+ @loaded = true
13
+ end
14
+
15
+ def self.load_secondary(fns)
16
+ return if !fns
17
+
18
+ fns.each do |fn|
19
+ path = if fn.match(/^\//)
20
+ fn
21
+ else
22
+ File.join(@config['base'], fn)
23
+ end
24
+ @config.merge!(YAML.load_file(path))
25
+ end
26
+ end
27
+
28
+ def self.loaded?
29
+ @loaded
30
+ end
31
+
32
+ def self.[](attr)
33
+ @config[attr]
34
+ end
35
+
36
+ def self.[]=(attr, val)
37
+ @config[attr] = val
38
+ end
39
+
40
+ def self.all
41
+ @config
42
+ end
43
+ end
@@ -0,0 +1,20 @@
1
+ module What::Helpers
2
+ # Stolen from Rails (http://api.rubyonrails.org/classes/ActiveSupport/Inflector.html)
3
+ def self.camelize(lower_case_and_underscored_word, first_letter_in_uppercase = true)
4
+ if first_letter_in_uppercase
5
+ lower_case_and_underscored_word.to_s.gsub(/\/(.?)/) { "::#{$1.upcase}" }.gsub(/(?:^|_)(.)/) { $1.upcase }
6
+ else
7
+ lower_case_and_underscored_word.to_s[0].chr.downcase + camelize(lower_case_and_underscored_word)[1..-1]
8
+ end
9
+ end
10
+
11
+ def self.underscore(camel_cased_word)
12
+ word = camel_cased_word.to_s.dup
13
+ word.gsub!(/::/, '/')
14
+ word.gsub!(/([A-Z]+)([A-Z][a-z])/,'\1_\2')
15
+ word.gsub!(/([a-z\d])([A-Z])/,'\1_\2')
16
+ word.tr!("-", "_")
17
+ word.downcase!
18
+ word
19
+ end
20
+ end
@@ -0,0 +1,26 @@
1
+ class What::Modules::Base
2
+ def initialize
3
+ @config = What::Config[self.name]
4
+ end
5
+
6
+ def name
7
+ What::Helpers.underscore(self.class.name.split('::').last)
8
+ end
9
+
10
+ def check!
11
+ raise "Module #{self.class.name} doesn't override 'check!'"
12
+ end
13
+
14
+ def status
15
+ { :health => health }.merge(details)
16
+ end
17
+
18
+ def health
19
+ raise "Module #{self.class.name} doesn't override 'health'"
20
+ end
21
+
22
+ def details
23
+ {}
24
+ end
25
+ end
26
+
@@ -0,0 +1,22 @@
1
+ class What::Modules::Unicorn < What::Modules::Base
2
+ @unicorns = []
3
+
4
+ def check!
5
+ @unicorns = `ps aux`.grep(/unicorn_rails worker/).map do |ln|
6
+ ln =~ /^\w+\s+(\d+).*(\d+:\d\d(?:\.\d\d)?) unicorn/
7
+ {:pid => $1, :cpu_time => $2}
8
+ end
9
+ end
10
+
11
+ def health
12
+ if @unicorns.count > 0
13
+ :ok
14
+ else
15
+ :alert
16
+ end
17
+ end
18
+
19
+ def details
20
+ {:workers => @unicorns.count, :details => @unicorns}
21
+ end
22
+ end
@@ -0,0 +1,19 @@
1
+ module What::Modules
2
+ # load all modules defined in what/modules, in addition to any paths
3
+ # specified in the config file.
4
+ def self.load_all
5
+ globs = [File.join(File.dirname(__FILE__), 'modules', '*.rb')]
6
+
7
+ if What::Config['module_paths']
8
+ What::Config['module_paths'].each do |module_path|
9
+ globs << File.join(What::Config['base'], module_path, '*.rb')
10
+ end
11
+ end
12
+
13
+ globs.each do |glob|
14
+ Dir[glob].each do |fn|
15
+ require fn
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,30 @@
1
+ class What::Monitor
2
+ def self.go!
3
+ @modules = What::Config['modules'].map do |m|
4
+ name = What::Helpers.camelize(m)
5
+ What::Modules.const_get(name).new
6
+ end
7
+
8
+ Thread.abort_on_exception = true
9
+ @thread = Thread.new(@modules) { |modules| self.do_it(modules) }
10
+ end
11
+
12
+ def self.do_it(modules)
13
+ loop do
14
+ overall = :ok
15
+ modules.each do |mod|
16
+ mod.check!
17
+ case mod.health
18
+ when :ok
19
+ when :warning
20
+ overall = :warning if overall != :alert
21
+ else
22
+ overall = :alert
23
+ end
24
+ What::Status[mod.name] = mod.status
25
+ end
26
+ What::Status[:health] = overall
27
+ sleep What::Config['interval']
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,14 @@
1
+ class What::Server
2
+ def initialize
3
+ What::Modules.load_all
4
+ What::Monitor.go!
5
+ end
6
+
7
+ def call(_)
8
+ [
9
+ What::Status[:health] != :alert ? 200 : 503,
10
+ {'Content-Type' => 'application/json'},
11
+ JSON.unparse(What::Status.all) + "\n"
12
+ ]
13
+ end
14
+ end
@@ -0,0 +1,15 @@
1
+ class What::Status
2
+ @status = {}
3
+
4
+ def self.[](attr)
5
+ @status[attr]
6
+ end
7
+
8
+ def self.[]=(attr, val)
9
+ @status[attr] = val
10
+ end
11
+
12
+ def self.all
13
+ @status
14
+ end
15
+ end
@@ -0,0 +1,3 @@
1
+ module What
2
+ VERSION = "0.0.1"
3
+ end
data/lib/what.rb ADDED
@@ -0,0 +1,14 @@
1
+ module What
2
+ end
3
+
4
+ require 'json'
5
+ require 'yaml'
6
+ require 'thin'
7
+
8
+ require 'what/version'
9
+ require 'what/helpers'
10
+ require 'what/config'
11
+ require 'what/status'
12
+ require 'what/modules'
13
+ require 'what/monitor'
14
+ require 'what/server'
data/what.gemspec ADDED
@@ -0,0 +1,26 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "what/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "what"
7
+ s.version = What::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Ryan Lower", "Ryan Fitzgerald"]
10
+ s.email = ["team@academia.edu"]
11
+ s.homepage = "http://academia.edu/"
12
+ s.summary = %q{Modular server monitoring with JSON endpoint}
13
+ s.description = %q{What runs a Thin server which returns a JSON object representing
14
+ the state of services running on a machine. It currently only includes a
15
+ module for monitoring Unicorn workers, but it's easy to add custom modules.}
16
+
17
+ s.rubyforge_project = "what"
18
+
19
+ s.files = `git ls-files`.split("\n")
20
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
21
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
22
+ s.require_paths = ["lib"]
23
+
24
+ s.add_dependency("thin")
25
+ s.add_dependency("json")
26
+ end
metadata ADDED
@@ -0,0 +1,114 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: what
3
+ version: !ruby/object:Gem::Version
4
+ hash: 29
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 1
10
+ version: 0.0.1
11
+ platform: ruby
12
+ authors:
13
+ - Ryan Lower
14
+ - Ryan Fitzgerald
15
+ autorequire:
16
+ bindir: bin
17
+ cert_chain: []
18
+
19
+ date: 2011-05-10 00:00:00 -07:00
20
+ default_executable:
21
+ dependencies:
22
+ - !ruby/object:Gem::Dependency
23
+ name: thin
24
+ prerelease: false
25
+ requirement: &id001 !ruby/object:Gem::Requirement
26
+ none: false
27
+ requirements:
28
+ - - ">="
29
+ - !ruby/object:Gem::Version
30
+ hash: 3
31
+ segments:
32
+ - 0
33
+ version: "0"
34
+ type: :runtime
35
+ version_requirements: *id001
36
+ - !ruby/object:Gem::Dependency
37
+ name: json
38
+ prerelease: false
39
+ requirement: &id002 !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - ">="
43
+ - !ruby/object:Gem::Version
44
+ hash: 3
45
+ segments:
46
+ - 0
47
+ version: "0"
48
+ type: :runtime
49
+ version_requirements: *id002
50
+ description: |-
51
+ What runs a Thin server which returns a JSON object representing
52
+ the state of services running on a machine. It currently only includes a
53
+ module for monitoring Unicorn workers, but it's easy to add custom modules.
54
+ email:
55
+ - team@academia.edu
56
+ executables:
57
+ - what
58
+ extensions: []
59
+
60
+ extra_rdoc_files: []
61
+
62
+ files:
63
+ - .gitignore
64
+ - Gemfile
65
+ - Rakefile
66
+ - bin/what
67
+ - example/what.yml
68
+ - lib/what.rb
69
+ - lib/what/config.rb
70
+ - lib/what/helpers.rb
71
+ - lib/what/modules.rb
72
+ - lib/what/modules/base.rb
73
+ - lib/what/modules/unicorn.rb
74
+ - lib/what/monitor.rb
75
+ - lib/what/server.rb
76
+ - lib/what/status.rb
77
+ - lib/what/version.rb
78
+ - what.gemspec
79
+ has_rdoc: true
80
+ homepage: http://academia.edu/
81
+ licenses: []
82
+
83
+ post_install_message:
84
+ rdoc_options: []
85
+
86
+ require_paths:
87
+ - lib
88
+ required_ruby_version: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ">="
92
+ - !ruby/object:Gem::Version
93
+ hash: 3
94
+ segments:
95
+ - 0
96
+ version: "0"
97
+ required_rubygems_version: !ruby/object:Gem::Requirement
98
+ none: false
99
+ requirements:
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ hash: 3
103
+ segments:
104
+ - 0
105
+ version: "0"
106
+ requirements: []
107
+
108
+ rubyforge_project: what
109
+ rubygems_version: 1.5.1
110
+ signing_key:
111
+ specification_version: 3
112
+ summary: Modular server monitoring with JSON endpoint
113
+ test_files: []
114
+