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

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

问题描述

我们希望有一个控制器集合,将所有操作和下游方法的记录器输出路由到单独的日志文件.这是一个Rails 3项目.在Rails 2中,我们通过重新定义"logger"方法来做到这一点,但是在Rails 3中,记录方式是使用"Rails.logger".我尝试放

We want to have a collection of controllers where we route logger output from all actions and downstream methods to a separate log file. This is a Rails 3 project. In Rails 2 we did this by redefining the "logger" method but in Rails 3, the way to log is using "Rails.logger". I tried putting

Rails::logger = Logger.new(File.join(Rails.root, 'log', "reports_controller.log"), 10, 1000000) 

在控制器顶部,但是仅将特定于在操作中专门使用Rails.logger的特定情况发送到指定的日志文件,控制器的所有默认日志输出仍将路由到主日志文件.

at the top of the controller, but only the specific cases where Rails.logger is used specifically in the action is getting sent to the specified log file, all of the default log output for the controller is still routing to the main log file.

如何将特定控制器的所有日志输出路由到特定日志文件,以包括所有默认控制器输出?

How can we route all log output for a specific controller to a specific log file to include all default controller output?

默认情况下,控制器输出是指以入站请求的开头开头的所有消息

By default controller output, I am referring to all of the messages that start with the very beginning of the inbound request

Started POST "/api/v1/reports.json" for 10.XXX.XX.XX at 2015-03-07 01:30:22 +0000
Processing by Api::V1::ReportsController#create as JSON
  Parameters: {"report"=>{"cloud_file_path"=>"report.zip", "company_id"=>nil, "created_at"=>"2015-03-07T01:30:17Z", "type_id"=>"2", "updated_at"=>"2015-03-07T01:30:17Z", "master"=>"1"}}

以及控制器中的入站请求和出站响应等可能产生的所有日志输出.

and all log output that might follow from the inbound request and outbound response in the controller, etc.

基本上,我希望报告控制器的所有日志记录都在reports_controller.log中,并且我不希望任何向报告控制器发送的消息显示在主日志中(即生产环境中的production.log)

Basically I want all logging for the reports controller to be in the reports_controller.log and I don't want any messages for traffic to the reports controller to show up in the main log (i.e. production.log if in production)

更新:

由于@mudasobwa在回答和聊天方面的帮助,我能够使用他的回答所描述的中间件来解决此问题(尽管我必须将我的insert_before更改为在Rails :: Rack :: Logger之前)

Thanks to @mudasobwa's help with his answer and chat, I was able to solve this using middleware as his answer depicts (although I had to change my insert_before to be before Rails::Rack::Logger)

他为我解决了这个问题的修订答案如下,它存在于config/initializers/logger_middleware.rb

the revised answer from him that solved it for me is below and it lives in config/initializers/logger_middleware.rb

module MyApp
  class LoggerMiddleware

    REPORTS_API_CONTROLLER_PATH = %r|\A/api/v.*/reports/.*|
    REPORTS_API_CONTROLLER_LOGFILE = "reports_controller.log"

    def initialize(app)
      @app, @logger = app, 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

推荐答案

并非所有内容都由 controller filter 重定向的原因是这些开始..."等由机架中间件,它在实例化控制器之前 被执行.

The reason that not all the stuff is redirected by controller filter, is that these "Started..." etc are written by rack middleware, that is executed before the controller was even instantiated.

因此,要抓取并重定向与某种情况相关的一切,应该进行更深层次的干预.以下是一个有关[如何可能侵入]管道的示例(可能是不完整的).

So, to grab and redirect everything related to some condition, one should interfere deeper. Below is a [possibly incomplete] example on how to hack into the pipeline.

定义中间件以切换记录器

module MyApp
  class MyMiddleware

    def initialize(app)
      @app, @logger = app, Rails.logger
                                .instance_variable_get(:@logger)
                                .instance_variable_get(:@log)
      @my_logger = Logger.new('reports_controller.log', ...)
    end

    def call(env)
      # env['action_dispatch.logger'].inspect
      #⇒ <TaggedLogging... @logger=#<BufferedLogger...> @log_dest=...>

      # here we do not have a controller name
      Rails.logger
           .instance_variable_get(:@logger)
           .instance_variable_set(:@log,
               case env['PATH_INFO'] # or PATH_INFO, or whatever
               when %r|\A/api/v1/| then @my_logger
               else @logger
               end
           )

      @app.call(env)
    end
  end
end

config/initializers/my_logger.rb

Add an initializer somewhere in config/initializers/my_logger.rb

Rails.application.middleware.insert_before \
    Rails::Rack::Logger, MyApp::MyMiddleware

请注意,Rails的记录器是嵌套的野兽:

Rails::logger
#⇒ #<ActiveSupport::TaggedLogging:0x000000020f5ad0 @logger=...
Rails::logger.instance_variable_get(:@logger)
#⇒ #<ActiveSupport::BufferedLogger:0x000000020f6188 @log_dest=...
Rails::logger.instance_variable_get(:@logger)
             .instance_variable_get(:@log)
#⇒ #<Logger:0x000000020f6138 @progname=nil, @level=0, @default_formatter=...

可能要设置一个特定的格式化程序,或者甚至在其中使用正则表达式的过滤器消息(尽管不应该将其视为一种好习惯.)

One might want to set a specific formatter on the logger, or even filter messages using regular expression there (though it should not be considered a good practice.)

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

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