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
精彩评论