开发者

Full URLs in Rails logs

Is it possible to get the full URLs in the logs of a Rails application? Currently I'm 开发者_JAVA技巧getting something like:

Started GET "/" for 127.0.0.1 at 2011-08-27 13:13:10 +0200

but I need to get:

Started GET "http://localhost:3000/" for 127.0.0.1 at 2011-08-27 13:13:10 +0200

because this is an app where the domains are important.


The line is coming from the middleware Rails::Rack::Logger, which is in railties. At the simplest, you could just override the method doing the logging, e.g., in an initializer:

class Rails::Rack::Logger < ActiveSupport::LogSubscriber
  protected

  def before_dispatch(env)
    request = ActionDispatch::Request.new(env)
    info "\n\nStarted #{request.request_method} \"#{request.url}\" for #{request.ip} at #{Time.now.to_default_s}"
  end
end

If you'd rather not override the logger, you could always add your own, which you've already created, then delete Rails::Rack::Logger from the stack via:

config.middleware.insert_before(Rails::Rack::Logger, YourLogger)
config.middleware.delete(Rails::Rack::Logger)

If you go this route you might check out the rack logger for its usage of ActionDispatch::Request, and be sure to do the other job it does of flushing the log subscriber cache after dispatch, via ActiveSupport::LogSubscriber.flush_all!


I don't think you can do this without changing Rails itself, which isn't nice, but you can add your own log call:

class ApplicationController < ActionController::Base

  before_filter :log_request

  protected

  def log_request
    logger.info("Started #{request.method} #{request.url}")
  end    

end


As of Rails 3.2.12, instead of monkey-patching before_dispatch or call_app, there is now a method that receives the request and returns the Started GET "/session/new" for 127.0.0.1 at 2012-09-26 14:51:42 -0700 bit.

So you can instead override that method in your own logger or monkey patch just that method.

# or "class Rails::Rack::Logger < ActiveSupport::LogSubscriber" for monkey patch
class URLLogger < Rails::Rack::Logger 

  def started_request_message(request)
    'Started %s "%s%s%s" for %s at %s' % [
      request.request_method,
      request.protocol,
      request.host_with_port,
      request.filtered_path,
      request.ip,
      Time.now.to_default_s ]
  end
end

If you subclass don't forget to modify the middleware chain in config/application.rb (and make sure URLLogger is loaded before the configuration block):

config.middleware.insert_before(Rails::Rack::Logger, URLLogger)
config.middleware.delete(Rails::Rack::Logger)


A workaround I'm using for now was creating this class:

class HostnameLogger
  def initialize(app)
    @app = app
  end

  def call(env)
    uri = env["REQUEST_URI"]
    if uri.blank? # While testing a Rails app, there's no env["REQUEST_UIR"] defined.
      uri = "http://#{env["HTTP_HOST"]}#{env["PATH_INFO"]}"
    end
    Rails.logger.info "Started #{env["REQUEST_METHOD"]} \"#{uri}\" for #{env["REMOTE_ADDR"]} at #{Time.now}"
    @app.call(env)
  end
end

and then adding it as Rack middleware (in application.rb):

config.middleware.use "HostnameLogger"

so I get:

Started GET "/users/login" for 127.0.0.1 at 2011-08-27 15:33:40 +0200

Started GET "http://localhost:3000/users/login" for 127.0.0.1 at 2011-08-27 15:33:40 +0200


Rails::Rack::Logger.class_eval do
  protected
  def started_request_message(request)
    "Started #{request.request_method} \"#{request.url}\" for #{request.ip} at #{Time.now.to_default_s}"
  end
end
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜