#ruby #logging #ruby-on-rails-6 #ruby-2.6
#ruby #ведение журнала #ruby-on-rails-6 #ruby-2.6
Вопрос:
Я пишу реализацию мультилоггера, чтобы позволить моему приложению регистрироваться в нескольких серверных системах. Реализация выглядит следующим образом:
class MultiLogger < Logger
def initialize(loggers = [])
@loggers = []
end
def add(severity, message, _attributes, _environment, progname)
@loggers.each do |logger|
logger.add(severity, message, progname)
end
end
def info(message, attributes, environment, progname)
add(Logger::INFO, message, attributes, environment, progname)
end
...
end
По сути, я только перенаправляю вызовы, выданные MultiLogger#add
всем регистраторам, связанным во время создания экземпляра. Проблема в том, что мне нужно установить этот регистратор в качестве регистратора Rails по умолчанию, но я не могу этого сделать.
Я добавляю config.logger = MultiLogger.new([Logger1.new, Logger2.new])
в свой application.rb
файл, но при вызове logger.info
я получаю ошибку, связанную с арностью add
метода.
Самое странное, что мое пользовательское добавление никогда не вызывается, и эта ошибка возникает из ActiveSupport::LogerThreadSafeLevel#add
, вот так: .rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/activesupport-6.0.3.2/lib/active_support/logger_thread_safe_level.rb:51:in 'add'
.
Я думаю, что я упускаю что-то важное о внутренней работе механизма ведения журнала Rails … но что? ActiveSupport
Перезаписывает ли мой add
метод? Что я могу сделать, чтобы избежать этого?
Ответ №1:
Используйте ActiveSupport::Logger или измените файл конфигурации приложения
По умолчанию Rails ожидает, что регистратор будет экземпляром ActiveSupport::Logger . Однако вы можете изменить application.rb, чтобы использовать что-то другое, совместимое. В документации Rails говорится:
2.1 Что такое регистратор?
Rails использует класс ActiveSupport::Logger для записи информации журнала. Другие регистраторы, такие как Log4r, также могут быть заменены.
Вы можете указать альтернативный регистратор в config/application.rb или любом другом файле среды[.]
Ответ №2:
Rails ожидает, что метод Logger #add будет следовать интерфейсу регистратора Ruby, то есть одному обязательному аргументу ( severity
), за которым следуют два необязательных аргумента ( message
и progname
), а также необязательный блок.
Здесь Rails также предполагал очень специфическую семантику того, как эти аргументы используются реализацией регистратора для создания окончательного сообщения (при передаче message
, progname
блока или любой их комбинации.
class MultiLogger
def add(severity, message = nil, progname = nil, amp;block)
@loggers.each do |logger|
logger.add(severity, message, progname, amp;block)
end
true
end
def info(message = nil, amp;block)
add(Logger::INFO, message, amp;block)
end
# ...
end
В вашем исходном коде вы определили дополнительные обязательные параметры в вашем add
методе (а именно _attributes
и _environment
), которые не предоставляются при вызове метода, что является исключением. Как только вы исправите свой список параметров (и реализуете отсутствующие методы быстрого доступа и средства доступа), все должно работать.