Skip to content

Commit

Permalink
Merge pull request #244 from alphagov/rewrite-healthcheck-doc
Browse files Browse the repository at this point in the history
Rewrite healthcheck guidance
  • Loading branch information
benthorner authored May 23, 2022
2 parents b3f4fa3 + 5c00d56 commit 25ae9bf
Showing 1 changed file with 36 additions and 108 deletions.
144 changes: 36 additions & 108 deletions docs/healthchecks.md
Original file line number Diff line number Diff line change
@@ -1,47 +1,6 @@
# Health Checks

## Check interface

A check is expected to be a class with the following methods:

```ruby
class CustomCheck
def name
:the_name_of_the_check
end

def status
if critical_condition?
:critical
elsif warning_condition?
:warning
else
:ok
end
end

# Optional
def message
"This is an optional custom message that will show up in the alert in Icinga"
end

# Optional
def details
{
extra: "This is an optional details hash",
}
end

# Optional
def enabled?
true # false if the check is not relevant at this time
end
end
```

It is expected that these methods may cache their results for performance
reasons, if a user wants to ensure they have the latest value they should
create a new instance of the check first.
GOV.UK apps often have special `/healthcheck` routes, which give an indication of whether the app is running and able to respond to requests. [Read about how health checks are used](https://docs.publishing.service.gov.uk/manual/alerts/app-healthcheck-not-ok.html).

## Including checks in your app

Expand All @@ -51,7 +10,7 @@ or custom checks you wish to perform.
For Rails apps:

```ruby
get "/healthcheck", to: GovukHealthcheck.rack_response(
get "/healthcheck/ready", to: GovukHealthcheck.rack_response(
GovukHealthcheck::SidekiqRedis,
GovukHealthcheck::ActiveRecord,
CustomCheck,
Expand All @@ -61,95 +20,64 @@ get "/healthcheck", to: GovukHealthcheck.rack_response(
It also accepts objects, so classes can be initialized:

```ruby
get "/healthcheck", to: GovukHealthcheck.rack_response(
get "/healthcheck/ready", to: GovukHealthcheck.rack_response(
InitializedCheck.new(:param),
)
```

## Built-in Checks

A convention used when naming these classes is that it should end with `Check`
if it must be subclassed to work, but a concrete class which works on its own
doesn't need that suffix. You should aim to follow this convention in your own
apps, ideally putting custom health checks into a `Healthcheck` module.

### `RailsCache`
Built-in checks you can use include:

This checks that the Rails cache store, such as Memcached, is acessible by
writing and reading back a cache entry called "healthcheck-cache".
- `GovukHealthcheck::RailsCache` - checks that the Rails cache store, such as Memcached, is acessible by writing and reading back a cache entry called "healthcheck-cache".

### `Mongoid`
- `GovukHealthcheck::Redis` - checks that the app can connect to Redis by writing and reading back a cache entry called "healthcheck-cache".

This checks that the app has a connection to its Mongo database via Mongoid.
- `GovukHealthcheck::Mongoid` - checks that the app has a connection to its Mongo database via Mongoid.

### `SidekiqRedis`
- `GovukHealthcheck::SidekiqRedis` - checks that the app has a connection to Redis via Sidekiq.

This checks that the app has a connection to Redis via Sidekiq.
- `GovukHealthcheck::ActiveRecord` - checks that the app has a connection to the database via ActiveRecord.

### `ActiveRecord`
## Writing a custom healthcheck

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.
A check is expected to be a class with the following methods:

```ruby
class MyThresholdCheck < GovukHealthcheck::ThresholdCheck
class CustomCheck
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
:the_name_of_the_check
end

def warning_threshold
# if the value is above this threshold, its status is warning
def status
if critical_condition?
:critical
elsif warning_condition?
:warning
else
:ok
end
end

def critical_threshold
# if the value is above this threshold, its status is critical
# Optional
def message
"This is an optional custom message that will show up in the alert in Icinga"
end
end
```

### `SidekiqQueueLatencyCheck`

This class is the basis for a check which compares the Sidekiq queue latencies
with warning or critical thresholds.

```ruby
class MySidekiqQueueLatencyCheck < GovukHealthcheck::SidekiqQueueLatencyCheck
def warning_threshold(queue:)
# the warning threshold for a particular queue
# Optional
def details
{
extra: "This is an optional details hash",
}
end

def critical_threshold(queue:)
# the critical threshold for a particular queue
# Optional
def enabled?
true # false if the check is not relevant at this time
end
end
```

### `SidekiqRetrySizeCheck`

Similar to `SidekiqQueueSizeCheck`, this class is the basis for a check which
compares the Sidekiq retry set size with a warning and critical threshold.

```ruby
class MySidekiqRetrySizeCheck < GovukHealthcheck::SidekiqRetrySizeCheck
def warning_threshold
# the warning threshold for the retry set
end
It is expected that these methods may cache their results for performance
reasons, if a user wants to ensure they have the latest value they should
create a new instance of the check first.

def critical_threshold
# the critical threshold for the retry set
end
end
```
Put custom health checks for your app into a `Healtcheck` module. Each custom check class should end with `Check`.

0 comments on commit 25ae9bf

Please sign in to comment.