Michael Graff
Michael Graff

Reputation: 485

Access to Rails request inside ActiveSupport::LogSubscriber subclass

I am trying to make a bit of a custom Rails logger which ultimately will log to a database. However, I don't have access to things like the request object, which I very much would like to have.

I'm currently trying to use the LogSubscriber (notification) interface to do the bulk of this; perhaps this is not the right approach. I do know I could abuse Thread.current[] but I was hoping to avoid doing that.

Here's the code I have which is as basic as I can get it for an example. This is loaded in an initializer.

module RequestLogging
  class LogSubscriber < ActiveSupport::LogSubscriber
    def process_action(event)
      pp request # <--- does not work
      pp event
    end
end

RequestLogging::LogSubscriber.attach_to :action_controller

Upvotes: 4

Views: 2315

Answers (2)

Shubham kumar
Shubham kumar

Reputation: 812

you can get the even.payload then pass it your own CustomLogger(formatted_log(even.payload) and then there you can define a module and save it. You may want to customise your formatted_log function to beautify the payload accordingly.

def process_action(event)
  CustomLogger.application(formattedLog(event.payload))
end

def formattedLog(payload)
 # some restructuring of data.
end

Upvotes: 0

Roman Trofimov
Roman Trofimov

Reputation: 109

Probably you need to override process_action in ActionController::Instrumentation and then request object will be accessible like event.payload[:request]. I think you can put code somewhere in config/initializers, code example:

ActionController::Instrumentation.class_eval do
  def process_action(*args)
    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:    request,
      session:    session
    }

    ActiveSupport::Notifications.instrument("start_processing.action_controller", raw_payload.dup)

    ActiveSupport::Notifications.instrument("process_action.action_controller", raw_payload) do |payload|
      result = super
      payload[:status] = response.status
      append_info_to_payload(payload)
      result
    end
  end
end

Upvotes: 4

Related Questions