ruby-on-rails – 重定向Rails 3中特定控制器的记录器输出

前端之家收集整理的这篇文章主要介绍了ruby-on-rails – 重定向Rails 3中特定控制器的记录器输出前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我们希望有一组控制器,我们将记录器输出从所有操作和下游方法路由到单独的日志文件.这是一个Rails 3项目.在Rails 2中,我们通过重新定义“logger”方法来实现这一点,但在Rails 3中,记录的方式是使用“Rails.logger”.我尝试过
Rails::logger = Logger.new(File.join(Rails.root,'log',"reports_controller.log"),10,1000000)

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

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

默认情况下,控制器输出,我指的是从入站请求的最开始处开始的所有消息

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"}}

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

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

更新:

感谢@ mudasobwa对他的回答和聊天的帮助,我能够使用中间件解决这个问题,因为他的答案描述了(尽管我必须将我的insert_before更改为Rails :: Rack :: Logger之前)

解决了我的修改后的答案如下,它存在于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),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

解决方法

不是所有的东西都被控制器过滤器重定向的原因是这些“Started ……”等是由 rack middleware写的,它是在控制器被实例化之前执行的.

因此,要抓住并重定向与某些条件相关的所有内容,应该更深入地干涉.下面是关于如何入侵管道的[可能不完整]示例.

定义中间件以切换记录器

module MyApp
  class MyMiddleware

    def initialize(app)
      @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中的某处添加初始化程序

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=...

有人可能想在记录器上设置特定的formatter,甚至在那里使用正则表达式过滤消息(尽管它不应被视为一种好的做法.)

猜你在找的Ruby相关文章