Rails でログの出力やその出力方法、ファイルサイズの肥大化を防ぐログローテートの設定など、ログに関する事柄をメモしておく。
Rails でログを出力する
Rails では logger を利用することでログを出力することができる。ログには五種類あり、以下のような感じで使い分けられている。
debug | デバッグ用情報 |
---|---|
info | 通常の動作の情報 |
warn | エラーとまでは行かないレベルの問題 |
error | 何等かの処理に失敗したときなどに出すエラー |
fatal | 致命的なエラーや予期せぬエラー |
unknown | ログレベル不明のエラー |
それぞれ logger.info 'hogehoge' のように記述する。
logger.debug 'this is debug'
logger.info 'this is info'
logger.warn 'this is warn'
logger.error 'this is error'
logger.fatal 'this is fatal'
logger.unknown 'this is unknown'
これを実行すると以下のような出力となる。
$ tail log/production.log
D, [2019-10-04T13:58:38.716138 #3624] DEBUG -- : this is debug
I, [2019-10-04T13:58:38.716002 #3624] INFO -- : this is info
W, [2019-10-04T13:58:38.716181 #3624] WARN -- : this is warn
E, [2019-10-04T13:58:38.716213 #3624] ERROR -- : this is error
F, [2019-10-04T13:58:38.716242 #3624] FATAL -- : this is fatal
F, [2019-10-04T13:58:38.716274 #3624] ANY -- : this is unknown
logger.debug などを実行する際に "NameError: undefined local variable or method `logger' for main:Object" というエラーが発生する場合には、以下のように Rails を頭につける。
Rails.logger.debug 'this is debug'
Rails.logger.info 'this is info'
Rails.logger.warn 'this is warn'
Rails.logger.error 'this is error'
Rails.logger.fatal 'this is fatal'
Rails.logger.unknown 'this is unknown'
Rails ログの設定
ログの出力の設定は config/environments/*.rb で行う。
ログを標準出力に出す
開発中なんかだと標準出力に出したいかもしれない。その場合には以下のように Logger.new に STDOUT を渡す。
config.logger = Logger.new STDOUT
production.rb にはデフォルトで以下のようなコードがあり、RAILS_LOG_TO_STDOUT 環境変数を指定して実行すればログが標準出力に出される。
if ENV["RAILS_LOG_TO_STDOUT"].present?
logger = ActiveSupport::Logger.new(STDOUT)
logger.formatter = config.log_formatter
config.logger = ActiveSupport::TaggedLogging.new(logger)
end
実行してみると以下のような感じ。
$ RAILS_LOG_TO_STDOUT=true RAILS_ENV=production rake test:logtest
D, [2019-10-04T15:06:17.033721 #4298] DEBUG -- : this is debug
I, [2019-10-04T15:06:17.033803 #4298] INFO -- : this is info
W, [2019-10-04T15:06:17.033826 #4298] WARN -- : this is warn
E, [2019-10-04T15:06:17.033846 #4298] ERROR -- : this is error
F, [2019-10-04T15:06:17.033864 #4298] FATAL -- : this is fatal
F, [2019-10-04T15:06:17.033883 #4298] ANY -- : this is unknown
ログレベルの設定方法
出力するログレベルを変更したい場合には config.log_level を指定する。
config.log_level = :error
例えば :error と指定すると error と fatal のみ出力し、warn, debug, info は出力されなくなる。
一時的にログレベルを変更したい、という場合には以下のようなコードを記述すると、その部分のみログレベルを変更できる。
Rails.logger.level = Logger::DEBUG
ログの出力フォーマットを変更する
config.log_formatter を利用してログの出力を変更できる。引数は severity, time, program name, message の四つあり、それらを自由に設定できる。
# ::Logger::Formatter.new を渡すとデフォルトのフォーマット
config.log_formatter = ::Logger::Formatter.new
# CSV っぽくするなら , で区切る(このままでまともに使えるとは思わないが例ということで)
config.log_formatter = proc do |severity, datetime, progname, msg|
"#{severity},#{datetime},#{progname},#{msg}\n"
end
ログローテートの設定
何もせずに放置しているとログファイルが肥大化して大変なのでログローテートの設定を行おう。Rails ではログファイルのサイズもしくは日数でのローテートを行うことができる。
日付でのログローテート
Logger.new の第二引数に daily, weekly, monthly の三種類を指定することで一日毎、一週間毎、月毎にログファイルを保存できる。
config.logger = Logger.new("log/production.log", 'daily')
ファイルサイズでのログローテート
ログファイルのサイズでログローテートする場合には、Logger.new の第二引数にログを残す数、第三引数にログの最大サイズを指定する。例えば 10M のファイルを 10 個まで残すのであれば以下のようにする。
config.logger = Logger.new("log/production.log", 10, 10 * 1024 * 1024)
まとめ
とりあえずこのあたりが分かっておけばどうにかなりそう。特にログローテートとログレベルは設定しておかないと production 環境で巨大なログファイルが生成されて面倒くさいことになるのでやっておくべし。