nginx + rails環境でのヘルスチェックログ(一部のアクセスログ)出力抑止
nginxの方は慣れていることもあって簡単に設定できたのですが、rails側がちょっと面倒だったのでメモを残しておきます。
構成例は、nginxのコンテナ名(ノード名)がweb、railsのコンテナ名がappで、ヘルスチェックURLは/healthとして準備しています。
rails側の死活監視もしたかったため、/healthもrailsコンテナ側に回し単純にokというviewだけを返すような実装にしました。
nginxの一部アクセスログ出力抑止
まずはnginx側から。
confのserverディレクティブに以下のように記述します。
location ~ /health { access_log off; proxy_pass http://app:3000; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header Host $host; }
ちなみに、親にあたるディレクティブ(server)では、以下のようにしています
この例では、AWSのCloudWatchログで拾いたかったため、ログファイルに出力ではなくコンソールに出力しています。
access_log /dev/stdout main; error_log /dev/stderr warn;
rails環境での一部のアクセスログ出力抑止
rails側は面倒でした。
ログ出力自体をgemを使って制御するという方法もあるようですが、今回はそのようなgemは導入していません。
というかrails側の対応をすっかり忘れていたために、CloudWatchログがこんな状態に…
ステージング環境であり他のトラフィックが少なくヘルスチェック間隔がゆるやかなので良いのですが、本番化の際には抑止しておかないと大変なことになりそうです。
ということで、 hello-world.jp.netさん の記事 ELBのヘルスチェックをアプリケーションログに残さないようにする を参考に設定していきます。
- CustomLoggerクラス追加
- オートロード設定
- config/intializersにCustomLogger設定追加
ということで、まさに参考記事に書かれているとおりなのですが設定していきます。
CustomLoggerクラス追加
lib/autoloadディレクトリを作り、custom_logger.rbを作成します。
class CustomLogger < Rails::Rack::Logger def call(env) if ['/health'].include?(env['PATH_INFO']) Rails.logger.silence do super end else super end end end
オートロード設定
作成したlib/autoloadディレクトリ内のものは全部オートロードしてしまおうという設定です。
class Application < Rails::Application
内に記述します
config.autoload_paths += %W(#{config.root}/lib/autoload)
config/intializersにCustomLogger設定追加
intializersに設定を追加します。
MyAppの部分は、config/application.rbでmodule Myappのように定義されていると思いますので、その部分のモジュール名を使います。
require "custom_logger" Myapp::Application.config.middleware.swap Rails::Rack::Logger, CustomLogger
ここまで設定できたら、railsを再起動して完了です。
ただし、たぶんrails側は/healthでエラーが発生してもログが出ません。
単純にokという文字列を返すだけにしたので良いのですが、DBの接続チェック等しているとエラーログだけ欲しいというケースもあるかもしれません。