重定向Rails 4中特定控制器的记录器输出

我已经基于我之前的问题中的答案构建了一个解决方案.Rails 3 for 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.logger的Rails 3 getter = 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)返回#

我尝试用Rails.instance_variable_get(:@logger)和带有Rails.instance_variable_set(:@logger,my_logger)的setter取代getter ,它几乎可以正常工作。 活动的第一部分,“已启动…”转到新的日志文件,但之后的所有内容都转到默认日志文件(中间件更改之前的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中相同的方式处理解决方案。似乎可能有其他方法可以实现您的最终目标。 你有没有考虑过这些方法或gem?

https://github.com/TwP/logging

如何在独立日志文件中记录Rails中的内容?

有时尝试与你已经完成的完全不同的东西可能会有所帮助恕我直言。

这是一个猜测,但这可能是你的getter setter没有按预期工作的原因: https : //github.com/rails/rails/commit/6329d9fa8b2f86a178151be264cccdb805bfaaac

关于Jagjot的解决方案并且需要为每个MVC Action Classes设置基本日志,Rails 4默认单独设置它们,这似乎提供了开箱即用的更多灵活性。 http://guides.rubyonrails.org/configuring.html#initializers

为1控制器使用不同的日志记录类的方法有一个缺点,它不适用于现在流行的线程服务器,不仅仅是使用JRuby,而是MRI也要感谢Heroku

在给出一周思考之后,我到目前为止只有想法是将日志传递给syslog并使用syslog的工具将它们分成单独的文件。

它仍然需要修补Logger以包含允许拆分的字符串(例如将#caller跟踪的格式化内容添加到日志文件中)。

B计划将引入我自己的记录器并简单地记录我在该控制器中需要的内容。 例如,如果这足够的话,您可以轻松地转储params和响应