【Ruby on Rails】ログ出力とログローテートの設定まとめ【Logger】

概要

Rails では ActiveSupport::Logger クラスを利用してログ出力ができます。

railsguides.jp

今回、ログの設定変更やログローテート方法、古いログの削除、オススメのプラグインなどをまとめました。

 

ログの設定

基本的には app/config/environments/*.rb を変更します。

環境毎に設定を分けたくない場合は app/config/application.rb に記載しても OK です。

ログレベルの変更

Logger クラスで指定可能なログレベルは全部で 6 つあります。

レベル 概要 説明
debug デバッグ用の情報 システムの動作状況に関する詳細な情報
info 情報 実行時の何らかの注目すべき事象(開始や終了など)
warn 警告 エラーに近い事象など、実行時に生じた異常とは言い切れないが正常とも異なる何らかの予期しない問題
error エラー 予期しないその他の実行時エラー
fatal 致命的なエラー プログラムの異常終了を伴うようなもの
unknown 不明なエラー ログレベルの把握できない原因不明のエラー

参考:log4j - Wikipedia

ログレベルは debug < info < warn < error < fatal < unknown の順に高くなっています。

ログに出力されるメッセージのログレベルが、設定済みのログレベル以上になった場合に、対応するログファイルにそのメッセージが出力されます。

デフォルトログレベルは全環境で debug です。

デフォルトのログレベルを変更するには以下のような設定を追加します。

config.log_level = :ログレベル

ログファイルの変更

デフォルトのログの保存場所は app/log 配下となります。

ログのファイル名には、アプリケーションが実行されるときの環境名が利用されます。

環境 ログファイル PATH
 development  app/log/development.log
 test  app/log/test.log
 production  app/log/production.log

 

デフォルトのログファイルを変更するには以下のような設定を追加します。

config.logger = Logger.new('ログファイル PATH')

ログフォーマットの変更

ログを出力する call メソッドは 4 つの引数 (severity, time, program name, message) を受け取ります。

call メソッドの返り値は文字列にしてください。

参考:class Logger (Ruby 2.4.0)

config.logger.formatter = proc { |severity, datetime, progname, message|
  # ここでログフォーマットを自由にカスタマイズする
  "[#{datetime}] [#{severity}] -- #{message}\n"
}

 

ログ出力

アプリケーション内でログ出力したい場合は、それぞれのログレベルに対応したメソッドを利用します。

設定したログレベル以下のメソッドは、使用しても出力されませんので注意して下さい。

logger.debug('Hello')
logger.info('Hello')
logger.warn('Hello')
logger.error('Hello')
logger.fatal('Hello')
logger.unknown('Hello')

 

ログローテート

アプリケーションログをいつまでも同一のファイルに出力していると、ログファイルが肥大化して、サーバ容量を圧迫してしまいます。

定期的にログローテートして、古いログファイルは削除することをお勧めします。

ログローテートは「日付」か「ファイルサイズ」のどちらかで行うことができます。

日付でログローテート

「日付」でのログローテートは、何か問題が発生した場合に、発生日時からログを検索しやすいのが利点だと思います。

ログローテートは daily、weekly、monthly から選びます。

ただし、1 日 3 回朝昼晩などの設定ができないので、アクセス量の多いアプリケーションには不向きかもしれません。

config.logger = Logger.new('log/trace.log', 'daily')
config.logger = Logger.new('log/trace.log', 'weekly')
config.logger = Logger.new('log/trace.log', 'monthly')

ファイルサイズでログローテート

「ファイルサイズ」でのログローテートは、サーバリソースを上手く使えるのが利点だと思います。

アクセス量が少ないアプリケーションでは、毎日ログローテートする必要も無いですし、逆にアクセス量の多いアプリケーションでは1日に数回ログローテートした方がいい場合があります。

また「ファイルサイズ」でログローテートした場合、一定期間ログファイルを保存して、期間を過ぎた古いログファイルを削除することができます。

以下の設定ではファイルサイズが 10 M となったらログローテートして、14日以上経過した古いログファイルは削除してくれます。

config.logger = Logger.new('log/trace.log', 14, 10 * 1024 * 1024)

これは Logger クラスの第二引数がログファイルを保持する数か、ログファイルを切り替える頻度 (daily, weekly, monthly) となっているためです。

そのため「日付」でログローテートする場合、古いログファイルの削除ができません。

参考:class Logger (Ruby 2.4.0)

 

その他

ログローテートを本格的にやるのであれば、Logger クラスのオプションでは少ないと思うので、logrotate.conf を作成して、定期的にlogrotate コマンドを叩くのがいいとお思います。

これは Ruby on Rails の話ではなくサーバサイドの話になってしまいますが。。

qiita.com 

まとめ

今回の設定を app/config/environments/development.rb に反映させました。

※ ログ出力周りの設定だけを抜粋しています。

Rails.application.configure do
# ログレベルの設定 config.log_level = :info
# ログ出力ファイルの設定、ログローテートの設定 config.logger = Logger.new('/var/log/rails_app.log', 14, 10 * 1024 * 1024)
# ログフォーマットの設定 config.logger.formatter = proc { |severity, datetime, _progname, message| "[#{datetime}] [#{severity}] -- #{message}\n" }
end

ログを確認すると、指定されたログファイルに指定されたフォーマットで出力されるようになりました。

$ tail -f /var/log/rails_app.log
[2017-12-25 14:11:37] [INFO] -- Started GET "/v1/users/9" for 127.0.0.1 at 2017-12-25 14:11:37 +0900
[2017-12-25 14:11:37] [INFO] -- Processing by UsersController#show as */*
[2017-12-25 14:11:37] [INFO] --   Parameters: {"id"=>"9"}
[2017-12-25 14:11:37] [INFO] -- Hello
[2017-12-25 14:11:37] [INFO] -- Completed 200 OK in 24ms (Views: 0.1ms | ActiveRecord: 12.0ms)