Статьи

Ведение журнала без статического регистратора

Как вы организуете вход в свои приложения? Я имею в виду веб-приложения или приложения командной строки, или даже мобильные приложения. Могу поспорить, у вас есть глобальная переменная или синглтон, известный как Logger , который имеет несколько методов, таких как info() , error() и debug() . Вы настраиваете его при запуске приложения или настраиваете его через что-то вроде log4j.properties и записывает все на консоль, в файл или даже в базу данных. Я делал именно это, или что-то очень похожее , много лет, пока, наконец, не осознал, насколько неправильным был этот подход. В одном из моих недавних приложений на Ruby я делал все по-другому, и с тех пор я гораздо счастливее, чем был раньше.

Статический регистратор

Что ж, если ваше приложение простое и почти не имеет модульных или интеграционных тестов, у вас все будет в порядке со статическим регистратором, который по сути является глобальной переменной. Однако, как мы уже говорили , глобальные переменные являются злом. Что может пойти не так, если мы используем статический регистратор? Или, другими словами, как говорил один из моих друзей, какую именно проблему мы собираемся решить? В основном, есть две проблемы:

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

Чтобы преодолеть их оба, в Zold , приложении для командной строки Ruby, я решил передать log как переменную всем классам, которые нуждаются в журналировании. В Ruby это проще, чем в Java, потому что они имеют необязательные параметры. Посмотрите на этот класс , например (это упрощенная версия, конечно):

01
02
03
04
05
06
07
08
09
10
11
12
13
class Zold::List
  def initialize(wallets:, log: Log::NULL)
    @wallets = wallets
    @log = log
  end
  def run
    @wallets.all.sort.each do |id|
      @wallets.acq(id) do |wallet|
        @log.info("#{id}: #{wallet.balance}")
      end
    end
  end
end

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

Как видите, значением по умолчанию для log является Log::NULL , который является константой, которую я должен был определить сам, как регистратор по умолчанию, который нигде ничего не регистрирует. По умолчанию этот класс ничего не регистрирует. Он будет спокойно проверять все остатки всех кошельков и ничего не печатать. Ну, это будет печатать, но никто этого не увидит.

В модульном тесте я создаю объект с помощью нескольких методов, таких как debug() , info() и т. Д., И передаю его экземпляру класса Zold::List , который я тестирую. Другими словами, это поддельная / фиктивная версия регистратора, которую я использую для захвата всего, что отправляет Zold::List . Тогда я могу проверить, что там.

Я говорю очевидные вещи здесь? Если так, почему у нас все еще есть статические регистраторы повсюду в Java, Ruby, PHP, C # и т. Д.? В любом случае, я рекомендую вместо этого использовать инъекционную зависимость ведения журнала.

И да, к слову, я уверен, что вы заметили изменение в названии. Это больше не logger , это log . Я уверен, что ты знаешь почему .

Опубликовано на Java Code Geeks с разрешения Егора Бугаенко, партнера нашей программы JCG . Смотрите оригинальную статью здесь: Ведение журнала без статического регистратора

Мнения, высказанные участниками Java Code Geeks, являются их собственными.