我已经根据我上一个问题中的答案构建了一个解决方案 重定向 Rails 3 中特定控制器的记录器输出 对于 Rails 3。它工作得很好,但是现在我正在尝试将相同的基于中间件的解决方案应用于 Rails 4 项目,但存在一些差异,使相同的解决方案无法正常工作。
Rails 3 解决方案:
module MyApp
class LoggerMiddleware
REPORTS_API_CONTROLLER_PATH = %r|A/api/v.*/reports.*|
REPORTS_API_CONTROLLER_LOGFILE = "reports_controller.log"
def initialize(app)
@app = app
@logger = Rails::logger
.instance_variable_get(:@logger)
.instance_variable_get(:@log)
@reports_api_controller_logger = Logger.new(
Rails.root.join('log', REPORTS_API_CONTROLLER_LOGFILE),
10, 1000000)
end
def call(env)
Rails::logger
.instance_variable_get(:@logger)
.instance_variable_set(:@log,
case env['PATH_INFO']
when REPORTS_API_CONTROLLER_PATH then
@reports_api_controller_logger
else
@logger
end
)
@app.call(env)
end
end
end
Rails.application.middleware.insert_before Rails::Rack::Logger, MyApp::LoggerMiddleware
在上面:
Rails 3 getter for Rails.logger = Rails::logger.instance_variable_get(:@logger).instance_variable_get(:@log)
Rails.logger 的 Rails 3 setter (设置为 @my_logger) = Rails::logger.instance_variable_get(:@logger).instance_variable_set(:@log,@my_logger)
我马上注意到的一件事是,在 Rails 4 中,上述Rails::logger.instance_variable_get(:@logger).instance_variable_get(:@log)
返回 nil。
检查 Rails 4 控制台时,我确实看到Rails.instance_variable_get(:@logger)
返回#<ActiveSupport::Logger:0x007f84ff503a08 ....>
我尝试用Rails.instance_variable_get(:@logger)
替换吸气器,用Rails.instance_variable_set(:@logger,my_logger)
替换二传手,它似乎几乎有效。活动的第一部分,"开始..."转到新的日志文件,但之后的所有内容都将转到默认日志文件(中间件更改之前的 Rails.logger)。
Rails.instance_variable_get(:@logger)
不是 Rails 4 中与 Rails 3 Rails::logger.instance_variable_get(:@logger).instance_variable_get(:@log)
的最低级别等效,用于获取/设置 Rails.logger,要么在我的中间件之后的稍后过程中还有其他东西在我设置它后覆盖它。
有什么线索吗?
更新:
澄清一下,上面发布的解决方案在 Rails 3 中按预期工作。在特殊环境中它可能有也可能没有的任何限制(例如,如果是这种情况,解决方案可能无法在线程服务器环境中工作)在这一点上是可以的,并且此时没有遇到障碍,因此这些相同的限制在 Rails 4 解决方案中也可以这个问题。
在破解了一天的 Rails 代码之后,我想我已经找到了解决您问题的黑客式解决方案。
您需要编辑call
方法和initialize
方法,如下所示:
def initialize(app)
@app = app
@logger = Rails.instance_variable_get(:@logger)
@reports_api_controller_logger = Logger.new(
Rails.root.join('log', REPORTS_API_CONTROLLER_LOGFILE),
10, 1000000)
end
def call(env)
if env['PATH_INFO'] =~ /api/v.*/reports.*/
Rails.instance_variable_set(:@logger, @reports_api_controller_logger)
ActionController::Base.logger = @reports_api_controller_logger
ActiveRecord::Base.logger = @reports_api_controller_logger
ActionView::Base.logger = @reports_api_controller_logger
else
Rails.instance_variable_set(:@logger, @logger)
ActionController::Base.logger = @logger
ActiveRecord::Base.logger = @logger
ActionView::Base.logger = @logger
end
@app.call(env)
end
这确实是一个黑客式的解决方案,并根据您的需要修改正则表达式。
告诉我这是否对你不起作用。
我不确定您是否需要以与在 Rails 3 中相同的方式处理解决方案。 似乎还有其他方法可以实现您的最终目标。 您是否考虑过这些方法或宝石中的任何一种?
https://github.com/TwP/logging
如何在独立的日志文件中记录 Rails 中的某些内容?
恕我直言,有时尝试与您已经做过的事情完全不同的事情可能会有所帮助。
这是一个猜测,但这可能就是为什么你的吸气器设置器没有按预期工作的原因:https://github.com/rails/rails/commit/6329d9fa8b2f86a178151be264cccdb805bfaaac
关于Jagjot的解决方案以及需要为每个MVC操作类设置基本日志,Rails 4默认单独设置这些日志,这似乎提供了开箱即用的更大灵活性。 http://guides.rubyonrails.org/configuring.html#initializers
为 1 个控制器使用不同日志记录类的方法有一个缺点,即它无法在线程服务器上工作,该服务器如今不仅与 JRuby 流行,而且由于 Heroku 的 MRI
也很流行经过一周的思考,到目前为止,我唯一的想法是将日志通过管道传输到 syslog 并使用 syslog 的工具将它们拆分为单独的文件。
它仍然需要修补Logger
以包含允许拆分的字符串(例如将#caller
跟踪的格式化行添加到日志文件)。
B计划是引入我自己的记录器,并简单地在该控制器中记录我需要的内容。例如,如果足够的话,您可以轻松转储参数和响应