system_health 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.
- checksums.yaml +7 -0
- data/.gitignore +22 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +117 -0
- data/Rakefile +2 -0
- data/app/controllers/system_health/monitors_controller.rb +21 -0
- data/config/routes.rb +5 -0
- data/lib/system_health.rb +19 -0
- data/lib/system_health/configuration.rb +5 -0
- data/lib/system_health/engine.rb +3 -0
- data/lib/system_health/monitor.rb +33 -0
- data/lib/system_health/monitors/base.rb +9 -0
- data/lib/system_health/version.rb +3 -0
- data/spec/lib/system_health/monitor_spec.rb +57 -0
- data/system_health.gemspec +26 -0
- metadata +118 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 96a950da89a77567a3adbde6e62909067be4f278
|
4
|
+
data.tar.gz: fd3e339d39b4d856d53146082098332936499b77
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 3ba4232c8569ff43d3744a1eabba6d1e5e8057dbf6823dd9f279a28164fd1c64e4e502bbf85534c5a9b84530d4e900883e2279ebaad41aacaf3a08f850dd1d78
|
7
|
+
data.tar.gz: 225c639c4bb66d66ef166255657dd637c65c0721c6ac3a745df0280f4ad89634e4223df46da6fe8a376cc9144bfae9b175409d270b6897957ac4210cc95a6637
|
data/.gitignore
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
.bundle
|
4
|
+
.config
|
5
|
+
.yardoc
|
6
|
+
Gemfile.lock
|
7
|
+
InstalledFiles
|
8
|
+
_yardoc
|
9
|
+
coverage
|
10
|
+
doc/
|
11
|
+
lib/bundler/man
|
12
|
+
pkg
|
13
|
+
rdoc
|
14
|
+
spec/reports
|
15
|
+
test/tmp
|
16
|
+
test/version_tmp
|
17
|
+
tmp
|
18
|
+
*.bundle
|
19
|
+
*.so
|
20
|
+
*.o
|
21
|
+
*.a
|
22
|
+
mkmf.log
|
data/.ruby-gemset
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
system_health
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.2.3
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2016 Stirling Olson
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,117 @@
|
|
1
|
+
# System Health
|
2
|
+
|
3
|
+
The System Health gem can be added to your Rails application to provide
|
4
|
+
a convenient way to regularly look for bad data or other system health
|
5
|
+
indicators. It provides a single endpoint that will generate and error
|
6
|
+
count and enumerate error messages. This count and the messages can be
|
7
|
+
collected by external monitoring tools the look for the HTTP status code
|
8
|
+
(200 when there are no errors or 500 when there is at least one error)
|
9
|
+
and/or inspect the JSON payload that is returned.
|
10
|
+
|
11
|
+
## Installation
|
12
|
+
|
13
|
+
Add this line to your application's Gemfile:
|
14
|
+
|
15
|
+
gem 'system_health'
|
16
|
+
|
17
|
+
And then execute:
|
18
|
+
|
19
|
+
$ bundle
|
20
|
+
|
21
|
+
Or install it yourself as:
|
22
|
+
|
23
|
+
$ gem install system_health
|
24
|
+
|
25
|
+
and then...
|
26
|
+
|
27
|
+
1. create an initializer in config/initializers/system_health.rb
|
28
|
+
|
29
|
+
```ruby
|
30
|
+
SystemHealth.configure do |config|
|
31
|
+
config.monitor_classes = [
|
32
|
+
SystemHealth::Monitors::BadData
|
33
|
+
]
|
34
|
+
end
|
35
|
+
```
|
36
|
+
|
37
|
+
This should define the SYSTEM_HEALTH_MONITOR_CLASSES array with all
|
38
|
+
your monitor classes. There can be as many monitor classes as you wish.
|
39
|
+
|
40
|
+
2. Create your monitor classes
|
41
|
+
|
42
|
+
In lib/system_health/monitors/bad_data.rb create:
|
43
|
+
|
44
|
+
```ruby
|
45
|
+
module SystemHealth
|
46
|
+
module Monitors
|
47
|
+
class BadData < Base
|
48
|
+
def error_messages
|
49
|
+
['some error message here'] if bad_data?
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
def bad_data?
|
55
|
+
# logic here
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
```
|
61
|
+
|
62
|
+
Each monitor should define a public instance method for `error_messages`
|
63
|
+
as an array. If that array is empty then the data is good. When the
|
64
|
+
data is bad, one or more error messages can be placed in that array.
|
65
|
+
That is it!
|
66
|
+
|
67
|
+
3. Define the environment variables
|
68
|
+
|
69
|
+
For applications hosted on Heroku, this might be something like:
|
70
|
+
|
71
|
+
```bash
|
72
|
+
heroku config:add SYSTEM_HEALTH_MONITOR_USERNAME=somenamehere
|
73
|
+
heroku config:add SYSTEM_HEALTH_MONITOR_PASSWORD=somesecrethere
|
74
|
+
```
|
75
|
+
|
76
|
+
on other environments, you'll need to define these elsewhere.
|
77
|
+
|
78
|
+
## Usage
|
79
|
+
|
80
|
+
The System Health gem exposes a single controller endpoint at:
|
81
|
+
/system_health/monitor
|
82
|
+
|
83
|
+
It will return a 200 HTTP status code if there are no errors and a 500
|
84
|
+
HTTP status code if there are any errors. It also returns a JSON
|
85
|
+
payload with data like this:
|
86
|
+
|
87
|
+
```json
|
88
|
+
{
|
89
|
+
"error_count": 2,
|
90
|
+
"messages": ["some error message here", "another error message"]
|
91
|
+
}
|
92
|
+
```
|
93
|
+
|
94
|
+
## To do?
|
95
|
+
|
96
|
+
1. Consider how to deal with long running monitors that may fail with
|
97
|
+
page load limits (e.g. Heroku's 30 second timeout)
|
98
|
+
2. Add ability to run different health monitors at different times or
|
99
|
+
possibly call monitors individually
|
100
|
+
3. Add the ability to generate error notifications directly from System
|
101
|
+
Health instead of relying on external monitoring tools to send these
|
102
|
+
|
103
|
+
## Contributing
|
104
|
+
|
105
|
+
1. Fork it ( https://github.com/[my-github-username]/system_health/fork )
|
106
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
107
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
108
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
109
|
+
5. Create a new Pull Request
|
110
|
+
|
111
|
+
## About Foraker Labs
|
112
|
+
|
113
|
+
[](https://www.foraker.com/)
|
114
|
+
|
115
|
+
[Foraker Labs](https://www.foraker.com/) builds exciting web and mobile apps in Boulder, CO. Our work powers a wide variety of businesses with many different needs. We love open source software, and we're proud to contribute where we can. Interested to learn more? [Contact us today](https://www.foraker.com/contact-us).
|
116
|
+
|
117
|
+
This project is maintained by Foraker Labs. The names and logos of Foraker Labs are fully owned and copyright Foraker Design, LLC.
|
data/Rakefile
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
module SystemHealth
|
2
|
+
class MonitorsController < ApplicationController
|
3
|
+
http_basic_authenticate_with \
|
4
|
+
name: ENV['SYSTEM_HEALTH_USERNAME'],
|
5
|
+
password: ENV['SYSTEM_HEALTH_PASSWORD']
|
6
|
+
|
7
|
+
def show
|
8
|
+
render json: monitor.as_json, status: monitor.http_status
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def monitor
|
14
|
+
@monitor ||= SystemHealth::Monitor.new(monitor_classes)
|
15
|
+
end
|
16
|
+
|
17
|
+
def monitor_classes
|
18
|
+
SystemHealth.configuration.monitor_classes
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/config/routes.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'system_health/configuration'
|
2
|
+
require 'system_health/engine'
|
3
|
+
require 'system_health/monitor'
|
4
|
+
require 'system_health/version'
|
5
|
+
require 'system_health/monitors/base'
|
6
|
+
|
7
|
+
module SystemHealth
|
8
|
+
class << self
|
9
|
+
attr_writer :configuration
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.configuration
|
13
|
+
@configuration ||= Configuration.new
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.configure
|
17
|
+
yield(configuration)
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module SystemHealth
|
2
|
+
class Monitor
|
3
|
+
def initialize(monitor_classes)
|
4
|
+
@monitor_classes = monitor_classes
|
5
|
+
end
|
6
|
+
|
7
|
+
def as_json(options = nil)
|
8
|
+
{
|
9
|
+
error_count: error_count,
|
10
|
+
messages: messages
|
11
|
+
}
|
12
|
+
end
|
13
|
+
|
14
|
+
def http_status
|
15
|
+
error_count > 0 ? 500 : 200
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
attr_reader :monitor_classes
|
20
|
+
|
21
|
+
def error_count
|
22
|
+
monitors.sum(&:error_count)
|
23
|
+
end
|
24
|
+
|
25
|
+
def messages
|
26
|
+
monitors.flat_map(&:error_messages)
|
27
|
+
end
|
28
|
+
|
29
|
+
def monitors
|
30
|
+
@monitors ||= monitor_classes.map(&:new)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'active_support/all'
|
2
|
+
require_relative '../../../lib/system_health/monitor'
|
3
|
+
require_relative '../../../lib/system_health/monitors/base'
|
4
|
+
|
5
|
+
module SystemHealth
|
6
|
+
describe Monitor do
|
7
|
+
|
8
|
+
class MonitorDouble < Monitors::Base
|
9
|
+
def error_messages
|
10
|
+
[]
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
let(:monitor_classes) { [MonitorDouble] }
|
15
|
+
let(:monitor) { described_class.new(monitor_classes) }
|
16
|
+
|
17
|
+
context 'when errors' do
|
18
|
+
before do
|
19
|
+
allow_any_instance_of(MonitorDouble).
|
20
|
+
to receive(:error_messages).
|
21
|
+
and_return(['something broke'])
|
22
|
+
end
|
23
|
+
|
24
|
+
describe '#as_json' do
|
25
|
+
it 'returns error_count and messages' do
|
26
|
+
expect(monitor.as_json).to eq({
|
27
|
+
error_count: 1,
|
28
|
+
messages: ['something broke']
|
29
|
+
})
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe '#http_status' do
|
34
|
+
it 'returns 500' do
|
35
|
+
expect(monitor.http_status).to eq 500
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
context 'when no errors' do
|
41
|
+
describe '#as_json' do
|
42
|
+
it 'returns error_count and messages' do
|
43
|
+
expect(monitor.as_json).to eq({
|
44
|
+
error_count: 0,
|
45
|
+
messages: []
|
46
|
+
})
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
describe '#http_status' do
|
51
|
+
it 'returns 200 when no errors' do
|
52
|
+
expect(monitor.http_status).to eq 200
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'system_health/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "system_health"
|
8
|
+
spec.version = SystemHealth::VERSION
|
9
|
+
spec.authors = ["Stirling Olson"]
|
10
|
+
spec.email = ["seo@foraker.com"]
|
11
|
+
spec.summary = %q{System health monitor for Rails apps}
|
12
|
+
spec.description = %q{}
|
13
|
+
spec.homepage = ""
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_dependency "rails"
|
22
|
+
|
23
|
+
spec.add_development_dependency "bundler", "~> 1.6"
|
24
|
+
spec.add_development_dependency "rake"
|
25
|
+
spec.add_development_dependency "rspec"
|
26
|
+
end
|
metadata
ADDED
@@ -0,0 +1,118 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: system_health
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Stirling Olson
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-12-23 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rails
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bundler
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.6'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.6'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
description: ''
|
70
|
+
email:
|
71
|
+
- seo@foraker.com
|
72
|
+
executables: []
|
73
|
+
extensions: []
|
74
|
+
extra_rdoc_files: []
|
75
|
+
files:
|
76
|
+
- ".gitignore"
|
77
|
+
- ".ruby-gemset"
|
78
|
+
- ".ruby-version"
|
79
|
+
- Gemfile
|
80
|
+
- LICENSE.txt
|
81
|
+
- README.md
|
82
|
+
- Rakefile
|
83
|
+
- app/controllers/system_health/monitors_controller.rb
|
84
|
+
- config/routes.rb
|
85
|
+
- lib/system_health.rb
|
86
|
+
- lib/system_health/configuration.rb
|
87
|
+
- lib/system_health/engine.rb
|
88
|
+
- lib/system_health/monitor.rb
|
89
|
+
- lib/system_health/monitors/base.rb
|
90
|
+
- lib/system_health/version.rb
|
91
|
+
- spec/lib/system_health/monitor_spec.rb
|
92
|
+
- system_health.gemspec
|
93
|
+
homepage: ''
|
94
|
+
licenses:
|
95
|
+
- MIT
|
96
|
+
metadata: {}
|
97
|
+
post_install_message:
|
98
|
+
rdoc_options: []
|
99
|
+
require_paths:
|
100
|
+
- lib
|
101
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
102
|
+
requirements:
|
103
|
+
- - ">="
|
104
|
+
- !ruby/object:Gem::Version
|
105
|
+
version: '0'
|
106
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
requirements: []
|
112
|
+
rubyforge_project:
|
113
|
+
rubygems_version: 2.4.5.1
|
114
|
+
signing_key:
|
115
|
+
specification_version: 4
|
116
|
+
summary: System health monitor for Rails apps
|
117
|
+
test_files:
|
118
|
+
- spec/lib/system_health/monitor_spec.rb
|