質問
Rails 3.2.11 で,リクエストの様々な情報をログに残したいと思っています.
特に下の2つですが,ActiveSupport::LogSubscriber
を利用しつつrequest
やsession
オブジェクトにアクセスしログに残す方法はありますか?
request.remote_ip
session[:user_id]
Rails.logger
をカスタマイズし 出力を加工することはできるのですが,request
やsession
オブジェクトにアクセスする方法がわかりません.
背景
ログ用に lograge というgem を使っているため,ActiveSupport::LogSubscriber
の拡張とActiveSupport::Notifications::Event
を使って実装できるとうれしいです.
参考
標準のActiveSupport::Notifications::Event の中身
以下のように,event.payload
にはrequest
オブジェクトの一部がString
として格納されています.
このままではsession
やrequest
にアクセスできなさそうです.
From: /path/to/myapp/config/application.rb @ line 65 :
60: # Version of your assets, change this if you want to expire all your assets
61: config.assets.version = '1.0'
62:
63: # Enable lograge
64: config.lograge.enabled = true
=> 65: config.lograge.custom_options = ->(event){ binding.pry }
66: end
67: end
[1] pry(Myapp::Application)> event
=> #<ActiveSupport::Notifications::Event:0x00000005b05810
@duration=1003.062372,
@end=2013-05-13 14:12:15 +0900,
@name="process_action.action_controller",
@payload=
{:controller=>"SomethingsController",
:action=>"index",
:params=>{"action"=>"index", "controller"=>"somethings"},
:format=>:html,
:method=>"GET",
:path=>"/somethings",
:status=>200,
:view_runtime=>714.8272919999999,
:db_runtime=>0},
@time=2013-05-13 14:12:14 +0900,
@transaction_id="1ce1d9096062737f43e4">
ActionController::Base 拡張による実装
https://github.com/roidrage/lograge/issues/10 のようにActionController::Base 内でpayload に新たな文字列をセットすれば実現できそうですが,これが良いアプローチかどうか自信がありません.
追記
# config/application.rb
config.log_tags = [:remote_ip]
により,request.remote_ip
をログに含めることができました.
次に,request.session[:user_id]
にアクセスするための方法を調べたので 追記します.
結果的には http://stackoverflow.com/questions/10811393/how-to-log-user-name-in-rails を参考にし,Rails::Rack::Logger
middleware の評価を後ろに回せば 動きました.
標準では次のようになっているmiddleware 群が
Rails.configuration.middleware.instance_variable_get(:@middlewares)
=> [ActionDispatch::Static,
Rack::Lock,
#<ActiveSupport::Cache::Strategy::LocalCache::Middleware:0x00000003e3be50>,
Rack::Runtime,
Rack::MethodOverride,
ActionDispatch::RequestId,
Rails::Rack::Logger,
ActionDispatch::ShowExceptions,
ActionDispatch::DebugExceptions,
ActionDispatch::RemoteIp,
ActionDispatch::Reloader,
ActionDispatch::Callbacks,
ActiveRecord::ConnectionAdapters::ConnectionManagement,
ActiveRecord::QueryCache,
ActionDispatch::Cookies,
ActionDispatch::Session::CookieStore,
ActionDispatch::Flash,
ActionDispatch::ParamsParser,
ActionDispatch::Head,
Rack::ConditionalGet,
Rack::ETag,
ActionDispatch::BestStandardsSupport]
次のような順序に変わります.
Rails.configuration.middleware.instance_variable_get(:@middlewares)
=> [ActionDispatch::Static,
Rack::Lock,
#<ActiveSupport::Cache::Strategy::LocalCache::Middleware:0x0000000434fd10>,
Rack::Runtime,
Rack::MethodOverride,
ActionDispatch::RequestId,
ActionDispatch::RemoteIp,
ActionDispatch::Cookies,
ActionDispatch::Session::CookieStore,
Rails::Rack::Logger,
ActionDispatch::ShowExceptions,
ActionDispatch::DebugExceptions,
ActionDispatch::Reloader,
ActionDispatch::Callbacks,
ActiveRecord::ConnectionAdapters::ConnectionManagement,
ActiveRecord::QueryCache,
ActionDispatch::Flash,
ActionDispatch::ParamsParser,
ActionDispatch::Head,
Rack::ConditionalGet,
Rack::ETag,
ActionDispatch::BestStandardsSupport]
これでrequest.session
にもアクセスできそうです.最終的には次のような設定になっています.
このソリューションの良し悪しはよく分かりませんが...動いているようには見えます.
# config/application.rb
config.middleware.delete ActionDispatch::RemoteIp
config.middleware.delete ActionDispatch::Cookies
config.middleware.delete ActionDispatch::Session::CookieStore
config.middleware.insert_before Rails::Rack::Logger, ActionDispatch::RemoteIp config.middleware.insert_before Rails::Rack::Logger, ActionDispatch::Cookies
config.middleware.insert_before Rails::Rack::Logger, ActionDispatch::Session::CookieStore
config.log_tags = [:remote_ip, ->(request){ request.session[:user_id] }]