Ruby on RailsのロガーをRuby標準の Logger
クラスから、 ActiveSupport::Logger
に変更すると形式が変わってしまったので、原因と対処方法を調査しました。
I, [2021-09-23T21:56:45.043019 #1103] INFO -- : Started GET "/" for XXX.XXX.XXX.XXX at 2021-09-23 21:57:22 +0900
I, [2021-09-23T21:56:45.043019 #1103] INFO -- : Processing by ExampleController#show as HTML
I, [2021-09-23T21:56:45.043019 #1103] INFO -- : Parameters: {"id"=>"1234"}
I, [2021-09-23T21:56:45.043019 #1103] INFO -- : Completed 200 OK in 341ms (Views: 152.1ms | ActiveRecord: 123.6ms)
I, [2021-09-23T21:56:45.043019 #1103] INFO -- : Started GET "/" for XXX.XXX.XXX.XXX at 2021-09-23 21:57:22 +0900
Started GET "/" for XXX.XXX.XXX.XXX at 2021-09-23 21:57:22 +0900
Processing by ExampleController#show as HTML
Parameters: {"id"=>"1234"}
Completed 200 OK in 341ms (Views: 152.1ms | ActiveRecord: 123.6ms)
先頭についていた I, [2021-09-23T21:56:45.043019 #1103] INFO -- :
のような表記がなくなってしまっています。
config/application.rb
(もしくは config/environments/{環境名}.rb
)で以下のように設定する。
- config.logger = ActiveSupport::Logger.new('log/application.log')
+ logger = ActiveSupport::Logger.new('log/application.log')
+ logger.formatter = ::Logger::Formatter.new
+ config.logger = logger
Rubyの Logger
クラスでは、ログのフォーマットは format_message
メソッドにて行われる。
https://github.com/ruby/ruby/blob/v2_2_3/lib/logger.rb#L490-L492
def format_message(severity, datetime, progname, msg)
(@formatter || @default_formatter).call(severity, datetime, progname, msg)
end
実際のログのフォーマットは @formatter
にセットされているフォーマッタクラスによって行われる。
Logger
クラスのインスタンスの formatter
をセットしない場合、デフォルトでは同じファイルで定義されている Formatter
クラスが利用される。
https://github.com/ruby/ruby/blob/v2_2_3/lib/logger.rb#L314
@default_formatter = Formatter.new
@formatter = nil
Rubyの Logger
クラスを継承した ActiveSupport::Logger
クラスでは、 formatter
の値を上書きして SimpleFormatter
クラスにしている。
https://github.com/rails/rails/blob/v4.2.4/activesupport/lib/active_support/logger.rb#L46
def initialize(*args)
super
@formatter = SimpleFormatter.new
end
SimpleFormatter
クラスは以下のような実装となっている。
https://github.com/rails/rails/blob/v4.2.4/activesupport/lib/active_support/logger.rb#L50-L55
class SimpleFormatter < ::Logger::Formatter
# This method is invoked when a log event occurs
def call(severity, timestamp, progname, msg)
"#{String === msg ? msg : msg.inspect}\n"
end
end
config/application.rb
で config.logger
に Logger
クラスを設定するとフォーマッタにはRubyの Formatter
クラスが利用され、 ActiveSupport::Logger
クラスを設定するとフォーマッタにはRailsの SimpleFormatter
クラスが利用される。logger.formatter
に任意のフォーマッタクラスをセットすることでログを好きなフォーマットに変更することができる。logger = ActiveSupport::Logger.new('log/application.log')
logger.formatter = ::Logger::Formatter.new
config.logger = ActiveSupport::TaggedLogging.new(logger)
config.log_formatter
の値が Logger
クラスの formatter
にセットされるのは、 config.logger
が未設定の場合のみ。
https://github.com/rails/rails/blob/v4.2.4/railties/lib/rails/application/bootstrap.rb#L33-L56
logger = ActiveSupport::Logger.new f
logger.formatter = config.log_formatter
logger = ActiveSupport::TaggedLogging.new(logger)
logger
よって、 config.log_formatter = ::Logger::Formatter.new
としたとしても、 config.logger = ActiveSupport::Logger.new('log/application.log')
としていると意味がなくなってしまう。
そのため、 config.log_formatter
を使わずに以下のように設定する。
logger = ActiveSupport::Logger.new('log/application.log')
logger.formatter = ::Logger::Formatter.new
config.logger = logger
RailsアプリでELBからのヘルスチェックのアクセスをログに残さないようにする は ActiveSupport::Logger
を継承したクラスを利用していないと行えなかったのでロガークラスを変更したところ、ログの形式が変わってしまったために本対応を行いました。
config.log_formatter
を変更しても適用されずしばらくハマりました。今回RailsやRubyのソースコードをじっくり追いながら実装を把握することができて明確になりました。フルタイムで働いていた頃は何かと忙しくてついこういった細部は「動けばいいや」でやってしまっていたことも多かったですが、しっかり調べることで足元を掬われにくくなるのでやはり急がば回れできちんと調べることが重要だと思いました。
log_formatter
オプションの挙動が説明されていました。