🏥

OK Computer で Deep Health Check する

2023/09/12に公開

Leaner 開発チームの黒曜(@kokuyouwind)です。

Kaigi on Rails 2023 の参加登録が始まりましたね。私も現地参加するのでよろしくお願いします。

Deep Health Check パターン

Web サービスを運用する際、アクセスが正しく受け付けられるかを確認するためにヘルスチェック用のエンドポイントを用意するのは定番パターンです。

Leaner でも、元々はヘルスチェック用のエンドポイントを以下のように用意していました。

class HealthController < ActionController::API
  def index
    render json: { status: 'OK' }
  end
end

コンテナ自体のヘルスチェックなど、 Rails サーバーが正常に動作しているか確認する目的であればこういった実装が適切です。

一方で「サービスが問題なく利用できるか」という観点では、「Web サーバーは応答しているがデータベースに繋がっていない」「メール送信サービスに繋がっていない」「非同期ジョブワーカーが動いておらずジョブが実行されていない」など、ミドルウェアや関連コンポーネントの状態も確認したくなってきます。

こうしたシステム全体の健全性をチェックするのが Deep Health Check パターンです。

https://aws.clouddesignpattern.org/index.php/CDP_Deep_Health_Checkパターン.html

Leaner でも APM からの外形監視のために Deep Health Check 用のエンドポイントを導入することにしました。

OK Computer gem

Rails で Deep Health Check を行うための gem はいくつかありますが、今回はOK Computer gemを導入しました。

https://github.com/sportngin/okcomputer/

デフォルトで用意されているチェック項目が豊富で、特に DelayedJob のジョブ数チェックが用意されていたのが決め手です。

チェック項目の設定

公式 README を見れば大体書いてありますが、 config/initializers/okcomputer.rb でチェック項目をカスタマイズできます。

現状は以下のようにしています。

# エンドポイントを `/health` 及び `/health/all` にする
# /health が Web サーバー自体の死活監視用、 /health/all が Deep Health Check 用のエンドポイントになる
OkComputer.mount_at = 'health'

# SMTP サーバーに接続できるかのチェック
OkComputer::Registry.register 'action_mailer', OkComputer::ActionMailerCheck.new
# データベースのマイグレーションが完了しているかのチェック
OkComputer::Registry.register 'database_migration', OkComputer::ActiveRecordMigrationsCheck.new
# Rails Cache が利用できるかのチェック
OkComputer::Registry.register 'cache', OkComputer::GenericCacheCheck.new
# DelayedJob のキューが溜まっていないかのチェック
# 優先度 0 の Job が 50 個以上溜まっていたらエラー
OkComputer::Registry.register 'job_queue', OkComputer::DelayedJobBackedUpCheck.new(0, 50)
# Ruby バージョンの表示
OkComputer::Registry.register 'ruby_version', OkComputer::RubyVersionCheck.new

この状態で /health/all にアクセスすると、以下のようなレスポンスを返します。[1]

Default Collection
  action_mailer: PASSED ActionMailer::Base check to xxxx:1025 successful (0.000s)
  cache: PASSED Able to read and write via Null store (0.000s)
  database: PASSED Schema version: xxxx (0.002s)
  database_migration: PASSED NO pending migrations (0.003s)
  default: PASSED Application is running (0.000s)
  job_queue: PASSED Delayed Jobs with priority lower than '0' at reasonable level (0) (0.003s)
  ruby_version: PASSED Ruby 3.2.2-p53 (0.000s)

ActionMailer が SMTP サーバーに接続できるかや DelayedJob のジョブ数など、各種サービスをチェックした上で全て PASSED になっているのが確認できますね。

あとは APM から /health/all のステータスチェックを定期的に行い、エラーになった場合はアラートを上げるようにすれば安心です。

利用できるチェック項目について

設定できるチェック用クラスは okcomputer/lib/ok_computer/built_in_checks/ から確認できる他、カスタムチェッククラスの実装も可能です。

個人的には DelayedJob のジョブ数チェックが便利だと感じます。この監視をどこでやるかが結構悩ましかったのですが、 Deep Health Check に組み込んでしまうことでヘルスチェックアラートに一元化できました[2]

まとめ

OK Computer gem での Deep Health Check については他の方の記事も大いに参考にさせていただきました。

https://qiita.com/dany1468/items/3b2f9c38d859d0fcd9b2

https://madogiwa0124.hatenablog.com/entry/2021/05/09/161417

Zenn ではまだ OK Computer gem に関する記事がなさそうだったことと、 DelayedJobBackedUpCheck を使った例があまりなさそうだったため、そのあたりでこの記事が誰かの役に立てば幸いです。

脚注
  1. ローカル環境で実行したためキャッシュは Null store になっています。また一部情報は xxxx でマスクしています。 ↩︎

  2. ジョブ数チェックを入れると Web サービス自体は問題なく動作する状態でもチェックに引っかかる可能性があり、ロードバランサーからのヘルスチェックなどでは適さなくなります。今回はサービス全体の健全性を APM から監視したかったため導入しました。 ↩︎

リーナーテックブログ

Discussion