Инициализация SLF4J - логгеры замены

Я делаю проект в Scala, и я использую slf4j с Logback для входа. Теперь инициализация логирования не кажется поточно-ориентированной. В качестве решения slf4j создает замещающие логгеры, т.е. NoOp-логгеры, которые глотают лог-операторы, сделанные во время инициализации. Домашняя страница slf4j гласит:

Заменяющие регистраторы были созданы во время фазы конфигурации по умолчанию базовой системы регистрации

Настраиваемые системы журналирования, такие как logback и log4j, могут создавать компоненты, которые вызывают регистраторы во время их собственной инициализации. Смотрите выпуск LOGBACK-127 для типичного случая. Однако, поскольку процесс связывания с SLF4J еще не завершен (поскольку базовая система ведения журнала еще не была полностью загружена в память), невозможно удовлетворить такие запросы на создание средства ведения журнала.

Чтобы избежать этой проблемы с курицей и яйцом, SLF4J создает замещающие логгеры на этом этапе (инициализация). Звонки, сделанные на сменные логгеры на этом этапе, просто сбрасываются. После завершения инициализации замещающий регистратор будет делегировать входящие вызовы соответствующей реализации регистратора и в противном случае будет функционировать как любой другой регистратор, возвращенный LoggerFactory.

Если необходимо было создать какой-либо замещающий регистратор, SLF4J выдаст список таких регистраторов. Этот список предназначен для того, чтобы вы знали, что любые вызовы журналов, сделанные этим регистраторам во время инициализации, были отброшены.

Существует также еще нерешенная проблема, описывающая проблему.

Для меня проблема возникла, когда я тестировал, как части приложения работают вместе. Операторы журнала производителя, работающие в своем собственном потоке, были потеряны, потому что они были отправлены в замещающий регистратор. Добавление оператора журнала непосредственно перед созданием потока производителя, казалось, помогло вовремя инициализировать регистратор. Тем не менее, я хотел бы знать, гарантирует ли произвольный вызов LoggerFactory.getLogger в качестве первого утверждения в приложении, что я никогда не буду входить в систему в качестве альтернативного регистратора.

Короче говоря, мои вопросы:

  • Инстанцирует ли LoggerFactory.getLogger(classOf[A]) все регистраторы или может быть, что два последующих одновременных вызова LoggerFactory.getLogger(classOf[B]) приведут к одному замещающему регистратору?

  • Есть ли способ получить гарантию, т.е. проверить, что регистратор был инициализирован (я не могу проверить тип регистратора, так как он скрыт фасадом slf4j) Редактировать: На самом деле, я просто подумал, что я мог бы быть возможность проверить тип регистратора. Могут ли следующие мысли привести к полезному решению?:

    def logger(context: Class[_]) = {
      log = LoggerFactory.getLogger(context)
      if (log.isInstanceOf[SubstituteLogger]) logger(context) else log
    

    Проблема, которую я вижу с этим подходом, состоит в том, что он зависит от одного конкретного класса реализации, то есть NOPLogger SubstituteLogger.

Приложение: я не уверен, имеет ли это отношение к этому вопросу, но я обертываю регистратор slf4j в классе, который создается для каждого контекста журналирования (context = класс, вызывающий регистратор). Кроме того, существует объект, который создает экземпляры этой оболочки, который передается в качестве неявного аргумента конструктора каждому классу, который хочет вести журналирование. Я передаю логгер в качестве аргумента, а не логирую статический объект (или смешиваю в черту), чтобы позволить пройти специальный логгер в модульных тестах.

1 ответ

Я столкнулся с той же проблемой, потому что несколько зависимостей принесли свои собственные дубликаты NoOp Logger. В моем случае решение состояло в том, чтобы явно унаследовать зависимость от slf4j-log4j12 с помощью:

libraryDependencies = Seq(
  ...
  ).map(_.exclude("org.slf4j", "slf4j-log4j12" ))
Другие вопросы по тегам