Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Seeking finer-grained logging options in Rails. How can I log entire requests and/or individual filters to alternative log files?

This is a two part question, but may have the same answer.

Part One: In our app, one particular controller get hit a lot -- so much so that we'd like to it be logged in a file separate from all other requests. Setting the FoosController.logger is not what I'm looking for, because the request exercises some lib files and active record object that have their logger object, and rails will log some info before handing control to the controller in question.

Part Two: We have a global before filter included in our root application_controller.rb that is run before most actions of most controllers. This before_filter is very wordy in the logs, and is a candidate for having all its logging info sent to a separate file. This before filter also calls out to libs and ActiveRecord code with their own refererences to the logger.

One possible solution is to run the single controller as its own standalone application. I haven't tried it yet, because it's pretty tied into the internals of app. This approach also would not help with the before_filter.

Are there any good solutions for more fine-grained logging in rails apps?

Thanks!

like image 753
mshiltonj Avatar asked Nov 04 '22 12:11

mshiltonj


2 Answers

For part I I recommend creating your own logger class (possibly inheriting from the ruby logger (1), have the logger filter out the request url and based on that log to a specific file.

For part II the easiest solution would be to just use a seperate logger for these methods. Instead of logger.debug "your message" you just call method_logger.debug "your message".

Creating your own logger is simple, just use the ruby logger class (1). The following code creates a logger that logs to a my_method.log file in the logs dir of your rails application.

method_logger = Logger.new(Rails.root.join('logs','my_method.log')

You can then write to your log with the following command, which should look familiar to you as rails uses the Ruby logger as well.

method_logger.debug "your debug message here"

(1) http://www.ruby-doc.org/stdlib-1.9.3/libdoc/logger/rdoc/Logger.html

like image 160
NielsV Avatar answered Nov 09 '22 16:11

NielsV


Here's the code for a custom logger that you can use to solve Part I. I adapted it for my own use from another Stack Overflow question, even including the answerer's inline comments. The main difference is that you can specify a different log path for development and production:

# app/concerns/event_notifications_logger.rb
class EventNotificationsLogger < Rails::Rack::Logger
  def initialize(app, opts = {})
    @default_logger = Rails.logger

    @notifications_logger = Logger.new(notifications_log_path)
    @notifications_logger.formatter = LogFormat.new
    @notifications_logger.level = @default_logger.level

    @app = app
    @opts = opts
  end

  def call(env)
    logger = if env['PATH_INFO'] == '/event_notifications/deliver'
      @notifications_logger
    else
      @default_logger
    end

    # What?! Why are these all separate?
    ActiveRecord::Base.logger = logger
    ActionController::Base.logger = logger
    Rails.logger = logger

    # The Rails::Rack::Logger class is responsible for logging the
    # 'starting GET blah blah' log line. We need to call super here (as opposed
    # to @app.call) to make sure that line gets output. However, the
    # ActiveSupport::LogSubscriber class (which Rails::Rack::Logger inherits
    # from) caches the logger, so we have to override that too
    @logger = logger

    super
  end

private

  def notifications_log_path
    Rails.env.production? ?  '/var/log/event-notifications.log' : Rails.root.join('log/event-notifications.log')
  end
end

Then include it in your application configuration:

require File.expand_path('../boot', __FILE__)
require 'rails/all'

require File.expand_path('../../app/concerns/event_notifications_logger', __FILE__)

module YourApp
  class Application < Rails::Application
    config.middleware.swap Rails::Rack::Logger, EventNotificationsLogger
    # ...
  end
end
like image 29
Brandan Avatar answered Nov 09 '22 17:11

Brandan