Динамически переопределить файл назначения всех выходных данных 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 с одним файлом - гораздо лучшее решение.