重定向Rails 4中特定控制器的记录器输出 [英] Redirect logger output for a specific controller in Rails 4

查看:49
本文介绍了重定向Rails 4中特定控制器的记录器输出的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经基于上一个问题中的答案构建了一个解决方案,为Rails 3中的特定控制器重定向记录器输出 for Rails3.它很好用,但是现在我试图将基于中间件的相同解决方案应用于Rails 4项目,但是有一些差异使相同的解决方案无法正常工作.

I've built a solution based on the answer in my previous question Redirect logger output for a specific controller in Rails 3 for Rails 3. It works great however now I am trying to apply the same middleware based solution to a Rails 4 project but there are some differences keeping the same solution from working.

Rails 3解决方案:

The Rails 3 solution:

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 3 getter for Rails.logger = Rails::logger.instance_variable_get(:@logger).instance_variable_get(:@log)

Rails 3 设置器 for Rails.logger(设置为@my_logger)= Rails::logger.instance_variable_get(:@logger).instance_variable_set(:@log,@my_logger)

Rails 3 setter for Rails.logger (setting to @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.

One thing I've noticed right away is that in Rails 4 the above Rails::logger.instance_variable_get(:@logger).instance_variable_get(:@log) returns nil.

在Rails 4控制台中检查,我确实看到Rails.instance_variable_get(:@logger)返回#<ActiveSupport::Logger:0x007f84ff503a08 ....>

Checking in Rails 4 console, I do see that Rails.instance_variable_get(:@logger) returns #<ActiveSupport::Logger:0x007f84ff503a08 ....>

我尝试用Rails.instance_variable_get(:@logger)替换 getter ,并用Rails.instance_variable_set(:@logger,my_logger)替换setter,这似乎可行.活动的第一部分已开始..."转到新的日志文件,但是此后的所有内容都转到默认的日志文件(中间件更改它之前的Rails.logger).

I've tried replacing the getter with Rails.instance_variable_get(:@logger) and the setter with Rails.instance_variable_set(:@logger,my_logger) and it almost seems to work. The first part of the activity, the "Started..." goes to the new log file but everything after that goes to the default log file (the Rails.logger before the middleware changed it).

对于获取/设置 Rails.logger,Rails.instance_variable_get(:@logger)并不是Rails 4中与Rails 3 Rails::logger.instance_variable_get(:@logger).instance_variable_get(:@log)中最低的等效项,或者在我之后的其他过程中设置后将其覆盖的中间件.

Either Rails.instance_variable_get(:@logger) is not the lowest level equivalent in Rails 4 to the Rails 3 Rails::logger.instance_variable_get(:@logger).instance_variable_get(:@log) for getting/setting the Rails.logger or there is something else later on in the process after my middleware that is overwriting this after I set it.

有任何线索吗?

更新:

为澄清起见,以上发布的解决方案可以在Rails 3中按预期方式工作.在特殊环境中它可能有也可能没有任何限制(例如,在这种情况下,该解决方案可能无法在线程服务器环境中工作)在这一点上并没有遇到障碍,因此在Rails 4解决方案中针对这些问题也可以使用这些相同的限制.

To clarify, the solution posted above works as expected in Rails 3. Any limitations it may or may not have in special environments (such as if the solution may not work in threading server environments if that is the case) are ok at this point and not experienced as obstacles at this time therefore these same limitations are also ok in a Rails 4 solution for this question.

推荐答案

在用Rails代码破解了一天之后,我想我已经找到了解决您问题的 hack-ish 解决方案.

After hacking around the Rails code for a day, I think I have found a hack-ish solution to your problem.

您需要按以下方式编辑call方法和initialize方法:

You need to edit the call method and initialize method as follow:

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 解决方案,并根据您的需要修改正则表达式.

This is really a hack-ish solution and modify the regex according to your needs.

如果这对您不起作用,请告诉我.

Tell me if this doesn't work for you.

这篇关于重定向Rails 4中特定控制器的记录器输出的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆