动态覆盖Rails中所有Logger输出的目标文件

时间:2018-10-12 13:51:15

标签: ruby-on-rails apartment-gem

我正在将Apartment gem用于多租户Rails 5.2应用程序。我不确定这对我的问题是否重要,只是给出一些背景信息即可。

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

思考...我有什么方法可以在Logger中进行猴子补丁修改,以动态更改写入的文件?

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

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

愚蠢的例子...但是我想在写任何日志行之前进行这种动态控制。

谢谢!

1 个答案:

答案 0 :(得分:1)

通常情况下,记录器通常是按服务器(或实际上是每个环境)配置的,而公寓则根据请求设置租户-这意味着在实践中,记录器实际上不能很好地工作。

您可以随时通过将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中并认为所有内容都是笨拙的-它将被称为延迟方式,并且大多数条目都带有重要内容,例如请求或在控制器之前弹出的所有错误将最终显示在默认日志中。

您可以做的是编写here的自定义片段,以切换日志:

# 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指南建议的带标签的记录器使用单个文件是更好的解决方案。