Динамически переопределить файл назначения всех выходных данных Logger в Rails

Я использую жемчужину квартиры для мультитенантного приложения Rails 5.2. Я не уверен, что это даже имеет значение для моего вопроса, но просто дает некоторый контекст.

Есть ли способ переопределить регистратор Rails и перенаправить каждую отдельную запись журнала в файл, основанный на используемом клиенте (базе данных)?

Думая... есть ли способ, который я могу monkeypatch в Logger, который изменит файл, записанный в динамически?

Пример: я хочу, чтобы каждое сообщение об ошибке было направлено в файл за этот день. Таким образом, в конце недели будет 7 динамически генерируемых файлов для ошибок, которые возникали в каждый конкретный день.

Другой пример: перед тем, как написать какое-либо сообщение журнала сервера, проверьте, не было ли оно до 13:00. Если это до 13:00, напишите это в /log/before_1.log ... если это после 13:00, напишите это в /log/after_1.log

Глупые примеры... но я хочу такой динамический контроль, прежде чем писать какую-либо строку журнала.

Спасибо!

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 и подумайте, что все очень просто - это будет называться слишком поздно, и большинство записей с важными вещами, такими как запрос или любые ошибки, которые всплывают до того, как контроллер попадет в журнал по умолчанию.

То, что вы могли бы сделать, это написать специальную часть промежуточного программного обеспечения, которая отключает журнал:

# 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 с одним файлом - гораздо лучшее решение.

Другие вопросы по тегам