How to mark each log call in rails with request id (lograge)

I use lograge with rails and I configured my logs using JSON format. I would like every time I call logger.info , logger.warn , etc., to enable the uuid request. The way rails handle this with labeled logging is lagging behind what I would like, because it does not seem to be able to combine the uuid request with the rest of the JSON payload, instead adding it to a string in a format other than JSON.

For example, if I call logger.info(client: :ig) , I expect the following log output:

 {"request_id": <request uuid>, "client": "ig"} 

But instead, the rails will add a uuid request (when configured through config.log_tags = [:uuid] ) as follows:

 [<request uuid>] {"client": "ig"} 

Does anyone know if there is a way to force the tag behavior to combine with the JSON payload, rather than adding it to a single line? I would like to configure our logs to be forwarded to Splunk using simple JSON formatting and not have to deal with this additional format.

In addition, I configured lograge to include the request_id set in the uuid request in lambda passed to custom_options in config/application.rb . This works, but only when the rails register a request. If I explicitly call one of the logging methods elsewhere, request_id not included.

 # application.rb config.lograge.enabled = true config.lograge.formatter = Lograge::Formatters::Json.new config.lograge.custom_options = lambda do |e| { params: e.payload[:params].except("controller", "action", "utf8"), request_id: e.payload[:request_id] # added this in `append_info_to_payload` in ApplicationController } end 

Then in config / environment / production.rb

 config.log_tags = [ -> (req) { { request_id: req.env["action_dispatch.request_id"] } } ] 

Any help is appreciated, thanks.

+5
source share
2 answers

The problem is that there is no request_id in the payload. As you can see in:

./actionpack-3.2.11/Library/action_controller/metal/instrumentation.rb: 18-25

 raw_payload = { :controller => self.class.name, :action => self.action_name, :params => request.filtered_parameters, :format => request.format.try(:ref), :method => request.method, :path => (request.fullpath rescue "unknown") } 

I override this method (copy ./actionpack-3.2.11/lib/action_controller/metal/instrumentation.rb to config / initializer.rb ) and add your parameter.

 raw_payload = { :controller => self.class.name, :action => self.action_name, :params => request.filtered_parameters, :format => request.format.try(:ref), :method => request.method, :path => (request.fullpath rescue "unknown"), :request_id => env["action_dispatch.request_id"] } 

There may be a better way to redefine instruments, but that’s enough.

+1
source

It is easier to override the initializer with class_eval, as you can see in: Accessing the Rails request in the ActiveSupport :: LogSubscriber subclass

0
source

All Articles