Railsで、複数の出力先にlogを出力する

railsアプリケーションで、error以上のレベルのログだけ、2箇所にログを出力したいと思った。

前提

ruby 2.1.2
rails 4.1.4

方法

まず、複数の出力先にロギングするには、ActiveSupport::Logger.#broadcastというメソッドが使える。
config/application.rbのMyapp::Applicationクラス内に下記のように書いてみた。

1
2
3
4
5
logger = ActiveSupport::Logger.new(config.paths["log"].first)
error_logger = ActiveSupport::Logger.new("log/error.log")
error_logger.level = Logger::ERROR
logger.extend ActiveSupport::Logger.broadcast(error_logger)
config.logger = logger

これで、複数箇所にログが出力されるようにはなった。
しかし、今回やりたかったのは、ERROR以上の時だけ2箇所にロギングしたいというもので、上記のようにconfig/application.rbでextendした場合、error_loggerのlevelをERRORにセットしていても、Rails.loggerのlevelと同じlevelでのloggingになってしまう。
全く同じエラーログを複数箇所に吐かせたいというだけであれば、上記の方法で良いと思う。(その際、上記のerror_logger.level = Logger::ERRORは意味が無いので消した方が良い)

error_logger.levelの指定が効くようにするには、run Rails.applicationよりも後で、error_loggerをRails.loggerにextendすると良い。
config.ruに下記を追記する。

1
2
3
4
5
run Rails.application

error_logger = ActiveSupport::Logger.new("log/error.log")
error_logger.level = Logger::ERROR
Rails.logger.extend ActiveSupport::Logger.broadcast(error_logger)

これで、log/error.logへは、ERRORレベル以上のログだけが出力されるようになった。
もちろん、log/development.logには、これまでどおりDEBUGレベルまで含めた全てのlogが出ている。

参考

[Ruby] 例えば、Rails の標準ログを止める - sonots:blog
RailsDoc - ActiveSupport::Logger
【Rails】バッチの実行ログを専用のログファイルと標準出力の両方に出す - おどるダメ人間