ruby-on-rails - 为 Rails 4 中的特定 Controller 重定向记录器输出

标签 ruby-on-rails ruby-on-rails-4 logging rack

我根据上一个问题 Redirect logger output for a specific controller in 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.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)返回零。

检查 Rails 4 控制台,我确实看到 Rails.instance_variable_get(:@logger)返回 #<ActiveSupport::Logger:0x007f84ff503a08 ....>
我试过用 Rails.instance_variable_get(:@logger) 替换 setter/getter 和 Rails.instance_variable_set(:@logger,my_logger) 的二传手它几乎似乎工作。事件的第一部分,“Started...”转到新的日志文件,但之后的所有内容都转到默认日志文件(中间件更改之前的 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

这确实是一个hack-ish解决方案,并根据您的需要修改正则表达式。

如果这对你不起作用,请告诉我。

关于ruby-on-rails - 为 Rails 4 中的特定 Controller 重定向记录器输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34936358/

相关文章:

ruby-on-rails - 从 rails 调用 javascript 函数

ruby-on-rails - 如何有条件地将类添加到 Rails 布局中的 <body>

java - PatternLayout (log4j) 的 C、F、L、l 和 M 到底有多慢?

ruby-on-rails - 在 Rails 4 中禁用 HTML 以外的其他格式?

ruby-on-rails - session 在 OmniAuth 和 Rails 4 重定向中不持久

android - 记录最佳实践和想法

jsf - AbortProcessingException 在服务器日志中留下堆栈跟踪,如何禁用它?

ruby-on-rails - 设计登录错误不返回 JSON

ruby-on-rails - 如何设置 Sunspot 以搜索字符序列而不是单词?

java - Hadoop在项目中的实际使用