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 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