Replacing Rails Logger with Lograge
Among the biggest problems of the default Rails logger are that it's:
- too verbose
- not parsable
which makes it a bad fit for production.
Let's add a Lograge to fight those issues:
gem "lograge"
The configuration below is the one I use in my current project, config/initializers/lograge.rb
:
# frozen_string_literal: true
Rails.application.configure do
config.lograge.enabled = true
config.lograge.keep_original_rails_log = true
config.lograge.formatter = Lograge::Formatters::Json.new
config.lograge.logger = ActiveSupport::Logger.new(STDOUT)
config.lograge.ignore_actions = [
'ActiveStorage::DiskController#show',
'ActiveStorage::BlobsController#show',
'ActiveStorage::RepresentationsController#show'
]
end
Additionaly I silenced the Active Record queries spam, by setting config/environments/production.rb
config.active_record.logger = nil
It works great, but does not allow to use the default Rails.logger.*severity*
logger anymore. So I created a custom events logger lib/log.rb
:
# frozen_string_literal: true
# Adds logger Log.*level* methods
module Log
extend self
%i[debug info warn error fatal unknown].each do |severity|
define_method severity do |message, params = {}|
raise ArgumentError, "Hash is expected as 'params'" unless params.is_a?(Hash)
logger.public_send(severity, {
m: message
}.merge(params).to_json)
end
end
private
def logger
Lograge.logger
end
end
Now it's possible to logs events like this:
Log.info "SMS received", from: from, body: body, message_id: message_id
And get a neat parsable output:
{"method":"GET","path":"/","format":"html","controller":"HomeController","action":"index","status":200,"duration":28.47,"view":25.91,"db":0.0}
{"m":"SMS received","from":"+XXXXXXXXXX","body":"Your verification code is: 5752","message_id":19932478}
...