app_status 0.1.1 → 1.0.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/README.md +74 -24
- data/app/models/app_status/check_collection.rb +38 -28
- data/lib/app_status/version.rb +1 -1
- data/spec/controllers/status_controller_spec.rb +2 -3
- data/spec/dummy/config/environments/development.rb +2 -2
- data/spec/dummy/log/development.log +0 -0
- data/spec/dummy/log/test.log +9 -0
- data/spec/models/check_collection_spec.rb +130 -44
- metadata +6 -4
data/README.md
CHANGED
@@ -3,6 +3,39 @@
|
|
3
3
|
AppStatus is a Rails engine which makes it easy to expose application status
|
4
4
|
data in a way easily consumed by Nagios or other monitoring packages.
|
5
5
|
|
6
|
+
## Why?
|
7
|
+
|
8
|
+
Defining health checks outside of your application (like in Nagios)
|
9
|
+
has a few different problems.
|
10
|
+
|
11
|
+
1. The people who maintain nagios aren't necessarily
|
12
|
+
the same people who maintain the application.
|
13
|
+
1. Keeping the 2 systems in sync can be non-trivial with a fast-changing
|
14
|
+
application.
|
15
|
+
1. Failing to monitor new features, or monitoring the wrong things, leads
|
16
|
+
to a false sense of security.
|
17
|
+
|
18
|
+
Instead, app_status lets you define your health checks right in the application
|
19
|
+
itself and expose the results as a JSON service which is easy for Nagios
|
20
|
+
to consume.
|
21
|
+
|
22
|
+
The benefits basically come down to 1 major thing: Nagios doesn't need to know
|
23
|
+
anything about your application. All Nagios needs is a 'healthy/not healthy'
|
24
|
+
status report.
|
25
|
+
|
26
|
+
This is good because:
|
27
|
+
|
28
|
+
1. As your app's feature set changes, you can deploy updated health checks
|
29
|
+
at the same time. No need for coordinated updates between the app and
|
30
|
+
the monitoring system.
|
31
|
+
1. Credentials for external services (like databases) can stay with your
|
32
|
+
app. Nagios doesn't need them.
|
33
|
+
1. You don't need nrpe to do local process checks. Your application can do
|
34
|
+
them for itself.
|
35
|
+
1. Your health checks can be testable methods just like all your other code.
|
36
|
+
1. You don't need to duplicate complex queries & other business logic over
|
37
|
+
to Nagios.
|
38
|
+
|
6
39
|
## Installation
|
7
40
|
|
8
41
|
### `Gemfile`
|
@@ -13,8 +46,6 @@ gem 'app_status'
|
|
13
46
|
|
14
47
|
### `config/routes.rb`
|
15
48
|
|
16
|
-
Wire it up.
|
17
|
-
|
18
49
|
```ruby
|
19
50
|
mount AppStatus::Engine, at: "/status"
|
20
51
|
```
|
@@ -30,19 +61,32 @@ This exposes the following URLs
|
|
30
61
|
|
31
62
|
This is where you set up the checks which you want to be run when
|
32
63
|
someone hits the URL above. Set up some calls which evaluate the health
|
33
|
-
of your application and call `
|
64
|
+
of your application and call `add_check` for each one.
|
65
|
+
|
66
|
+
`add_check` expects a service name, plus a block to be evaluated to determine
|
67
|
+
the health of that service. The block should return either a status value, or
|
68
|
+
a 2-element array with status and some details.
|
34
69
|
|
35
70
|
```ruby
|
36
71
|
AppStatus::CheckCollection.configure do |c|
|
37
|
-
|
38
|
-
c.
|
72
|
+
|
73
|
+
c.add_check('some_service') do
|
74
|
+
details = do_something_to_check_your_service
|
75
|
+
status = (details != "FAIL") ? :ok : :critical
|
76
|
+
[status, details]
|
77
|
+
end
|
78
|
+
|
79
|
+
c.add_check('failing_service') do
|
80
|
+
:critical # you can return just a status if desired.
|
81
|
+
end
|
39
82
|
end
|
40
83
|
```
|
41
84
|
|
42
|
-
The
|
43
|
-
|
85
|
+
The details string should be concise. `app_status` does its best to provide
|
86
|
+
readable output, and Nagios does its best to make this impossible to actually
|
87
|
+
do well.
|
44
88
|
|
45
|
-
|
89
|
+
Valid status values (in ascending order of seriousness) are:
|
46
90
|
- :ok
|
47
91
|
- :warning
|
48
92
|
- :critical
|
@@ -50,8 +94,9 @@ Status values (in ascending order of seriousness)
|
|
50
94
|
|
51
95
|
These are set up to be compatible with Nagios.
|
52
96
|
|
53
|
-
|
54
|
-
|
97
|
+
Keep in mind that anyone who hits your status URL can cause your checks to run,
|
98
|
+
so if they expose sensitive data or are a potential DOS vector you should
|
99
|
+
probably protect them with some kind of authentication.
|
55
100
|
|
56
101
|
## Usage
|
57
102
|
|
@@ -62,33 +107,34 @@ Output will look something like this:
|
|
62
107
|
{
|
63
108
|
"status": "critical",
|
64
109
|
"status_code": 2,
|
65
|
-
"
|
110
|
+
"ms": 52,
|
66
111
|
"finished": "2013-10-03T21:28:10Z",
|
67
112
|
"checks": {
|
68
113
|
"some_service": {
|
69
114
|
"status": "ok",
|
70
115
|
"status_code": 0,
|
71
|
-
"details": "Looks good!"
|
116
|
+
"details": "Looks good!",
|
117
|
+
"ms": 30
|
72
118
|
},
|
73
119
|
"failing_service": {
|
74
120
|
"status": "critical",
|
75
121
|
"status_code": 2,
|
76
|
-
"details": "
|
122
|
+
"details": "",
|
123
|
+
"ms": 20
|
77
124
|
}
|
78
125
|
}
|
79
126
|
}
|
80
127
|
```
|
81
128
|
|
82
|
-
The overall status will be the worst
|
83
|
-
individual checks.
|
129
|
+
The overall status will be the worst value observed in your individual checks.
|
84
130
|
|
85
131
|
## Nagios Integration
|
86
132
|
|
87
|
-
[
|
133
|
+
[check_app_status.rb](check_app_status.rb)
|
88
134
|
is a Nagios check script which can be used to monitor the output from `app_status`
|
89
135
|
|
90
136
|
```
|
91
|
-
$
|
137
|
+
$ ./check_app_status.rb --help
|
92
138
|
Nagios check script for app_status. See https://github.com/alexdean/app_status
|
93
139
|
-v, --verbose Output more information
|
94
140
|
-V, --version Output version information
|
@@ -102,14 +148,18 @@ The script's exit status is derived from the overall status returned by the
|
|
102
148
|
server. Individual detail items will be grouped by status for display.
|
103
149
|
(Unknowns are displayed together, then criticals, then warnings, then OKs.)
|
104
150
|
|
105
|
-
Sample output
|
151
|
+
Sample output
|
106
152
|
|
107
153
|
```
|
108
|
-
$
|
109
|
-
|
110
|
-
|
111
|
-
|
154
|
+
$ ./check_app_status.rb --url http://localhost:3000/status
|
155
|
+
|
156
|
+
CRIT failed_service
|
157
|
+
--- failed_service: shit's on fire yo, 501ms
|
158
|
+
|
159
|
+
WARN problematic_service
|
160
|
+
--- problematic_service: not looking good, 2001ms
|
112
161
|
|
113
|
-
|
114
|
-
|
162
|
+
OK ok_process, ok_process_2
|
163
|
+
--- ok_process: these are some details, 0ms
|
164
|
+
--- ok_process_2: more details on another process, 0ms
|
115
165
|
```
|
@@ -4,7 +4,7 @@ module AppStatus
|
|
4
4
|
|
5
5
|
class CheckCollection
|
6
6
|
|
7
|
-
@@
|
7
|
+
@@checks = HashWithIndifferentAccess.new
|
8
8
|
|
9
9
|
# Add checks here.
|
10
10
|
#
|
@@ -24,11 +24,11 @@ module AppStatus
|
|
24
24
|
#
|
25
25
|
# end
|
26
26
|
def self.configure(&block)
|
27
|
-
|
27
|
+
yield self
|
28
28
|
end
|
29
29
|
|
30
30
|
def self.clear_checks!
|
31
|
-
@@
|
31
|
+
@@checks = HashWithIndifferentAccess.new
|
32
32
|
end
|
33
33
|
|
34
34
|
def initialize
|
@@ -39,7 +39,7 @@ module AppStatus
|
|
39
39
|
unknown: 3
|
40
40
|
}.freeze
|
41
41
|
|
42
|
-
@
|
42
|
+
@check_results = HashWithIndifferentAccess.new
|
43
43
|
@eval_finished = nil
|
44
44
|
@eval_time = 0
|
45
45
|
end
|
@@ -50,24 +50,15 @@ module AppStatus
|
|
50
50
|
# example:
|
51
51
|
# value = some_service_check
|
52
52
|
# c.add(:name => 'some_service', :status => :ok, :details => value)
|
53
|
-
def
|
54
|
-
raise ArgumentError, ":name option is required." if !
|
55
|
-
raise ArgumentError, ":status option is required." if ! options[:status]
|
56
|
-
|
57
|
-
name = options[:name].to_sym
|
58
|
-
status = options[:status].to_sym
|
59
|
-
details = options[:details].to_s
|
60
|
-
|
61
|
-
# blow up if someone sends us options we don't understand.
|
62
|
-
other_options = options.keys - [:name, :status, :details]
|
63
|
-
if other_options.size > 0
|
64
|
-
raise ArgumentError, "Unrecognized option(s) for '#{name}' check: #{other_options.join(',')}"
|
65
|
-
end
|
53
|
+
def self.add_check(name, &block)
|
54
|
+
raise ArgumentError, ":name option is required." if ! name
|
55
|
+
# raise ArgumentError, ":status option is required." if ! options[:status]
|
66
56
|
|
67
|
-
|
68
|
-
raise ArgumentError, "Check name '#{name}' has already been added." if
|
57
|
+
name = name.to_sym
|
58
|
+
raise ArgumentError, "Check name '#{name}' has already been added." if @@checks.keys.include?(name.to_s)
|
59
|
+
raise ArgumentError, "No check defined for '#{name}'." if ! block_given?
|
69
60
|
|
70
|
-
|
61
|
+
@@checks[name] = block
|
71
62
|
end
|
72
63
|
|
73
64
|
def valid_status?(status)
|
@@ -77,28 +68,47 @@ module AppStatus
|
|
77
68
|
# run the checks added via configure
|
78
69
|
# results of the checks are available via as_json
|
79
70
|
def evaluate!
|
80
|
-
|
81
|
-
@
|
82
|
-
@@
|
71
|
+
eval_start = Time.now
|
72
|
+
@check_results = {}
|
73
|
+
@@checks.each do |name,proc|
|
74
|
+
check_start = Time.now
|
75
|
+
status, details = proc.call
|
76
|
+
check_time = (Time.now - check_start) * 1000
|
77
|
+
|
78
|
+
status = status.to_sym if status
|
79
|
+
details = details.to_s if details
|
80
|
+
|
81
|
+
if ! valid_status?(status)
|
82
|
+
details = "Check returned invalid status '#{status}'. #{details}".strip
|
83
|
+
status = :unknown
|
84
|
+
end
|
85
|
+
@check_results[name] = {
|
86
|
+
status: status,
|
87
|
+
status_code: @valid_status[status],
|
88
|
+
details: details,
|
89
|
+
ms: check_time.to_i
|
90
|
+
}
|
91
|
+
end
|
92
|
+
|
83
93
|
@eval_finished = Time.now.utc
|
84
|
-
@eval_time = (Time.now -
|
94
|
+
@eval_time = (Time.now - eval_start) * 1000
|
85
95
|
end
|
86
96
|
|
87
97
|
def as_json
|
88
|
-
if @
|
98
|
+
if @check_results.size == 0
|
89
99
|
max_status = :unknown
|
90
100
|
max_int = @valid_status[max_status]
|
91
101
|
else
|
92
|
-
max_int = @
|
102
|
+
max_int = @check_results.inject([]){ |memo,val| memo << val[1][:status_code]; memo}.max
|
93
103
|
max_status = @valid_status.invert[max_int]
|
94
104
|
end
|
95
105
|
|
96
106
|
HashWithIndifferentAccess.new({
|
97
107
|
status: max_status,
|
98
108
|
status_code: max_int,
|
99
|
-
|
109
|
+
ms: @eval_time.to_i,
|
100
110
|
finished: @eval_finished.iso8601,
|
101
|
-
checks: @
|
111
|
+
checks: @check_results
|
102
112
|
})
|
103
113
|
end
|
104
114
|
end
|
data/lib/app_status/version.rb
CHANGED
@@ -4,9 +4,8 @@ describe AppStatus::StatusController do
|
|
4
4
|
|
5
5
|
describe "GET index" do
|
6
6
|
before(:each) do
|
7
|
-
AppStatus::CheckCollection.
|
8
|
-
|
9
|
-
end
|
7
|
+
AppStatus::CheckCollection.clear_checks!
|
8
|
+
AppStatus::CheckCollection.add_check('some_service') {[:ok, 'foo']}
|
10
9
|
end
|
11
10
|
|
12
11
|
it "should render json" do
|
@@ -23,11 +23,11 @@ Dummy::Application.configure do
|
|
23
23
|
config.action_dispatch.best_standards_support = :builtin
|
24
24
|
|
25
25
|
# Raise exception on mass assignment protection for Active Record models
|
26
|
-
config.active_record.mass_assignment_sanitizer = :strict
|
26
|
+
# config.active_record.mass_assignment_sanitizer = :strict
|
27
27
|
|
28
28
|
# Log the query plan for queries taking more than this (works
|
29
29
|
# with SQLite, MySQL, and PostgreSQL)
|
30
|
-
config.active_record.auto_explain_threshold_in_seconds = 0.5
|
30
|
+
# config.active_record.auto_explain_threshold_in_seconds = 0.5
|
31
31
|
|
32
32
|
# Do not compress assets
|
33
33
|
config.assets.compress = false
|
File without changes
|
data/spec/dummy/log/test.log
CHANGED
@@ -41,3 +41,12 @@ Processing by AppStatus::StatusController#index as JSON
|
|
41
41
|
Completed 200 OK in 1ms (Views: 0.3ms)
|
42
42
|
Processing by AppStatus::StatusController#index as HTML
|
43
43
|
Completed 200 OK in 18ms (Views: 17.4ms)
|
44
|
+
Processing by AppStatus::StatusController#index as HTML
|
45
|
+
Rendered /Users/alex/Code/app_status/app/views/app_status/status/index.html.haml within layouts/app_status/application (0.2ms)
|
46
|
+
Completed 200 OK in 23ms (Views: 22.3ms)
|
47
|
+
Processing by AppStatus::StatusController#index as JSON
|
48
|
+
Completed 200 OK in 0ms (Views: 0.2ms)
|
49
|
+
Processing by AppStatus::StatusController#index as JSON
|
50
|
+
Completed 200 OK in 1ms (Views: 0.3ms)
|
51
|
+
Processing by AppStatus::StatusController#index as HTML
|
52
|
+
Completed 200 OK in 16ms (Views: 16.0ms)
|
@@ -6,81 +6,98 @@ describe AppStatus::CheckCollection do
|
|
6
6
|
AppStatus::CheckCollection.clear_checks!
|
7
7
|
end
|
8
8
|
|
9
|
-
describe "
|
9
|
+
describe "configure" do
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
c = AppStatus::CheckCollection.new
|
15
|
-
expect {
|
16
|
-
c.evaluate!
|
17
|
-
}.to raise_error(ArgumentError, ":name option is required.")
|
11
|
+
it "should yield itself" do
|
12
|
+
AppStatus::CheckCollection.configure do |c|
|
13
|
+
c.should eq AppStatus::CheckCollection
|
18
14
|
end
|
15
|
+
end
|
19
16
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
17
|
+
end
|
18
|
+
|
19
|
+
describe "clear_checks!" do
|
20
|
+
it "should remove all checks" do
|
21
|
+
c = AppStatus::CheckCollection.new
|
22
|
+
AppStatus::CheckCollection.add_check('test') { nil }
|
23
|
+
c.evaluate!
|
24
|
+
c.as_json['checks'].size.should eq 1
|
27
25
|
|
28
|
-
|
29
|
-
|
30
|
-
|
26
|
+
AppStatus::CheckCollection.clear_checks!
|
27
|
+
c.evaluate!
|
28
|
+
c.as_json['checks'].size.should eq 0
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe "add_check" do
|
33
|
+
|
34
|
+
describe "validations" do
|
35
|
+
it "should raise an error if name is not supplied" do
|
31
36
|
expect {
|
32
|
-
|
33
|
-
}.to raise_error(ArgumentError, "
|
37
|
+
AppStatus::CheckCollection.add_check
|
38
|
+
}.to raise_error(ArgumentError, "wrong number of arguments (0 for 1)")
|
34
39
|
end
|
35
40
|
|
36
|
-
it "should raise an error if
|
37
|
-
AppStatus::CheckCollection.configure {|c| c.add name: 'foo', status: 'test' }
|
38
|
-
c = AppStatus::CheckCollection.new
|
41
|
+
it "should raise an error if block is not supplied" do
|
39
42
|
expect {
|
40
|
-
|
41
|
-
}.to raise_error(ArgumentError, "
|
43
|
+
AppStatus::CheckCollection.add_check 'some_service'
|
44
|
+
}.to raise_error(ArgumentError, "No check defined for 'some_service'.")
|
42
45
|
end
|
43
46
|
|
44
47
|
it "should raise an error if a :name is used multiple times" do
|
45
|
-
AppStatus::CheckCollection.
|
46
|
-
c.add name: 'foo', status: :ok
|
47
|
-
c.add name: 'foo', status: :critical
|
48
|
-
end
|
49
|
-
c = AppStatus::CheckCollection.new
|
48
|
+
AppStatus::CheckCollection.add_check('foo') {[:ok, 'ok']}
|
50
49
|
expect {
|
51
|
-
|
50
|
+
AppStatus::CheckCollection.add_check('foo') {[:ok, 'ok']}
|
52
51
|
}.to raise_error(ArgumentError, "Check name 'foo' has already been added.")
|
53
52
|
end
|
54
53
|
end
|
55
54
|
|
56
55
|
end
|
57
56
|
|
57
|
+
|
58
58
|
describe "evaluate!" do
|
59
|
+
|
59
60
|
it "should run configured checks each time it is called" do
|
60
61
|
counter = 0
|
61
|
-
|
62
|
-
AppStatus::CheckCollection.configure do |c|
|
63
|
-
num_calls = check.call
|
64
|
-
c.add name: 'something', status: :ok, details: num_calls
|
65
|
-
end
|
62
|
+
AppStatus::CheckCollection.add_check('test') { counter += 1; [:ok, counter] }
|
66
63
|
|
67
64
|
c = AppStatus::CheckCollection.new
|
68
65
|
|
69
66
|
Timecop.freeze '2013-10-04T12:00:00Z' do
|
70
67
|
c.evaluate!
|
71
68
|
c.as_json[:finished].should eq '2013-10-04T12:00:00Z'
|
72
|
-
c.as_json[:checks][:
|
69
|
+
c.as_json[:checks][:test][:details].should eq "1"
|
73
70
|
end
|
74
71
|
|
75
72
|
Timecop.freeze '2013-10-04T01:00:00Z' do
|
76
73
|
c.evaluate!
|
77
74
|
c.as_json[:finished].should eq '2013-10-04T01:00:00Z'
|
78
|
-
c.as_json[:checks][:
|
75
|
+
c.as_json[:checks][:test][:details].should eq "2"
|
79
76
|
end
|
80
77
|
end
|
78
|
+
|
79
|
+
it "should set :unknown status for a check which does not return a status" do
|
80
|
+
AppStatus::CheckCollection.add_check('test') { nil }
|
81
|
+
|
82
|
+
c = AppStatus::CheckCollection.new
|
83
|
+
c.evaluate!
|
84
|
+
c.as_json[:checks][:test][:status].should eq :unknown
|
85
|
+
c.as_json[:checks][:test][:details].should eq "Check returned invalid status ''."
|
86
|
+
end
|
87
|
+
|
88
|
+
it "should set :unknown status for a check which returns an invalid status" do
|
89
|
+
AppStatus::CheckCollection.add_check('test') { 'huh?' }
|
90
|
+
|
91
|
+
c = AppStatus::CheckCollection.new
|
92
|
+
c.evaluate!
|
93
|
+
c.as_json[:checks][:test][:status].should eq :unknown
|
94
|
+
c.as_json[:checks][:test][:details].should eq "Check returned invalid status 'huh?'."
|
95
|
+
end
|
96
|
+
|
81
97
|
end
|
82
98
|
|
83
99
|
describe "as_json" do
|
100
|
+
|
84
101
|
it "should use :unknown status if no checks are configured" do
|
85
102
|
c = AppStatus::CheckCollection.new
|
86
103
|
c.evaluate!
|
@@ -89,17 +106,86 @@ describe AppStatus::CheckCollection do
|
|
89
106
|
data[:status].should eq :unknown
|
90
107
|
data[:checks].should eq({})
|
91
108
|
end
|
92
|
-
end
|
93
109
|
|
94
|
-
|
95
|
-
|
110
|
+
it "should set overall status to match the worst status among configured checks" do
|
111
|
+
c = AppStatus::CheckCollection.new
|
112
|
+
|
113
|
+
AppStatus::CheckCollection.add_check('a') { :ok }
|
114
|
+
|
115
|
+
c.evaluate!
|
116
|
+
c.as_json['status'].should eq :ok
|
117
|
+
c.as_json['checks'].size.should eq 1
|
118
|
+
|
119
|
+
AppStatus::CheckCollection.add_check('b') { :warning }
|
120
|
+
|
121
|
+
c.evaluate!
|
122
|
+
c.as_json['status'].should eq :warning
|
123
|
+
c.as_json['checks'].size.should eq 2
|
124
|
+
|
125
|
+
AppStatus::CheckCollection.add_check('c') { :critical }
|
126
|
+
|
127
|
+
c.evaluate!
|
128
|
+
c.as_json['status'].should eq :critical
|
129
|
+
c.as_json['checks'].size.should eq 3
|
130
|
+
|
131
|
+
AppStatus::CheckCollection.add_check('d') { :unknown }
|
132
|
+
|
133
|
+
c.evaluate!
|
134
|
+
c.as_json['status'].should eq :unknown
|
135
|
+
c.as_json['checks'].size.should eq 4
|
136
|
+
end
|
137
|
+
|
138
|
+
it "should include details on all checks" do
|
96
139
|
AppStatus::CheckCollection.configure do |c|
|
97
|
-
c.
|
140
|
+
c.add_check('test1') { [:ok, 'looks good'] }
|
141
|
+
c.add_check('test2') { [:huh, 'invalid'] }
|
142
|
+
c.add_check('test3') { [:warning, 'not good'] }
|
143
|
+
c.add_check('test4') { [:critical, 'on fire'] }
|
144
|
+
c.add_check('test5') { [:unknown, 'no idea'] }
|
98
145
|
end
|
99
146
|
|
100
147
|
c = AppStatus::CheckCollection.new
|
101
|
-
c.evaluate!
|
102
|
-
|
148
|
+
Timecop.freeze('2013-10-05T12:00:00Z') { c.evaluate! }
|
149
|
+
|
150
|
+
c.as_json.should eq({
|
151
|
+
"status" => :unknown,
|
152
|
+
"status_code" => 3,
|
153
|
+
"ms" => instance_of(Fixnum),
|
154
|
+
"finished" => "2013-10-05T12:00:00Z",
|
155
|
+
"checks" => {
|
156
|
+
"test1" => {
|
157
|
+
"status" => :ok,
|
158
|
+
"status_code" => 0,
|
159
|
+
"details" => "looks good",
|
160
|
+
"ms" => instance_of(Fixnum)
|
161
|
+
},
|
162
|
+
"test2" => {
|
163
|
+
"status" => :unknown,
|
164
|
+
"status_code" => 3,
|
165
|
+
"details" => "Check returned invalid status 'huh'. invalid",
|
166
|
+
"ms" => instance_of(Fixnum)
|
167
|
+
},
|
168
|
+
"test3" => {
|
169
|
+
"status" => :warning,
|
170
|
+
"status_code" => 1,
|
171
|
+
"details" => "not good",
|
172
|
+
"ms" => instance_of(Fixnum)
|
173
|
+
},
|
174
|
+
"test4" => {
|
175
|
+
"status" => :critical,
|
176
|
+
"status_code" => 2,
|
177
|
+
"details" => "on fire",
|
178
|
+
"ms" => instance_of(Fixnum)
|
179
|
+
},
|
180
|
+
"test5" => {
|
181
|
+
"status" => :unknown,
|
182
|
+
"status_code" => 3,
|
183
|
+
"details" => "no idea",
|
184
|
+
"ms" => instance_of(Fixnum)
|
185
|
+
}
|
186
|
+
}
|
187
|
+
})
|
103
188
|
end
|
189
|
+
|
104
190
|
end
|
105
191
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: app_status
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-10-
|
12
|
+
date: 2013-10-07 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rails
|
@@ -168,6 +168,7 @@ files:
|
|
168
168
|
- spec/dummy/config/locales/en.yml
|
169
169
|
- spec/dummy/config/routes.rb
|
170
170
|
- spec/dummy/config.ru
|
171
|
+
- spec/dummy/log/development.log
|
171
172
|
- spec/dummy/log/test.log
|
172
173
|
- spec/dummy/public/404.html
|
173
174
|
- spec/dummy/public/422.html
|
@@ -192,7 +193,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
192
193
|
version: '0'
|
193
194
|
segments:
|
194
195
|
- 0
|
195
|
-
hash:
|
196
|
+
hash: 4001732300146768489
|
196
197
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
197
198
|
none: false
|
198
199
|
requirements:
|
@@ -201,7 +202,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
201
202
|
version: '0'
|
202
203
|
segments:
|
203
204
|
- 0
|
204
|
-
hash:
|
205
|
+
hash: 4001732300146768489
|
205
206
|
requirements: []
|
206
207
|
rubyforge_project:
|
207
208
|
rubygems_version: 1.8.24
|
@@ -231,6 +232,7 @@ test_files:
|
|
231
232
|
- spec/dummy/config/locales/en.yml
|
232
233
|
- spec/dummy/config/routes.rb
|
233
234
|
- spec/dummy/config.ru
|
235
|
+
- spec/dummy/log/development.log
|
234
236
|
- spec/dummy/log/test.log
|
235
237
|
- spec/dummy/public/404.html
|
236
238
|
- spec/dummy/public/422.html
|