okcomputer 0.1.0

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/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2012 YOURNAME
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.markdown ADDED
@@ -0,0 +1,61 @@
1
+ # OK Computer
2
+
3
+ Inspired by the ease of installing and setting up [fitter-happier] as a Rails
4
+ application's health check, but frustrated by its lack of flexibility, OK
5
+ Computer was born. It provides a robust endpoint to perform server health
6
+ checks with a set of built-in plugins, as well as a simple interface to add
7
+ your own custom checks.
8
+
9
+ ## Installation
10
+
11
+ Add this line to your application's Gemfile:
12
+
13
+ gem 'okcomputer'
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install okcomputer
22
+
23
+ ## Usage
24
+
25
+ To perform the default checks (application running and database connection), do nothing other than adding to your application's Gemfile.
26
+
27
+ ### Registering Additional Checks
28
+
29
+ Register additional checks in an initializer, like do:
30
+
31
+ ```ruby
32
+ # config/initializers/okcomputer.rb
33
+ OKComputer::Registry.register "resque", OKComputer::Checks::Resque
34
+ OKComputer::Registry.register "load", OKComputer::Checks::CPULoad
35
+ ```
36
+
37
+ TODO: Figure out interface for configuring checks (e.g., Resque looking for more than 100 jobs in the "critical" queue)
38
+
39
+ ### Registering Custom Checks
40
+
41
+ TODO: Figre out interface for custom checks
42
+
43
+ ## Performing Checks
44
+
45
+ * Perform a simple up check: http://example.com/okcomputer
46
+ * Perform all installed checks: http://example.com/okcomputer/all
47
+ * Perform a specific installed check: http://example.com/okcomputer/database
48
+
49
+ Checks are available as plain text (by default) or JSON by appending .json, e.g.:
50
+ * http://example.com/okcomputer.json
51
+ * http://example.com/okcomputer/all.json
52
+
53
+ ## Contributing
54
+
55
+ 1. Fork it
56
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
57
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
58
+ 4. Push to the branch (`git push origin my-new-feature`)
59
+ 5. Create new Pull Request
60
+
61
+ [fitter-happier]:https://rubygems.org/gems/fitter-happier
data/Rakefile ADDED
@@ -0,0 +1,24 @@
1
+ #!/usr/bin/env rake
2
+ begin
3
+ require 'bundler/setup'
4
+ rescue LoadError
5
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
6
+ end
7
+
8
+ APP_RAKEFILE = File.expand_path("../spec/dummy/Rakefile", __FILE__)
9
+ load 'rails/tasks/engine.rake'
10
+
11
+ Bundler::GemHelper.install_tasks
12
+
13
+ task :default => :spec
14
+
15
+ require "rspec/core/rake_task"
16
+
17
+ RSpec::Core::RakeTask.new(:spec)
18
+
19
+ namespace :spec do
20
+ RSpec::Core::RakeTask.new(:docs) do |t|
21
+ t.rspec_opts = ["--format doc"]
22
+ end
23
+ end
24
+
@@ -0,0 +1,21 @@
1
+ class OkComputerController < ApplicationController
2
+ layout nil
3
+ respond_to :text, :json
4
+
5
+ def index
6
+ checks = OKComputer::Registry.all
7
+
8
+ respond_with checks, status: status_code(checks)
9
+ end
10
+
11
+ def show
12
+ check = OKComputer::Registry.fetch(params[:check])
13
+
14
+ respond_with check, status: status_code(check)
15
+ end
16
+
17
+ def status_code(check)
18
+ check.success? ? :ok : :error
19
+ end
20
+ private :status_code
21
+ end
data/config/routes.rb ADDED
@@ -0,0 +1,5 @@
1
+ Rails.application.routes.draw do
2
+ match "/okcomputer" => "ok_computer#show", defaults: {check: "default", format: "text"}
3
+ match "/okcomputer/all(.:format)" => "ok_computer#index", defaults: {format: "text"}
4
+ match "/okcomputer/(:check)(.:format)" => "ok_computer#show", defaults: {format: "text"}
5
+ end
data/lib/okcomputer.rb ADDED
@@ -0,0 +1,17 @@
1
+ require "okcomputer/engine"
2
+ require "okcomputer/check"
3
+ require "okcomputer/check_collection"
4
+ require "okcomputer/registry"
5
+
6
+ # and the built-in checks
7
+ require "okcomputer/built_in_checks/default_check"
8
+ require "okcomputer/built_in_checks/database_check"
9
+ require "okcomputer/built_in_checks/resque_backed_up_check"
10
+ require "okcomputer/built_in_checks/resque_down_check"
11
+
12
+ module OKComputer
13
+ end
14
+
15
+ OKComputer::Registry.register "default", OKComputer::DefaultCheck.new
16
+ OKComputer::Registry.register "database", OKComputer::DatabaseCheck.new
17
+
@@ -0,0 +1,22 @@
1
+ module OKComputer
2
+ class DatabaseCheck < Check
3
+ # Public: Return the schema version of the database
4
+ def call
5
+ "Schema version: #{schema_version}"
6
+ rescue ConnectionFailed => e
7
+ mark_failure
8
+ "Failed to connect: '#{e}'"
9
+ end
10
+
11
+ # Public: The scema version of the app's database
12
+ #
13
+ # Returns a String with the version number
14
+ def schema_version
15
+ ActiveRecord::Migrator.current_version
16
+ rescue => e
17
+ raise ConnectionFailed, e
18
+ end
19
+
20
+ ConnectionFailed = Class.new(StandardError)
21
+ end
22
+ end
@@ -0,0 +1,8 @@
1
+ module OKComputer
2
+ class DefaultCheck < Check
3
+ # Public: Check that Rails can render anything at all
4
+ def call
5
+ "OKComputer Site Check Passed"
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,31 @@
1
+ module OKComputer
2
+ class ResqueBackedUpCheck < Check
3
+ attr_accessor :queue
4
+ attr_accessor :threshold
5
+
6
+ # Public: Initialize a check for a backed-up Resque queue
7
+ #
8
+ # queue - The name of the Resque queue to check
9
+ # threshold - An Integer to compare the queue's count against to consider
10
+ # it backed up
11
+ def initialize(queue, threshold)
12
+ self.queue = queue
13
+ self.threshold = Integer(threshold)
14
+ end
15
+
16
+ # Public: Check whether the given queue is backed up
17
+ def call
18
+ if count <= threshold
19
+ "Resque queue '#{queue}' at reasonable level (#{count})"
20
+ else
21
+ mark_failure
22
+ "Resque queue '#{queue}' backed up! (#{count})"
23
+ end
24
+ end
25
+
26
+ # Public: The number of jobs in the check's queue
27
+ def count
28
+ Resque.size(queue)
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,36 @@
1
+ module OKComputer
2
+ class ResqueDownCheck < Check
3
+ attr_accessor :queue
4
+
5
+ # Public: Initilize a check for whether Resque is running
6
+ #
7
+ # queue - The name of the Resque queue to check
8
+ def initialize(queue)
9
+ self.queue = queue
10
+ end
11
+
12
+ # Public: Check whether Resque workers are working
13
+ def call
14
+ if queued? and not working?
15
+ mark_failure
16
+ "Resque is DOWN. No workers are working the queue."
17
+ else
18
+ "Resque is working"
19
+ end
20
+ end
21
+
22
+ # Public: Whether the given Resque queue has jobs
23
+ #
24
+ # Returns a Boolean
25
+ def queued?
26
+ Resque.info.fetch(:pending) > 0
27
+ end
28
+
29
+ # Public: Whether the Resque has workers working on a job
30
+ #
31
+ # Returns a Boolean
32
+ def working?
33
+ Resque.info.fetch(:working) > 0
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,46 @@
1
+ module OKComputer
2
+ class Check
3
+ # to be set by Registry upon registration
4
+ attr_accessor :name
5
+ # nil by default, only set to true if the check deems itself failed
6
+ attr_accessor :failure_occurred
7
+
8
+ # Public: Perform the appropriate check
9
+ #
10
+ # Your subclass of Check must define its own #call method. This method
11
+ # must return the string to render when performing the check.
12
+ def call
13
+ raise(CallNotDefined, "Your subclass must define its own #call.")
14
+ end
15
+
16
+ # Public: The text output of performing the check
17
+ #
18
+ # Returns a String
19
+ def to_text
20
+ "#{name}: #{call}"
21
+ end
22
+
23
+ # Public: The JSON output of performing the check
24
+ #
25
+ # Returns a String containing JSON
26
+ def to_json(*args)
27
+ # NOTE swallowing the arguments that Rails passes by default since we don't care. This may prove to be a bad idea
28
+ # Rails passes stuff like this: {:prefixes=>["ok_computer", "application"], :template=>"show", :layout=>#<Proc>}]
29
+ {name => call}.to_json
30
+ end
31
+
32
+ # Public: Whether the check passed
33
+ #
34
+ # Returns a boolean
35
+ def success?
36
+ not failure_occurred
37
+ end
38
+
39
+ # Public: Mark that this check has failed in some way
40
+ def mark_failure
41
+ self.failure_occurred = true
42
+ end
43
+
44
+ CallNotDefined = Class.new(StandardError)
45
+ end
46
+ end
@@ -0,0 +1,42 @@
1
+ module OKComputer
2
+ class CheckCollection
3
+ attr_accessor :registry
4
+
5
+ # Public: Initialize a new CheckCollection
6
+ #
7
+ # registry - a Hash of checks, with keys being unique names and values
8
+ # being Check instances
9
+ def initialize(registry={})
10
+ self.registry = registry
11
+ end
12
+
13
+ # Public: The list of checks in the collection
14
+ #
15
+ # Returns an Array of the registry's values
16
+ def checks
17
+ registry.values
18
+ end
19
+
20
+ # Public: The text of each check in the collection
21
+ #
22
+ # Returns a String
23
+ def to_text
24
+ checks.map(&:to_text).join("\n")
25
+ end
26
+
27
+ # Public: The JSON of each check in the collection
28
+ #
29
+ # Returns a String containing a JSON array of hashes
30
+ def to_json(*args)
31
+ # smooshing their #to_json objects into a JSON array
32
+ "[#{checks.map(&:to_json).join(",")}]"
33
+ end
34
+
35
+ # Public: Whether all the checks succeed
36
+ #
37
+ # Returns a Boolean
38
+ def success?
39
+ checks.all?(&:success?)
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,7 @@
1
+ module OKComputer
2
+ class Engine < ::Rails::Engine
3
+ config.generators do |g|
4
+ g.test_framework :rspec, :view_specs => false
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,51 @@
1
+ # Private: Storage of the checks which have been registered with OKComputer.
2
+ #
3
+ # No one is expected to interact directly with this class, but rather through
4
+ # the outer OKComputer interface.
5
+ module OKComputer
6
+ class Registry
7
+ # Public: Return the check registered to the given name
8
+ #
9
+ # check_name - The name of the check to retrieve
10
+ #
11
+ # Returns the registered check or raises Registry::CheckNotFound
12
+ def self.fetch(check_name)
13
+ registry.fetch(check_name)
14
+ rescue KeyError
15
+ raise CheckNotFound, "No check registered with '#{check_name}'"
16
+ end
17
+
18
+ # Public: Return an object containing all the registered checks
19
+ #
20
+ # Returns a CheckCollection instance
21
+ def self.all
22
+ CheckCollection.new registry
23
+ end
24
+
25
+ # Public: Register the given check with OKComputer
26
+ #
27
+ # check_name - The name of the check to retrieve
28
+ # check_object - Instance of Checker to register
29
+ def self.register(check_name, check_object)
30
+ check_object.name = check_name
31
+ registry[check_name] = check_object
32
+ end
33
+
34
+ # Public: Remove the check of the given name being checked
35
+ #
36
+ # check_name - The name of the check to retrieve
37
+ def self.deregister(check_name)
38
+ registry.delete(check_name)
39
+ end
40
+
41
+ # Private: The list of registered checks, keyed by their unique names
42
+ #
43
+ # Returns a Hash
44
+ def self.registry
45
+ @registry ||= {}
46
+ end
47
+
48
+ # used when fetching a check that has not been registered
49
+ CheckNotFound = Class.new(StandardError)
50
+ end
51
+ end
@@ -0,0 +1,3 @@
1
+ module OKComputer
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :okcomputer do
3
+ # # Task goes here
4
+ # end
metadata ADDED
@@ -0,0 +1,118 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: okcomputer
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Patrick Byrne
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-12-07 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rails
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: '3.0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: '3.0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: sqlite3
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: rspec-rails
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ description: ! "\n Inspired by the simplicity of Fitter Happier, but frustrated
63
+ by its lack of\n flexibility, we built OK Computer. Create and register your
64
+ own custom\n health checks, or choose from the built-in library of checks to
65
+ ensure your\n app is working as intended.\n "
66
+ email:
67
+ - patrick.byrne@tstmedia.com
68
+ executables: []
69
+ extensions: []
70
+ extra_rdoc_files: []
71
+ files:
72
+ - app/controllers/ok_computer_controller.rb
73
+ - config/routes.rb
74
+ - lib/okcomputer/built_in_checks/database_check.rb
75
+ - lib/okcomputer/built_in_checks/default_check.rb
76
+ - lib/okcomputer/built_in_checks/resque_backed_up_check.rb
77
+ - lib/okcomputer/built_in_checks/resque_down_check.rb
78
+ - lib/okcomputer/check.rb
79
+ - lib/okcomputer/check_collection.rb
80
+ - lib/okcomputer/engine.rb
81
+ - lib/okcomputer/registry.rb
82
+ - lib/okcomputer/version.rb
83
+ - lib/okcomputer.rb
84
+ - lib/tasks/okcomputer_tasks.rake
85
+ - MIT-LICENSE
86
+ - Rakefile
87
+ - README.markdown
88
+ homepage: https://github.com/tstmedia/okcomputer
89
+ licenses: []
90
+ post_install_message:
91
+ rdoc_options: []
92
+ require_paths:
93
+ - lib
94
+ required_ruby_version: !ruby/object:Gem::Requirement
95
+ none: false
96
+ requirements:
97
+ - - ! '>='
98
+ - !ruby/object:Gem::Version
99
+ version: '0'
100
+ segments:
101
+ - 0
102
+ hash: 2558154404506305637
103
+ required_rubygems_version: !ruby/object:Gem::Requirement
104
+ none: false
105
+ requirements:
106
+ - - ! '>='
107
+ - !ruby/object:Gem::Version
108
+ version: '0'
109
+ segments:
110
+ - 0
111
+ hash: 2558154404506305637
112
+ requirements: []
113
+ rubyforge_project:
114
+ rubygems_version: 1.8.24
115
+ signing_key:
116
+ specification_version: 3
117
+ summary: A simple, extensible health-check monitor
118
+ test_files: []