diff --git a/CHANGELOG.md b/CHANGELOG.md index 20144951..8c9de382 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +# 2.4.0 + +* Add new GovukHealthcheck::Mongoid check +* Add new GovukHealthcheck::RailsCache check + # 2.3.0 * Remove unused SidekiqQueueSizeCheck healthcheck base class diff --git a/docs/healthchecks.md b/docs/healthchecks.md index f481d081..68dc8eca 100644 --- a/docs/healthchecks.md +++ b/docs/healthchecks.md @@ -73,6 +73,15 @@ 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` + +This checks that the Rails cache store, such as Memcached, is acessible by +writing and reading back a cache entry called "healthcheck-cache". + +### `Mongoid` + +This checks that the app has a connection to its Mongo database via Mongoid. + ### `SidekiqRedis` This checks that the app has a connection to Redis via Sidekiq. diff --git a/govuk_app_config.gemspec b/govuk_app_config.gemspec index 24c86c90..cf2fd5e1 100644 --- a/govuk_app_config.gemspec +++ b/govuk_app_config.gemspec @@ -25,7 +25,6 @@ Gem::Specification.new do |spec| spec.add_dependency "statsd-ruby", "~> 1.4.0" spec.add_dependency "unicorn", ">= 5.4", "< 5.8" - spec.add_development_dependency "bundler", "~> 1.15" spec.add_development_dependency "climate_control" spec.add_development_dependency "rack-test", "~> 1.1.0" spec.add_development_dependency "rails", "~> 6" diff --git a/lib/govuk_app_config/govuk_healthcheck.rb b/lib/govuk_app_config/govuk_healthcheck.rb index 5733dd1f..0244e6be 100644 --- a/lib/govuk_app_config/govuk_healthcheck.rb +++ b/lib/govuk_app_config/govuk_healthcheck.rb @@ -1,5 +1,7 @@ require "govuk_app_config/govuk_healthcheck/checkup" require "govuk_app_config/govuk_healthcheck/active_record" +require "govuk_app_config/govuk_healthcheck/mongoid" +require "govuk_app_config/govuk_healthcheck/rails_cache" require "govuk_app_config/govuk_healthcheck/sidekiq_redis" require "govuk_app_config/govuk_healthcheck/threshold_check" require "govuk_app_config/govuk_healthcheck/sidekiq_queue_check" diff --git a/lib/govuk_app_config/govuk_healthcheck/mongoid.rb b/lib/govuk_app_config/govuk_healthcheck/mongoid.rb new file mode 100644 index 00000000..64de50a3 --- /dev/null +++ b/lib/govuk_app_config/govuk_healthcheck/mongoid.rb @@ -0,0 +1,14 @@ +module GovukHealthcheck + class Mongoid + def name + :database_connectivity + end + + def status + ::Mongoid.default_client.database_names.any? + GovukHealthcheck::OK + rescue StandardError + GovukHealthcheck::CRITICAL + end + end +end diff --git a/lib/govuk_app_config/govuk_healthcheck/rails_cache.rb b/lib/govuk_app_config/govuk_healthcheck/rails_cache.rb new file mode 100644 index 00000000..fbf951b9 --- /dev/null +++ b/lib/govuk_app_config/govuk_healthcheck/rails_cache.rb @@ -0,0 +1,16 @@ +module GovukHealthcheck + class RailsCache + def name + :rails_cache + end + + def status + ::Rails.cache.write("healthcheck-cache", true) + raise unless ::Rails.cache.read("healthcheck-cache") + + GovukHealthcheck::OK + rescue StandardError + GovukHealthcheck::CRITICAL + end + end +end diff --git a/lib/govuk_app_config/rails_ext/action_dispatch/debug_exceptions.rb b/lib/govuk_app_config/rails_ext/action_dispatch/debug_exceptions.rb index ed40aacf..76b6e733 100644 --- a/lib/govuk_app_config/rails_ext/action_dispatch/debug_exceptions.rb +++ b/lib/govuk_app_config/rails_ext/action_dispatch/debug_exceptions.rb @@ -27,7 +27,7 @@ def self.should_monkey_patch_log_error?(clazz = ::ActionDispatch::DebugException def self.monkey_patch_log_error(clazz = ::ActionDispatch::DebugExceptions) clazz.class_eval do - private + private def log_error(request, wrapper) logger = logger(request) diff --git a/lib/govuk_app_config/version.rb b/lib/govuk_app_config/version.rb index a25cc16f..e871b138 100644 --- a/lib/govuk_app_config/version.rb +++ b/lib/govuk_app_config/version.rb @@ -1,3 +1,3 @@ module GovukAppConfig - VERSION = "2.3.0".freeze + VERSION = "2.4.0".freeze end diff --git a/spec/lib/govuk_healthcheck/mongoid_spec.rb b/spec/lib/govuk_healthcheck/mongoid_spec.rb new file mode 100644 index 00000000..15443325 --- /dev/null +++ b/spec/lib/govuk_healthcheck/mongoid_spec.rb @@ -0,0 +1,31 @@ +require "spec_helper" +require "govuk_app_config/govuk_healthcheck" +require_relative "shared_interface" + +RSpec.describe GovukHealthcheck::Mongoid do + let(:client) { double(:client, database_names: %w[db]) } + let(:mongoid) { double(:mongoid, default_client: client) } + before { stub_const("Mongoid", mongoid) } + + describe ".status" do + context "when the database is connected" do + it_behaves_like "a healthcheck" + + it "returns OK" do + expect(subject.status).to eq(GovukHealthcheck::OK) + end + end + + context "when the database is not connected" do + before do + allow(client).to receive(:database_names) { raise } + end + + it_behaves_like "a healthcheck" + + it "returns CRITICAL" do + expect(subject.status).to eq(GovukHealthcheck::CRITICAL) + end + end + end +end diff --git a/spec/lib/govuk_healthcheck/rails_cache_spec.rb b/spec/lib/govuk_healthcheck/rails_cache_spec.rb new file mode 100644 index 00000000..23d7be74 --- /dev/null +++ b/spec/lib/govuk_healthcheck/rails_cache_spec.rb @@ -0,0 +1,43 @@ +require "spec_helper" +require "govuk_app_config/govuk_healthcheck" +require_relative "shared_interface" + +RSpec.describe GovukHealthcheck::RailsCache do + let(:cache) { double(:cache, write: true, read: true) } + let(:rails) { double(:mongoid, cache: cache) } + before { stub_const("Rails", rails) } + + describe ".status" do + context "when the cache is available" do + it_behaves_like "a healthcheck" + + it "returns OK" do + expect(subject.status).to eq(GovukHealthcheck::OK) + end + end + + context "when the cache is silently unavailable" do + before do + allow(cache).to receive(:read) { false } + end + + it_behaves_like "a healthcheck" + + it "returns CRITICAL" do + expect(subject.status).to eq(GovukHealthcheck::CRITICAL) + end + end + + context "when the cache is loudly unavailable" do + before do + allow(cache).to receive(:read) { raise } + end + + it_behaves_like "a healthcheck" + + it "returns CRITICAL" do + expect(subject.status).to eq(GovukHealthcheck::CRITICAL) + end + end + end +end