ruby-on-rails - 动态覆盖 Rails 中所有 Logger 输出的目标文件
问题描述
我正在将 Apartment gem 用于多租户 Rails 5.2 应用程序。我不确定这对我的问题是否重要,但只是给出一些背景信息。
有没有办法覆盖 Rails 记录器并将每个日志条目重定向到基于正在使用的租户(数据库)的文件?
思考...有没有一种方法可以在 Logger 中进行monkeypatch 来动态更改写入的文件?
示例:我希望当天的每条错误消息都指向一个文件。因此,在一周结束时,将有 7 个动态生成的文件用于每个特定日期发生的错误。
另一个例子:在你写任何服务器日志消息之前,检查它是否在下午 1 点之前。如果在下午 1 点之前将其写入 /log/before_1.log ... 如果在下午 1 点之后将其写入 /log/after_1.log
愚蠢的例子......但我想要在写入任何日志行之前进行那种动态控制。
谢谢!
解决方案
通常,记录器通常是为每个服务器(或每个环境)配置的,而公寓为每个请求设置租户——这意味着实际上它并不能很好地工作。
您可以通过分配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
并认为一切都是笨拙的——它会被称为迟到,大多数条目都包含重要的东西,比如请求或在控制器之前弹出的任何错误将在默认日志中结束。
你可以做的是编写一个自定义的中间件来切换日志:
# 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 指南的建议,使用带有单个文件的标记记录器是一个更好的解决方案。
推荐阅读
- c# - 将两个表单中的数据保存到 Winforms 应用程序中的同一个表中
- python - 如何在 pygame 中使用图像进行碰撞检测
- laravel - 雄辩的创建方法在存储数据后返回“id”0
- java - 如何创建一个函数来确定来自 youtube 的当前视频 URL?
- javascript - 如何从使用 nodejs 的直接链接下载文件
- python - 在 Python 3 中从特定端口读取 TCP 数据包
- excel - Validate if sheet exists before deleting
- azure - 部署 azure sql server 时发现 NoRegisteredProvider
- angular - 通过 Twitter、GitHub、Microsoft 的 Angular FirebaseUI 身份验证不工作
- python - 在 Heroku 上部署 Flask 应用程序