govuk_app_config 1.6.0 → 1.7.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +5 -0
- data/README.md +3 -47
- data/docs/healthchecks.md +156 -0
- data/govuk_app_config.gemspec +1 -0
- data/lib/govuk_app_config/govuk_healthcheck/checkup.rb +7 -3
- data/lib/govuk_app_config/govuk_healthcheck/sidekiq_queue_check.rb +62 -0
- data/lib/govuk_app_config/govuk_healthcheck/sidekiq_queue_latency_check.rb +13 -0
- data/lib/govuk_app_config/govuk_healthcheck/sidekiq_queue_size_check.rb +11 -0
- data/lib/govuk_app_config/govuk_healthcheck/sidekiq_retry_size_check.rb +11 -0
- data/lib/govuk_app_config/govuk_healthcheck/threshold_check.rb +50 -0
- data/lib/govuk_app_config/govuk_healthcheck.rb +5 -0
- data/lib/govuk_app_config/version.rb +1 -1
- metadata +22 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9f7f43376f22e323fe01a108e034bcb673fadd805c5d76971d0f2c291e862206
|
4
|
+
data.tar.gz: 45af98d19295bffce0940c8d2b62ffb4e1fb2d3664f56fb7679ab50ab9be3ad3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1fafd81168467849be5652cf90707bf081b4276a44017d5ea696a855915946998d9d01b5e50b908d48c44f169880fb1c0a44c42821cdab61b06300543bb5c340
|
7
|
+
data.tar.gz: 2110d081b64ccda1902656854d6817821e8d65d93e88fde3437b48efec171486ec0faae091a673aca52d75974f60b4508c32e7e9626f91575028ba5a3ff645c5
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -105,54 +105,10 @@ GovukStatsd.gauge "bork", 100
|
|
105
105
|
GovukStatsd.time("account.activate") { @account.activate! }
|
106
106
|
```
|
107
107
|
|
108
|
-
##
|
108
|
+
## Health Checks
|
109
109
|
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
Custom checks must be a class which implements
|
114
|
-
[this interface](spec/lib/govuk_healthcheck/shared_interface.rb):
|
115
|
-
|
116
|
-
```ruby
|
117
|
-
class CustomCheck
|
118
|
-
def name
|
119
|
-
:custom_check
|
120
|
-
end
|
121
|
-
|
122
|
-
def status
|
123
|
-
ThingChecker.everything_okay? ? OK : CRITICAL
|
124
|
-
end
|
125
|
-
|
126
|
-
# Optional
|
127
|
-
def message
|
128
|
-
"This is an optional custom message"
|
129
|
-
end
|
130
|
-
|
131
|
-
# Optional
|
132
|
-
def details
|
133
|
-
{
|
134
|
-
extra: "This is an optional details hash",
|
135
|
-
}
|
136
|
-
end
|
137
|
-
end
|
138
|
-
```
|
139
|
-
|
140
|
-
For Rails apps:
|
141
|
-
```ruby
|
142
|
-
get "/healthcheck", to: GovukHealthcheck.rack_response(
|
143
|
-
GovukHealthcheck::SidekiqRedis,
|
144
|
-
GovukHealthcheck::ActiveRecord,
|
145
|
-
CustomCheck,
|
146
|
-
)
|
147
|
-
```
|
148
|
-
|
149
|
-
This will check:
|
150
|
-
- Redis connectivity (via Sidekiq)
|
151
|
-
- Database connectivity (via ActiveRecord)
|
152
|
-
- Your custom healthcheck
|
153
|
-
|
154
|
-
Each check class gets instanced each time the health check end point is called.
|
155
|
-
This allows you to cache any complex queries speeding up performance.
|
110
|
+
This Gem provides a common "health check" framework for apps. See [the health
|
111
|
+
check docs](docs/healthchecks.md) for more information on how to use it.
|
156
112
|
|
157
113
|
## Rails logging
|
158
114
|
|
@@ -0,0 +1,156 @@
|
|
1
|
+
# Health Checks
|
2
|
+
|
3
|
+
## Check interface
|
4
|
+
|
5
|
+
A check is expected to be a class with the following methods:
|
6
|
+
|
7
|
+
```ruby
|
8
|
+
class CustomCheck
|
9
|
+
def name
|
10
|
+
:the_name_of_the_check
|
11
|
+
end
|
12
|
+
|
13
|
+
def status
|
14
|
+
if critical_condition?
|
15
|
+
:critical
|
16
|
+
elsif warning_condition?
|
17
|
+
:warning
|
18
|
+
else
|
19
|
+
:ok
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# Optional
|
24
|
+
def message
|
25
|
+
"This is an optional custom message"
|
26
|
+
end
|
27
|
+
|
28
|
+
# Optional
|
29
|
+
def details
|
30
|
+
{
|
31
|
+
extra: "This is an optional details hash",
|
32
|
+
}
|
33
|
+
end
|
34
|
+
|
35
|
+
# Optional
|
36
|
+
def enabled?
|
37
|
+
true # false if the check is not relevant at this time
|
38
|
+
end
|
39
|
+
end
|
40
|
+
```
|
41
|
+
|
42
|
+
It is expected that these methods may cache their results for performance
|
43
|
+
reasons, if a user wants to ensure they have the latest value they should
|
44
|
+
create a new instance of the check first.
|
45
|
+
|
46
|
+
## Including checks in your app
|
47
|
+
|
48
|
+
Set up a route in your rack-compatible Ruby application, and pick the built-in
|
49
|
+
or custom checks you wish to perform.
|
50
|
+
|
51
|
+
For Rails apps:
|
52
|
+
|
53
|
+
```ruby
|
54
|
+
get "/healthcheck", to: GovukHealthcheck.rack_response(
|
55
|
+
GovukHealthcheck::SidekiqRedis,
|
56
|
+
GovukHealthcheck::ActiveRecord,
|
57
|
+
CustomCheck,
|
58
|
+
)
|
59
|
+
```
|
60
|
+
|
61
|
+
## Built-in Checks
|
62
|
+
|
63
|
+
A convention used when naming these classes is that it should end with `Check`
|
64
|
+
if it must be subclassed to work, but a concrete class which works on its own
|
65
|
+
doesn't need that suffix. You should aim to follow this convention in your own
|
66
|
+
apps, ideally putting custom health checks into a `Healthcheck` module.
|
67
|
+
|
68
|
+
### `SidekiqRedis`
|
69
|
+
|
70
|
+
This checks that the app has a connection to Redis via Sidekiq.
|
71
|
+
|
72
|
+
### `ActiveRecord`
|
73
|
+
|
74
|
+
This checks that the app has a connection to the database via ActiveRecord.
|
75
|
+
|
76
|
+
### `ThresholdCheck`
|
77
|
+
|
78
|
+
This class is the basis for a check which compares a value with a warning or a
|
79
|
+
critical threshold.
|
80
|
+
|
81
|
+
```ruby
|
82
|
+
class MyThresholdCheck < GovukHealthcheck::ThresholdCheck
|
83
|
+
def name
|
84
|
+
:my_threshold_check
|
85
|
+
end
|
86
|
+
|
87
|
+
def value
|
88
|
+
# get the value to be checked
|
89
|
+
end
|
90
|
+
|
91
|
+
def total
|
92
|
+
# (optional) get the total value to be included in the details as extra
|
93
|
+
# information
|
94
|
+
end
|
95
|
+
|
96
|
+
def warning_threshold
|
97
|
+
# if the value is above this threshold, its status is warning
|
98
|
+
end
|
99
|
+
|
100
|
+
def critical_threshold
|
101
|
+
# if the value is above this threshold, its status is critical
|
102
|
+
end
|
103
|
+
end
|
104
|
+
```
|
105
|
+
|
106
|
+
### `SidekiqQueueLatencyCheck`
|
107
|
+
|
108
|
+
This class is the basis for a check which compares the Sidekiq queue latencies
|
109
|
+
with warning or critical thresholds.
|
110
|
+
|
111
|
+
```ruby
|
112
|
+
class MySidekiqQueueLatencyCheck < GovukHealthcheck::SidekiqQueueLatencyCheck
|
113
|
+
def warning_threshold(queue:)
|
114
|
+
# the warning threshold for a particular queue
|
115
|
+
end
|
116
|
+
|
117
|
+
def critical_threshold(queue:)
|
118
|
+
# the critical threshold for a particular queue
|
119
|
+
end
|
120
|
+
end
|
121
|
+
```
|
122
|
+
|
123
|
+
### `SidekiqQueueSizeCheck`
|
124
|
+
|
125
|
+
This class is the basis for a check which compares the Sidekiq queue sizes
|
126
|
+
with warning or critical thresholds.
|
127
|
+
|
128
|
+
```ruby
|
129
|
+
class MySidekiqQueueSizeCheck < GovukHealthcheck::SidekiqQueueSizeCheck
|
130
|
+
def warning_threshold(queue:)
|
131
|
+
# the warning threshold for a particular queue
|
132
|
+
end
|
133
|
+
|
134
|
+
def critical_threshold(queue:)
|
135
|
+
# the critical threshold for a particular queue
|
136
|
+
end
|
137
|
+
end
|
138
|
+
```
|
139
|
+
|
140
|
+
|
141
|
+
### `SidekiqRetrySizeCheck`
|
142
|
+
|
143
|
+
Similar to `SidekiqQueueSizeCheck`, this class is the basis for a check which
|
144
|
+
compares the Sidekiq retry set size with a warning and critical threshold.
|
145
|
+
|
146
|
+
```ruby
|
147
|
+
class MySidekiqRetrySizeCheck < GovukHealthcheck::SidekiqRetrySizeCheck
|
148
|
+
def warning_threshold
|
149
|
+
# the warning threshold for the retry set
|
150
|
+
end
|
151
|
+
|
152
|
+
def critical_threshold
|
153
|
+
# the critical threshold for the retry set
|
154
|
+
end
|
155
|
+
end
|
156
|
+
```
|
data/govuk_app_config.gemspec
CHANGED
@@ -29,6 +29,7 @@ Gem::Specification.new do |spec|
|
|
29
29
|
spec.add_development_dependency "bundler", "~> 1.15"
|
30
30
|
spec.add_development_dependency "rake", "~> 10.0"
|
31
31
|
spec.add_development_dependency "rspec", "~> 3.6.0"
|
32
|
+
spec.add_development_dependency "rspec-its", "~> 1.2.0"
|
32
33
|
spec.add_development_dependency "climate_control"
|
33
34
|
spec.add_development_dependency "webmock"
|
34
35
|
spec.add_development_dependency "pry"
|
@@ -43,9 +43,13 @@ module GovukHealthcheck
|
|
43
43
|
end
|
44
44
|
|
45
45
|
def build_component_status(check)
|
46
|
-
|
47
|
-
|
48
|
-
|
46
|
+
if check.respond_to?(:enabled?) && !check.enabled?
|
47
|
+
{ status: :ok, message: "currently disabled" }
|
48
|
+
else
|
49
|
+
component_status = details(check).merge(status: check.status)
|
50
|
+
component_status[:message] = check.message if check.respond_to?(:message)
|
51
|
+
component_status
|
52
|
+
end
|
49
53
|
end
|
50
54
|
|
51
55
|
def details(check)
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module GovukHealthcheck
|
2
|
+
class SidekiqQueueCheck
|
3
|
+
def status
|
4
|
+
queues.each do |name, value|
|
5
|
+
if value >= critical_threshold(queue: name)
|
6
|
+
return :critical
|
7
|
+
elsif value >= warning_threshold(queue: name)
|
8
|
+
return :warning
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
:ok
|
13
|
+
end
|
14
|
+
|
15
|
+
def message
|
16
|
+
messages = queues.map do |name, value|
|
17
|
+
critical = critical_threshold(queue: name)
|
18
|
+
warning = warning_threshold(queue: name)
|
19
|
+
|
20
|
+
if value >= critical
|
21
|
+
"#{name} (#{value}) is above the critical threshold (#{critical})"
|
22
|
+
elsif value >= warning
|
23
|
+
"#{name} (#{value}) is above the warning threshold (#{warning})"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
messages = messages.compact
|
28
|
+
|
29
|
+
if messages.empty?
|
30
|
+
"all queues are below the critical and warning thresholds"
|
31
|
+
else
|
32
|
+
messages.join("\n")
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def details
|
37
|
+
{
|
38
|
+
queues: queues.each_with_object({}) do |(name, value), hash|
|
39
|
+
hash[name] = {
|
40
|
+
value: value,
|
41
|
+
thresholds: {
|
42
|
+
critical: critical_threshold(queue: name),
|
43
|
+
warning: warning_threshold(queue: name),
|
44
|
+
},
|
45
|
+
}
|
46
|
+
end,
|
47
|
+
}
|
48
|
+
end
|
49
|
+
|
50
|
+
def queues
|
51
|
+
raise "This method must be overriden to be a hash of queue names and data."
|
52
|
+
end
|
53
|
+
|
54
|
+
def critical_threshold(queue:)
|
55
|
+
raise "This method must be overriden to be the critical threshold."
|
56
|
+
end
|
57
|
+
|
58
|
+
def warning_threshold(queue:)
|
59
|
+
raise "This method must be overriden to be the warning threshold."
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module GovukHealthcheck
|
2
|
+
class SidekiqQueueLatencyCheck < SidekiqQueueCheck
|
3
|
+
def name
|
4
|
+
:sidekiq_queue_latency
|
5
|
+
end
|
6
|
+
|
7
|
+
def queues
|
8
|
+
@queues ||= Sidekiq::Stats.new.queues.keys.each_with_object({}) do |name, hash|
|
9
|
+
hash[name] = Sidekiq::Queue.new(name).latency
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module GovukHealthcheck
|
2
|
+
class ThresholdCheck
|
3
|
+
def status
|
4
|
+
if value >= critical_threshold
|
5
|
+
:critical
|
6
|
+
elsif value >= warning_threshold
|
7
|
+
:warning
|
8
|
+
else
|
9
|
+
:ok
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def message
|
14
|
+
if value >= critical_threshold
|
15
|
+
"#{value} is above the critical threshold (#{critical_threshold})"
|
16
|
+
elsif value >= warning_threshold
|
17
|
+
"#{value} is above the warning threshold (#{warning_threshold})"
|
18
|
+
else
|
19
|
+
"#{value} is below the critical and warning thresholds"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def details
|
24
|
+
{
|
25
|
+
value: value,
|
26
|
+
total: total,
|
27
|
+
thresholds: {
|
28
|
+
critical: critical_threshold,
|
29
|
+
warning: warning_threshold,
|
30
|
+
},
|
31
|
+
}
|
32
|
+
end
|
33
|
+
|
34
|
+
def value
|
35
|
+
raise "This method must be overridden to be the check value."
|
36
|
+
end
|
37
|
+
|
38
|
+
def total
|
39
|
+
nil # This method can be overriden to provide the total for the check.
|
40
|
+
end
|
41
|
+
|
42
|
+
def critical_threshold
|
43
|
+
raise "This method must be overriden to be the critical threshold."
|
44
|
+
end
|
45
|
+
|
46
|
+
def warning_threshold
|
47
|
+
raise "This method must be overriden to be the warning threshold."
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -1,6 +1,11 @@
|
|
1
1
|
require "govuk_app_config/govuk_healthcheck/checkup"
|
2
2
|
require "govuk_app_config/govuk_healthcheck/active_record"
|
3
3
|
require "govuk_app_config/govuk_healthcheck/sidekiq_redis"
|
4
|
+
require "govuk_app_config/govuk_healthcheck/threshold_check"
|
5
|
+
require "govuk_app_config/govuk_healthcheck/sidekiq_queue_check"
|
6
|
+
require "govuk_app_config/govuk_healthcheck/sidekiq_queue_latency_check"
|
7
|
+
require "govuk_app_config/govuk_healthcheck/sidekiq_queue_size_check"
|
8
|
+
require "govuk_app_config/govuk_healthcheck/sidekiq_retry_size_check"
|
4
9
|
require "json"
|
5
10
|
|
6
11
|
module GovukHealthcheck
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: govuk_app_config
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.7.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- GOV.UK Dev
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-07-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: statsd-ruby
|
@@ -108,6 +108,20 @@ dependencies:
|
|
108
108
|
- - "~>"
|
109
109
|
- !ruby/object:Gem::Version
|
110
110
|
version: 3.6.0
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: rspec-its
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - "~>"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: 1.2.0
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - "~>"
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: 1.2.0
|
111
125
|
- !ruby/object:Gem::Dependency
|
112
126
|
name: climate_control
|
113
127
|
requirement: !ruby/object:Gem::Requirement
|
@@ -168,6 +182,7 @@ files:
|
|
168
182
|
- Rakefile
|
169
183
|
- bin/console
|
170
184
|
- bin/setup
|
185
|
+
- docs/healthchecks.md
|
171
186
|
- govuk_app_config.gemspec
|
172
187
|
- lib/govuk_app_config.rb
|
173
188
|
- lib/govuk_app_config/configure.rb
|
@@ -175,7 +190,12 @@ files:
|
|
175
190
|
- lib/govuk_app_config/govuk_healthcheck.rb
|
176
191
|
- lib/govuk_app_config/govuk_healthcheck/active_record.rb
|
177
192
|
- lib/govuk_app_config/govuk_healthcheck/checkup.rb
|
193
|
+
- lib/govuk_app_config/govuk_healthcheck/sidekiq_queue_check.rb
|
194
|
+
- lib/govuk_app_config/govuk_healthcheck/sidekiq_queue_latency_check.rb
|
195
|
+
- lib/govuk_app_config/govuk_healthcheck/sidekiq_queue_size_check.rb
|
178
196
|
- lib/govuk_app_config/govuk_healthcheck/sidekiq_redis.rb
|
197
|
+
- lib/govuk_app_config/govuk_healthcheck/sidekiq_retry_size_check.rb
|
198
|
+
- lib/govuk_app_config/govuk_healthcheck/threshold_check.rb
|
179
199
|
- lib/govuk_app_config/govuk_logging.rb
|
180
200
|
- lib/govuk_app_config/govuk_statsd.rb
|
181
201
|
- lib/govuk_app_config/govuk_unicorn.rb
|