OkComputer
Inspired by the ease of installing and setting up fitter-happier as a Rails application's health check, but frustrated by its lack of flexibility, OK Computer was born. It provides a robust endpoint to perform server health checks with a set of built-in plugins, as well as a simple interface to add your own custom checks.
For more insight into why we built this, check out our blog post introducing OkComputer.
OkComputer supports the following Rails versions, as tested by the CI build matrix:
- 8.1
- 8.0
- 7.2
- 7.1
- 7.0
- 6.1
- 6.0
- 5.2
- 5.1
- 5.0
- 4.2
- 4.1
- 4.0
Not using Rails?
If you use Grape instead of Rails, check out okcomputer-grape.
Installation
Add this line to your application's Gemfile:
gem 'okcomputer'
And then execute:
$ bundle
Or install it yourself as:
$ gem install okcomputer
Usage
Adding OkComputer to your Gemfile mounts its routes at /okcomputer and
registers a simple application check named default. When ActiveRecord is
loaded, it also registers an ActiveRecord connection check named
database. If Sequel is loaded instead, it registers a Sequel database check.
Test the application check without any additional configuration:
$ curl http://localhost:3000/okcomputer
default: PASSED Application is running (0.000s)
Endpoints
| Endpoint | Checks performed |
|---|---|
/okcomputer |
The default application check |
/okcomputer/database |
The registered database check, when present |
/okcomputer/all |
All checks and collections in the default collection, except those registered with skip_all: true |
/okcomputer/:name |
The registered check or collection named :name |
A successful check returns HTTP 200. A failed check, or an aggregate containing a failed check, returns HTTP 500. Requesting an unregistered check returns HTTP 404.
Responses are plain text by default. Append .json or send an
Accept: application/json header to receive JSON:
{
"default": {
"message": "Application is running",
"success": true,
"time": 0.000123
}
}
If Not Using ActiveRecord
We also include a MongoidCheck, but do not register it. If you use Mongoid, replace the default ActiveRecord check like so:
OkComputer::Registry.register "database", OkComputer::MongoidCheck.new
If you use another database adapter, see Registering Custom Checks below to
build your own database check and register it with the name "database" to
replace the built-in check, or use OkComputer::Registry.deregister "database"
to stop checking your database altogether.
Requiring Authentication
Optionally require HTTP Basic authentication to view the results of checks in an initializer, like so:
# config/initializers/okcomputer.rb
OkComputer.require_authentication("username", "password")
To allow access to specific checks without a password, optionally specify the names of the checks:
# config/initializers/okcomputer.rb
OkComputer.require_authentication("username", "password", except: %w(default nonsecret))
Changing the OkComputer Route
By default, OkComputer routes are mounted at /okcomputer. If you'd like to use an alternate route,
you can configure it with:
# config/initializers/okcomputer.rb
OkComputer.mount_at = 'health_checks' # Mounts at /health_checks
For more control of adding OkComputer to your routes, set `OkComputer.mount_at
false` to disable automatic mounting, and you can manually mount the engine
in your routes.rb.
# config/initializers/okcomputer.rb
OkComputer.mount_at = false
# config/routes.rb, at any priority that suits you
mount OkComputer::Engine, at: "/custom_path"
Logging check results
Log check results by setting OkComputer.logger. Note: results will be logged at the info level.
OkComputer.logger = Rails.logger
[okcomputer] mycheck: PASSED (0s)
Registering Additional Checks
Register additional checks in an initializer, like so:
# config/initializers/okcomputer.rb
OkComputer::Registry.register "resque_down", OkComputer::ResqueDownCheck.new
OkComputer::Registry.register "resque_backed_up", OkComputer::ResqueBackedUpCheck.new("critical", 100)
# This check works on 2.4.0 and above versions of resque-scheduler
OkComputer::Registry.register "resque_scheduler_down", OkComputer::ResqueSchedulerCheck.new
# If you're using SolidCache instead of Memcached, use this check instead of CacheCheck
OkComputer::Registry.register "cache", OkComputer::CacheCheckSolidCache.new
# If you're using SolidQueue, these checks monitor its health and throughput.
OkComputer::Registry.register "solid_queue", OkComputer::SolidQueueCheck.new
# Optionally, alert when a specific queue's backlog of ready jobs gets too high:
OkComputer::Registry.register "solid_queue_backed_up", OkComputer::SolidQueueBackedUpCheck.new("default", 100)
# Optionally, alert when scheduled jobs are overdue — a sign the dispatcher has
# stalled and is not promoting jobs to ready.
OkComputer::Registry.register "solid_queue_scheduled_backed_up", OkComputer::SolidQueueScheduledBackedUpCheck.new(0, grace: 2.minutes)
# Optionally, alert when too many jobs have failed in total:
OkComputer::Registry.register "solid_queue_failed_jobs", OkComputer::SolidQueueFailedJobsCheck.new(25)
# Optionally, alert on a rapid increase in failures (more than 10 failures in 300 sec)
OkComputer::Registry.register "solid_queue_failed_jobs_rate", OkComputer::SolidQueueFailedJobsRateCheck.new(10, 300)
Registering Custom Checks
The simplest way to register a check unique to your application is to subclass
OkComputer::Check and implement your own #check method, which sets the
display message with mark_message, and calls mark_failure if anything is
wrong.
# config/initializers/okcomputer.rb
class MyCustomCheck < OkComputer::Check
def check
if rand(10).even?
"Even is great!"
else
mark_failure
"We don't like odd numbers"
end
end
end
OkComputer::Registry.register "check_for_odds", MyCustomCheck.new
Grouping Checks
Use a CheckCollection to expose several related checks from one endpoint. Register
the collection with skip_all: true when the group should not run as part of the
default /okcomputer/all endpoint:
# config/initializers/okcomputer.rb
versions = OkComputer::CheckCollection.new("Versions")
OkComputer::Registry.register "versions", versions, skip_all: true
OkComputer::Registry.register "ruby_version", OkComputer::RubyVersionCheck.new, "versions"
OkComputer::Registry.register "app_version", OkComputer::AppVersionCheck.new, "versions"
The group is available at /okcomputer/versions and /okcomputer/versions.json.
Its checks remain individually available, but neither the group nor its checks run
at /okcomputer/all.
An individual check can also be omitted from /okcomputer/all while retaining its
own endpoint:
OkComputer::Registry.register "ruby_version", OkComputer::RubyVersionCheck.new, skip_all: true
Registering Optional Checks
Register an optional check like so:
# ...
OkComputer::Registry.register "some_optional_check", OkComputer::ResqueBackedUpCheck.new("critical", 100)
# ...
OkComputer.make_optional %w(some_optional_check another_optional_check)
This check will run and report its status, but will not affect the HTTP status code returned.
Customizing plain-text output
The plain-text output flows through Rails' internationalization framework.
Adjust the output as necessary by defining okcomputer.check.passed and
okcomputer.check.failed keys in your setup. The default values are available
in okcomputer.en.yml.
Running checks in parallel
By default, OkComputer runs checks in sequence. If you'd like to run them in parallel, you can configure it with:
# config/initializers/okcomputer.rb
OkComputer.check_in_parallel = true
OkComputer NewRelic Ignore
If NewRelic is installed, OkComputer automatically disables NewRelic monitoring for uptime checks, as it will start to artificially bring your request time down.
If you'd like to intentionally count OkComputer requests in your NewRelic analytics, set:
# config/initializers/okcomputer.rb
OkComputer.analytics_ignore = false
Development
Setup
$ bundle install
Running the test suite
OkComputer tests are written with RSpec.
To run the full test suite:
$ rake spec
You may also use the environment variable RAILS_VERSION with one
of the supported versions of Rails (found at the top of this file) to
bundle and run the tests with a specific version of Rails.
Contributing
- Fork this repository
- Create your feature branch (
git checkout -b my-new-feature) - Commit your changes (
git commit -am 'Add some feature') - Push to the branch (
git push origin my-new-feature) - Create a new pull request on upstream (this repository)
- Update
CHANGELOG.markdownunder anUnreleasedtag version (create a new one at the top if needed) with summarized changes and link to the pull request
Releasing
- Ensure you have push permissions to RubyGems
- Merge all PRs so that
mainis up to date with the new version - Determine the new version (
lib/ok_computer/versionhas the current latest one) by following semantic versioning guidelines - Ensure you're on the
mainbranch and you are locally up to date (git checkout main && git pull) - Run the release script and pass in the new version (
bin/release vX.X.X... thevat the beginning is optional)