govuk_app_config 1.6.0 → 1.7.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 209a3832e7995ecd4fae908416ca9656849489c3b2dd9f287c175029d3c2a683
4
- data.tar.gz: 5c12231bddd44f7fff7dd32c6b21484bc1ff7fef9bb3b7d54bf3abcf266bb46b
3
+ metadata.gz: 9f7f43376f22e323fe01a108e034bcb673fadd805c5d76971d0f2c291e862206
4
+ data.tar.gz: 45af98d19295bffce0940c8d2b62ffb4e1fb2d3664f56fb7679ab50ab9be3ad3
5
5
  SHA512:
6
- metadata.gz: 820ef2c5342d0fc44d64d756bef5732789e65fefb0053b45ca961af214b523401348c2887cf46c93b43734a414b2a276eeb8916c79e85e1143e54dafd2710a61
7
- data.tar.gz: 6fc2796951741d81cbe57712cd4de98d77976e046cecfbd68096b5f7726dbcadf1a6817f5afd557c6d80bee9f8cdaa6e4ad93aa7a628cb17b58a4414065b3877
6
+ metadata.gz: 1fafd81168467849be5652cf90707bf081b4276a44017d5ea696a855915946998d9d01b5e50b908d48c44f169880fb1c0a44c42821cdab61b06300543bb5c340
7
+ data.tar.gz: 2110d081b64ccda1902656854d6817821e8d65d93e88fde3437b48efec171486ec0faae091a673aca52d75974f60b4508c32e7e9626f91575028ba5a3ff645c5
data/CHANGELOG.md CHANGED
@@ -1,3 +1,8 @@
1
+ # 1.7.0
2
+
3
+ * Add various convenience health check classes which make it easier to add
4
+ custom checks into apps without writing lots of code.
5
+
1
6
  # 1.6.0
2
7
 
3
8
  * Make health checks classes rather than instances, allowing internal data to
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
- ## Healthchecks
108
+ ## Health Checks
109
109
 
110
- Set up a route in your rack-compatible Ruby application, and pick the built-in
111
- or custom checks you wish to perform.
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
+ ```
@@ -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
- component_status = details(check).merge(status: check.status)
47
- component_status[:message] = check.message if check.respond_to?(:message)
48
- component_status
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,11 @@
1
+ module GovukHealthcheck
2
+ class SidekiqQueueSizeCheck < SidekiqQueueCheck
3
+ def name
4
+ :sidekiq_queue_size
5
+ end
6
+
7
+ def queues
8
+ @queues ||= Sidekiq::Stats.new.queues
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ module GovukHealthcheck
2
+ class SidekiqRetrySizeCheck < ThresholdCheck
3
+ def name
4
+ :sidekiq_retry_size
5
+ end
6
+
7
+ def value
8
+ Sidekiq::Stats.new.retry_size
9
+ end
10
+ end
11
+ 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
@@ -1,3 +1,3 @@
1
1
  module GovukAppConfig
2
- VERSION = "1.6.0"
2
+ VERSION = "1.7.0"
3
3
  end
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.6.0
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-06-29 00:00:00.000000000 Z
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