Skip to content

Commit

Permalink
Add a generic threshold check class
Browse files Browse the repository at this point in the history
This makes it easier to implement a class of check which compares
a value with a threshold.
  • Loading branch information
thomasleese committed Jul 12, 2018
1 parent 6e16859 commit f1a2519
Show file tree
Hide file tree
Showing 4 changed files with 159 additions and 0 deletions.
41 changes: 41 additions & 0 deletions docs/healthchecks.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,44 @@ This will check:

Each check class gets instanced each time the health check end point is called.
This allows you to cache any complex queries speeding up performance.

## Built-in Checks

### `SidekiqRedis`

This checks that the app has a connection to Redis via Sidekiq.

### `ActiveRecord`

This checks that the app has a connection to the database via ActiveRecord.

### `ThresholdCheck`

This class is the basis for a check which compares a value with a warning or a
critical threshold. To implement this kind of check in your application, you
can inherit from the class.

```ruby
class MyThresholdCheck < GovukHealthcheck::ThresholdCheck
def name
:my_threshold_check
end

def value
# get the value to be checked
end

def total
# (optional) get the total value to be included in the details as extra
# information
end

def warning_threshold
# if the value is above this threshold, its status is warning
end

def critical_threshold
# if the value is above this threshold, its status is critical
end
end
```
1 change: 1 addition & 0 deletions lib/govuk_app_config/govuk_healthcheck.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
require "govuk_app_config/govuk_healthcheck/checkup"
require "govuk_app_config/govuk_healthcheck/active_record"
require "govuk_app_config/govuk_healthcheck/sidekiq_redis"
require "govuk_app_config/govuk_healthcheck/threshold_check"
require "json"

module GovukHealthcheck
Expand Down
50 changes: 50 additions & 0 deletions lib/govuk_app_config/govuk_healthcheck/threshold_check.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
module GovukHealthcheck
class ThresholdCheck
def status
if value >= critical_threshold
:critical
elsif value >= warning_threshold
:warning
else
:ok
end
end

def message
if value >= critical_threshold
"#{value} is above the critical threshold (#{critical_threshold})"
elsif value >= warning_threshold
"#{value} is above the warning threshold (#{warning_threshold})"
else
"#{value} is below the critical and warning thresholds"
end
end

def details
{
value: value,
total: total,
thresholds: {
critical: critical_threshold,
warning: warning_threshold,
},
}
end

def value
raise "This method must be overridden to be the check value."
end

def total
nil # This method can be overriden to provide the total for the check.
end

def critical_threshold
raise "This method must be overriden to be the critical threshold."
end

def warning_threshold
raise "This method must be overriden to be the warning threshold."
end
end
end
67 changes: 67 additions & 0 deletions spec/lib/govuk_healthcheck/threshold_check_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
require "spec_helper"
require "govuk_app_config/govuk_healthcheck"
require_relative "shared_interface"

RSpec.describe GovukHealthcheck::ThresholdCheck do
context "an ok check" do
subject { TestThresholdCheck.new(0, 10, 20) }

it_behaves_like "a healthcheck"

its(:status) { is_expected.to eq(:ok) }
its(:message) { is_expected.to match(/below the critical and warning thresholds/) }
its(:details) do
is_expected.to match(
hash_including(value: 0, thresholds: { warning: 10, critical: 20 })
)
end
end

context "a warning check" do
subject { TestThresholdCheck.new(11, 10, 20) }

it_behaves_like "a healthcheck"

its(:status) { is_expected.to eq(:warning) }
its(:message) { is_expected.to match(/above the warning threshold/) }
its(:details) do
is_expected.to match(
hash_including(value: 11, thresholds: { warning: 10, critical: 20 })
)
end
end

context "a critical check" do
subject { TestThresholdCheck.new(21, 10, 20) }

it_behaves_like "a healthcheck"

its(:status) { is_expected.to eq(:critical) }
its(:message) { is_expected.to match(/above the critical threshold/) }
its(:details) do
is_expected.to match(
hash_including(value: 21, thresholds: { warning: 10, critical: 20 })
)
end
end

context "with a total" do
subject { TestThresholdCheck.new(0, 10, 20, 40) }

it_behaves_like "a healthcheck"

its(:details) { is_expected.to match(hash_including(total: 40)) }
end

class TestThresholdCheck < GovukHealthcheck::ThresholdCheck
def initialize(value, warning_threshold, critical_threshold, total = nil, name = :test)
@value = value
@warning_threshold = warning_threshold
@critical_threshold = critical_threshold
@total = total
@name = name
end

attr_reader :value, :warning_threshold, :critical_threshold, :total, :name
end
end

0 comments on commit f1a2519

Please sign in to comment.