In a new Rails 7.1.2 app, the following lines can be found in config/environments/production.rb
:
config.logger = ActiveSupport::Logger.new(STDOUT)
.tap { |logger| logger.formatter = ::Logger::Formatter.new }
.then { |logger| ActiveSupport::TaggedLogging.new(logger) }
This tells the Rails logger to log to STDOUT
.
I would like to configure it so that it ALSO logs to log/production.log
, but I can't for the life of me figure it out...
In this article by Fly.io it says to add these lines:
logger = ActiveSupport::Logger.new(STDOUT)
logger.formatter = config.log_formatter
volume_logger = ActiveSupport::Logger.new("/logs/production.log", 3)
logger = logger.extend ActiveSupport::Logger.broadcast(volume_logger)
But it seems like these instructions are for Rails < 7.1, since I get the error NoMethodError: undefined method
broadcast' for ActiveSupport::Logger:Class`.
How can I do this in Rails 7.1?
Rails v7.1
added new BroadcastLogger
class to handle broadcasting:
stdout_logger = ActiveSupport::Logger.new(STDOUT)
stdout_logger.formatter = ::Logger::Formatter.new
file_logger = ActiveSupport::Logger.new("log/production.log")
file_logger.formatter = ::Logger::Formatter.new
tagged_stdout_logger = ActiveSupport::TaggedLogging.new(stdout_logger)
tagged_file_logger = ActiveSupport::TaggedLogging.new(file_logger)
broadcast_logger = ActiveSupport::BroadcastLogger.new(tagged_stdout_logger, tagged_file_logger)
config.logger = broadcast_logger
https://api.rubyonrails.org/classes/ActiveSupport/BroadcastLogger.html
Since rails v7.1
you could pass formatter
to new
, which makes the setup much cleaner: https://github.com/rails/rails/commit/3b012a52540f7e4564d70f1955785bde32269a3d:
config.logger = ActiveSupport::BroadcastLogger.new(
ActiveSupport::TaggedLogging.new(ActiveSupport::Logger.new($stdout, formatter: Logger::Formatter.new)),
ActiveSupport::TaggedLogging.new(ActiveSupport::Logger.new("log/production.log", formatter: Logger::Formatter.new))
)