代码之家  ›  专栏  ›  技术社区  ›  slindsey3000

动态覆盖Rails中所有记录器输出的目标文件

  •  0
  • slindsey3000  · 技术社区  · 7 年前

    我正在使用公寓宝石多租户Rails 5.2应用程序。我不确定这对我的问题是否重要,只是提供一些背景。

    有没有一种方法可以覆盖Rails日志记录器并将每个日志条目重定向到一个基于正在使用的租户(数据库)的文件?

    思考…Logger中是否有一个方法可以更改动态写入的文件?

    示例:我希望当天的每个错误消息都指向一个文件。因此,在一周结束时,将有7个动态生成的文件用于处理每个特定日期发生的错误。

    另一个例子:在编写任何服务器日志消息之前,请检查它是否在下午1点之前。如果它在下午1点之前,写在/log/之前。如果是在下午1点之后,写到/log/在1.log之后。

    愚蠢的例子…但我希望在写任何一行日志之前都能进行这种动态控制。

    谢谢您!

    1 回复  |  直到 7 年前
        1
  •  1
  •   max Mike Williams    7 年前

    通常情况下,日志记录器通常是按服务器(或按实际环境)配置的,而公寓则按请求设置租户——这意味着实际上,它并不能很好地工作。

    您可以通过分配 Rails.logger 到记录器实例。

    Rails.logger = Logger.new(Rails.root.join('log/foo.log'), File::APPEND)
    
    # or for multiple loggers
    Rails.logger.extend(Logger.new(Rails.root.join('log/foo.log'), File::APPEND))
    

    但这并不简单-你不能把它扔到 ApplicationController 并且认为一切都是美好的多利-它将被称为方式晚,大多数条目与重要的东西,如请求或任何错误弹出之前,控制器将结束在默认日志。

    你能做的就是写一篇 middleware 切换日志:

    # app/middleware/tenant_logger.rb
    class TenantLogger
      def initialize app
        @app = app
      end
    
      def call(env)
        file_name = "#{Appartment::Tenant.current}.log"
        Rails.logger = Logger.new(Rails.root.join('log', file_name), File::APPEND)
        @app.call(env)
      end
    end
    

    安装在中间件堆栈中的“电梯”之后:

    Rails.application.config.middleware.insert_after Apartment::Elevators::Subdomain, TenantLogger
    

    但是,由于这在中间件堆栈中非常低,您仍然会错过大量由中间件记录的重要信息,例如 Rails::Rack::Logger .

    按照Rails指南的建议,使用带有标签的记录器和单个文件是一个更好的解决方案。