Как стать автором
Обновить

Альтернативный Slf4j логгер «Бобина»

Java *
Из песочницы
Приветствую, дорогие друзья!

Хочу поделиться своими рассуждениями на тему логирования и тем к чему они привели.

Возможно по причине некоторого недостатка теоретических изысканий, логирование всегда было некой зоной турбулентности в Java мире. С течением времени, это вызвало появление нескольких библиотек для логирования, таких как:

  • Log4j
  • Java Util Logging
  • Commons Logging
  • Logback
  • Log4j2

Пытаясь сузить ограничения остальных, к сожалению каждая из них привносила свои недостатки.

И если с точки зрения стандартизации кода, ситуация улучшилась после появления Slf4j — как слоя абстракции для логирования, в существующих реализациях все еще присутствуют неразрешенные проблемы.

Как Open Source сообщество, мы предпринимаем инициативу чтобы придти к новому, революционному подходу — и создать легковесный (но в тоже время функционально-насыщенный) логгер, используя последние наработки, такие как скриптинг.

Проблемы


— Существующие реализации предоставляют лишь частичную поддержку скриптов в настройках


Это приводит к декларативному программированию в конфигурационных файлах логгера (XML, JSON, YAML), хотя гораздо проще было бы динамически интерпретировать конфигурационные значения во время исполнения, используя императивный скриптинг.

Возьмём пример конфигурации фильтра в Logback, для логирования только сообщений с уровнем логирования INFO:

<filter class="ch.qos.logback.classic.filter.LevelFilter">
  <level>INFO</level>
  <onMatch>ACCEPT</onMatch>
  <onMismatch>DENY</onMismatch>
</filter>

Это типичный пример декларативного XML программирования.

(да, Logback поддерживает фильтр использующий Groovy, но он применим только к конкретным аппендерам, а не к логгеру)

А вот поддержка скриптинга для форматирования строки отсутствует полностью.

— Усложнённая и переудлинённая конфигурация


Возьмём Logback и Log4j2:

Отсутствует возможность настроить уровень логирования для конкретного аппендера.

Аппендеры настраиваются отдельно от логгеров и логгеры ссылаются на аппендеры используя атрибут «AppenderRef» — при этом только логгеры поддерживают настройку уровня логирования и имён классов.

Допустим, нам надо исключить Debug сообщения от одного класса Foo из конкретного лог файла, не повлияв на другие лог файлы и классы.

В Logback это возможно используя Groovy Script фильтр на аппендере — но если у нас есть множество аппендеров — размер конфигурации растёт экспоненциально.

— Каждому уровню логирования — отдельный файл!


Мы не смогли найти возможность такой настройки, при которой сообщения группируются в файлы по уровню сообщения (debug, info, и т.д.)

Существующие возможности требуют дупликации аппендеров на каждый уровень логирования.

— Настройка фильтрации по имени класса в самом Root логгере


Root логгер поддерживает настройку только уровня логирования, но отсутствует возможность централизованного контроля того, какие классы должны логироваться.

— Существует концептуальное разъединение между тем, как производятся лог данные в приложении и тем, как эти данные потребляются логгером


Историческая практика такова, что логгеры (и их конфигурация) являются более классо-центричными, чем если бы файло-центричными.

Это противоречит человеческому восприятию, которое более логично воспринимает ожидания вокруг конечного содержимого лог файлов, а не беспокоится о настройке каждого отдельного класса.

На практике этот парадокс является причиной функциональных ограничений существующих реализаций:

  • Усложнённая конфигурация имён файлов
  • Иррациональная настройка логгера, например:

Logback поддерживает максимум 1 «discriminator» в «SiftingAppender».
SiftingAppender имеет ограничения в настройках полиси для архивирования
Переусложнённая настройка «RoutingAppender» в Log4j2

Решение


— Полная поддержка скриптинга в конфигурации


Bobbin (Бобина) использует конфигурацию как местодержатель для скриптов Groovy, которые определяют поведение логгера во времени исполнения приложения.

Вот так выглядит вышеприведенный пример «фильтра»:

{
  "levels": "['info'].contains(level)"
}

Каждый аспект логгера поддерживает настройку, используя скрипты:

  • Уровни логирования
  • Имена классов
  • Формат сообщения
  • Имена файлов

— Простая и краткая настройка


Bobbin не требует Энкодеры, Паттерны, Фильтры, Дискриминаторы и много других лишних вещей.

Он настраивается всего-лишь несколькими основными параметрами:

  • Уровни
  • Классы
  • Файлы
  • Формат строки

Отдельные файлы для каждого уровня логирования: просто разместите "${level}" в маску имени файла в Bobbin.json (файл настройки).

Пример файла настройки:

{
  "levels": "['debug', 'info', 'warn', 'error'].contains(level)",
  "destinations": [
    {
      "name": "io.infinite.bobbin.destinations.FileDestination",
      "properties": {
        "fileName": "\"./LOGS/PLUGINS/INPUT/${className}/${level}/${className}_${level}.log\""
      },
      "classes": "className.contains('conf.plugins.input')"
    },
    {
      "name": "io.infinite.bobbin.destinations.FileDestination",
      "properties": {
        "fileName": "\"./LOGS/PLUGINS/OUTPUT/${className}/${level}/${threadName}_${level}_${date}.log\""
      },
      "classes": "className.contains('conf.plugins.output')"
    },
    {
      "name": "io.infinite.bobbin.destinations.FileDestination",
      "properties": {
        "fileName": "\"./LOGS/THREADS/${threadGroupName}/${threadName}/${level}/${threadName}_${level}_${date}.log\""
      },
      "classes": "className.contains('io.infinite.')"
    },
    {
      "name": "io.infinite.bobbin.destinations.FileDestination",
      "properties": {
        "fileName": "\"./LOGS/ALL/WARNINGS_AND_ERRORS_${date}.log\""
      },
      "levels": "['warn', 'error'].contains(level)"
    },
    {
      "name": "io.infinite.bobbin.destinations.ConsoleDestination",
      "levels": "['warn', 'error'].contains(level)"
    }
  ]
}

Попробуйте Bobbin сейчас:

Gradle: compile "io.infinite:bobbin:2.0.0"

*Bobbin является Open Source проектом под лицензией Apache.
Теги:
Хабы:
Всего голосов 10: ↑9 и ↓1 +8
Просмотры 4K
Комментарии 31
Комментарии Комментарии 31