28
16

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Rails で利用できる Health Check API 系の Gem である okcomputer について

Last updated at Posted at 2017-06-30

ここでいう Health Check API とは

Pattern: Health Check API - Microservice Architecture

上記は一例ですが、Web アプリケーションが動作をしているかを確認できるエンドポイントを提供することを指しています。

他に呼び方があるかもしれませんが。

Rails で利用できる Gem

調査時に発見できたものです。拾うワードが少なかった印象はあります。他にもありそう。

:star: 数/last_update は 2017/6/30 時点

Gem description :star: last_update
ianheggie/health_check Simple health check of Rails app for use with uptime checking sites like newrelic and pingdom 191 2016/12/7
jbarnette/pinglish A simple Rack middleware for checking application health. 154 2016/11/28
sportngin/okcomputer Provides a health-check endpoint to your Ruby on Rails apps. 137 2017/5/9
lbeder/health-monitor-rails A Rails plugin which provides a health checking and monitoring API of various services and application aspects. 58 2017/6/21
mitaku/komachi_heartbeat Rails アプリケーションとDBサーバーの死活監視するためのURLを提供するEngine 39 2017/5/22
lserman/aws-healthcheck Mounts a 200 response at /healthcheck for AWS load balancers 14 2016/10/31
on-site/server_health_check
on-site/server_health_check-rack
on-site/server_health_check-rails
This gem provides a standard set of health checks for web services 0 2017/5/8

Rack / Rails Mountable Engine などの違いはありつつも、いずれもあるエンドポイント(大抵は変更可能)に対してリクエストをした際に DB 等(大抵は Migration 管理用のテーブル)にアクセスして、動作確認をし、成功すれば 200 を返すという単純なものです。

それぞれで、ビルトインのチェック処理が異なるので、どれぐらいカスタマイズしたいかや、「面倒だからビルトインが多いほうがいい」等で決めれば良いかと思います。

okcomputer について

私のチームでは okcomputer を選定しました。
ianheggie/health_check, lbeder/health-monitor-rails との比較で悩みましたが、ビルトインのチェックの多さと、 :ok: の場合にもメッセージを返却できる点で sportngin/okcomputer を選びました。

他は、Rails5 リリース以降にメンテナンスが行われていない事や、:star: が少なすぎる等で一時除外しました。ただ、komachi_heartbeat だけは、選定が終わってから見つけたのでなんとも言えないです。

使い方

README が丁寧にかかれているので特に迷うことは無いと思います。

最も簡単な例であれば Gemfile に追加しただけで以下にリクエストすればチェックが行われます。

  • /okcomputer
  • /okcomputer/all
  • /okcomputer/default
  • /okcomputer/database
    • database チェックだけ個別に行いたければこちら

/okcomputer 以外は、.json をつければ JSON フォーマットで返されます。

% curl http://localhost:3000/okcomputer/default
default: PASSED Application is running (0s)%

% curl http://localhost:3000/okcomputer/default.json
{"default":{"message":"Application is running","success":true,"time":9.889001375995576e-06}}

見ての通りで成功時でも message を返せるため、単純に boolean の結果としてだけでなく、アプリの内部状態を知るための情報を返させてもいいかもしれません。

okcomputer の Collection 機能を使う

README には記述されていませんが、Collection という機能が存在します。(なくなる予定なのかもしれません)

チェックの登録時に collection 名が渡せる

okcomputer ではチェックの登録に以下のように Registry を使います。

OkComputer::Registry.register "database", OkComputer::ActiveRecordCheck.new

Registry#register は以下のようになっています。

lib/okcomputer/registry.rb
module OkComputer
  class Registry
    # Public: Register the given check with OkComputer
    #
    # check_name - The name of the check to retrieve
    # check_object - Instance of Checker to register
    # collection_name - The name of the check collection the check should be registered to
    def self.register(check_name, check_object, collection_name=nil)
      check_object.registrant_name = check_name
      find_collection(collection_name).register(check_name, check_object)
    end

    private_class_method def self.find_collection(collection_name=nil)
      collection_name ? default_collection.fetch(collection_name) : default_collection
    rescue KeyError
      raise CollectionNotFound
    end

    def self.default_collection
      @default_collection ||= CheckCollection.new('Default Collection')
    end

#registercollection_name という引数があり、それを使って default_collection から fetch をしているように見えます。
そして default_collectionCheckCollection のインスタンスであることがわかります。

続いて、CheckCollection を見ていきます。

lib/okcomputer/check_collection.rb
module OkComputer
  class CheckCollection
    def initialize(display)
      self.display = display
      self.collection = {}
    end

    # Public: Returns a check or collection if it's in the check collection
    #
    # key - a check or collection name
    # throws a KeyError when the key is not found
    def fetch(key, default=nil)
      found_in = self_and_sub_collections.detect{ |c| c[key] }
      raise KeyError unless found_in
      found_in[key]
    end

    def sub_collections
      checks.select{ |c| c.is_a?(CheckCollection)}
    end

    def checks
      collection.values
    end

    def self_and_sub_collections
      [collection] + sub_collections
    end

    def register(name, check)
      collection[name] = check
    end

CheckCollection は内部に collection という Hash を持つだけのようです。 #fetch では、渡されたキーから自身が管理する collection と、自身が管理する collection の中にある sub_collections が管理する collection からも検索を行っているようです。

つまり以下のような構造で collection を管理しているようです。

OkComputer::CheckCollection.new('Default Collection')
@display = 'Default Collection'
@collection = {
  'database' => OkComputer::ActiveRecordCheck.new,
  'sidekiq' => OkComputer::SidekiqCheck.new,
  'sub1' => OkComputer::CheckCollection.new('sub1') # この中でもさらに collection がある
}

再帰的に fetch するわけではなさそうなので、おそらく第一階層の sub 階層までになりそうです。

よって、Registry#register の際に collection_name を渡すと、 Default 以外の collection にチェックを登録することができます。

そして Default 以外の collection は、単に CheckCollectionRegistry#register すれがいいことがわかります。

Collection を追加する

ここまで分かると独自に collection を追加できます。

OkComputer::Registry.register "special_check", OkComputer::CheckCollection.new('Special Check Collection')

collection を追加できれば、この collection にチェックを追加しましょう。

OkComputer::Registry.register "migration", OkComputer::ActiveRecordMigrationsCheck.new, "special_check"

こうすると以下の URL でチェックができます。

% curl http://localhost:3000/okcomputer/special_check
% curl http://localhost:3000/okcomputer/migration

# 以下は駄目
% curl http://localhost:3000/okcomputer/special_check/migration

所属する Collection が異なるので以下のように default で呼び出しても migaration チェックは実行されません。

# 以下の結果に migration の結果は含まれない
% curl http://localhost:3000/okcomputer/default

Collection の用途

okcomputer はもちろん単純な Health Check 用途に使った方がいいですが、Collection を分けておくことで、監視のエンドポイントを分けられたり、メトリクス用にチェックを作る時に、うまくグルーピングができて便利です。

参考

2 年以上前ですが、ドリコムさんは komachi_heartbeat を利用していると書かれています。
Mountable Engine だらけの Rails アプリ開発 - http://blog.onk.ninja/

Gitlab は health_check を使っているようです。
https://gitlab.com/gitlab-org/gitlab-ce/blob/master/Gemfile#L382

28
16
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
28
16

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?