Перезаписывает ли Rails регистратор Ruby по умолчанию?

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