Рубрики
Uncategorized

Дайте свои журналы больше контекста — часть 2

Эта статья была первоначально опубликована в моем личном блоге. Строительство контекстного регистратора т … Теги с узлом, регистрацией, дежоптом.

Эта статья была первоначально опубликована в моем Персональный блог Отказ

Создание контекстуального регистратора

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

Дайте свои журналы больше контекста — часть 1

Генрике Барселос · 6 февраля · 8 мин прочитаны

Код, который мы собираемся построить на эту историю, на моем Github Отказ Если вы просто хотите проверить окончательную версию, вы можете получить его в Мастер филиал.

В прошлый раз мы проходили через способ управления контекстом через одновременные запросы, используя Pino и CLS-крючок Отказ Теперь давайте построим обертку вокруг Pino. Это автоматически справится с этим для нас.

И теперь это tiiiiiiime!

Нам нужно построить регистратор, который будет иметь базовую «глобальный» контекст через CLS-крючок , но также позволит нам дополнить такое контекст, когда на самом деле вызывая методы регистратора.

Чтобы улучшить многократность и совместимость, мы хотим поддерживать оригинальные по умолчанию Pino. API Таким образом, у нас уже есть хороший набор тестовых случаев для покрытия. Кроме того, нам нужно предоставить путь для нашего приложения взаимодействовать с контекстом.

Мы собираемся реализовать эту обертку TDD стиль. Однако тесты, которые мы напишем, не являются «единицы» тестами в строгом смысле, потому что они будут включать Pino. сам и устанавливает утверждения о сгенерированных данных журнала. Это возможно, потому что Pino принимает пользовательский WritableStream как его место назначения.

В качестве структуры тестирования мы будем использовать ava Отказ Имейте в виду, что пока ava По умолчанию транспилирует тестовые файлы, это не делает это для фактического кода без правильной настройки Бабел Отказ Чтобы не добавить более сложность к этому решению, все код (включая тесты) не будут использовать модули ES или любые функции, которые не доступны в Node.js 10.9.0.

Если вы хотите, следите за реализацией, пожалуйста, проверьте инструкции в репозитории GitHub:

HBarcelos/Thank-your-logs-more-context

Обелочка на вершине Pino, которая обеспечивает интеграцию с крючком CLS для лучшего контекста в сообщениях журнала

Этот репозиторий — это реализация идей от «Дайте ваши журналы больше контекста» серии статьи:

Требования

Настраивать

Если вы следите за статьей, после клонирования этого хранилища я проверю Первоначальный тег:

git clone https://github.com/hbarcelos/give-your-logs-more-context
git checkout initial

Каждый шаг в статье является последующий коммит, который вы можете ссылаться на хэш Commit.

Окончательная версия находится под Финал Тег, который также ГОЛОВА главной ветки.

git checkout final
# or...
git checkout master

После выбора того, что вы хотите увидеть, запустите:

yarn install
yarn test

Я попытался сделать эту последовательность как можно более естественную, только устраняя некоторые внутренние петли и борьбу, которые происходят в обычном кодирующем сеансе.

Начальная настройка

yarn init -y
yarn add pino cls-hooked
yarn add --dev ava

Хорошая особенность Pino принимает пользовательский WritableStream как его место назначения. Это сделает нашу жизнь легче при тестировании нашего пользовательского регистратора.

Обеспечение методов уровня журнала

Для простоты давайте придерживаться Pino Уровни журнала по умолчанию: трассировка , отлаживать , Информация , предупреждать , Ошибка . и Fatal Отказ

Самый простой способ добиться этого:

logger.js в настоящее время просто фабричная функция, которая возвращает обычную Pino экземпляры. logger.test.js Файл генерирует один тестовый случай для каждого доступного метода, чтобы убедиться, что мы не нарушаем ничего позже.

Parse-Json-stream.js Это утилита, которая будет анализировать выходной поток журнала и возвращать объекты простого JavaScript, чтобы облегчить запуск утверждений против вывода журнала.

Stream-To-Generator.js Есть ли для удобства: ava не хорошо играет с потоковыми API. Чтобы сделать тесты более лаконичными, мы преобразуем поток журнала к Генератор Это дает обещания к следующему записи журнала.

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

Сохранение контекста на вызове метода регистратора

Также обратите внимание, что Pino Позвольте нам пройти локальный контекст к записи журнала, добавляя объект в список аргументов. Это поведение, которое мы хотим сохранить.

Итак, давайте добавим тестовый случай, который охватывает этот сценарий:

Поскольку до сих пор мы просто создаем Pino экземпляр, тест пройдет.

Добавление осведомленности CLS.

Теперь мы начнем трогать CLS. Сначала нам нужно создать пространство имен и разоблачить его в мир:

Предотвращение совместного использования контекста CLS между экземплярами

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

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

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

Иногда меньше больше!

Вот что изменилось:

Применение контекста CLS для журналов

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

Извините, я не мог сломать это на меньшие изменения:/

Тестовый код не имеет ничего особенного в этом, просто обратите внимание, что мы должны запустить наше ведение журнала и утверждение внутри logger.cls.run метод обратного вызова.

Вещи начинают интересны в реальном коде, хотя. Мы используем JavaScript Прокси Чтобы перехватить звонки метода журнала и исправления их аргументов.

Итак, в очереди 52 Мы создаем прокси для нашего объекта регистратора, чей обработчик называется loggerobjecthandler — линии 34-43 Отказ Обработчик определяет Получить ловушка , это перехванет только звонки для методов журнала — трассировка , Отладка , и т.д. Что это делает, это обернуть эти методы в еще один прокси, чей обработчик называется logmethodhandler — линии 11-32 Отказ

loggermethodhandler собирает текущий активный контекст на CLS, исключая некоторые нерелевантные свойства от него — линии 14-15 . Затем, основываясь на текущем списке аргументов, он проверяет, имеете ли мы или нет локальный контекст на вызове метода. Если мы этого не сделаем, то нам просто нужно добавить контекст CLS в список аргументов — строки 20-23 Отказ В противном случае нам нужно объединить локальный контекст в контекст CLS — линии 24-28 Отказ Наконец, мы называем оригинальный метод с правильными аргументами — Line 30 Отказ

Распространение изменений в детских регистраторах

Хорошая особенность от Pino Это позволяет нам создавать детские регистраторы через .child () метод. Детский регистратор поддерживает все свойства со своего родителя, но также может принять дополнительный контекст. Итак, нам нужно также знать наше поколение детей CL:

Опять же, новые тесты являются самоописательными. Давайте сосредоточимся на реализации. Сначала мы извлекли создание обертки в свою собственную функцию, названной CreateWrapper — линии 47-52 Отказ Это позволяет нам создать обертку для детских регистраторов.

Далее мы определяем Childmethodhandler которые перехватывают звонки на .child () — линии 18-25 Отказ Этот обработчик позвонит CreateWrapper На вновь созданном детском регистратере, передавая контекст CLS от родителя в качестве параметра. Это гарантирует, что родитель и дети (и дети детей) все имеют тот же контекст.

Наконец, мы изменяем реализацию loggerobjecthandler Чтобы включить прокси для .child () Способ, а также — линии 30-45 — в том числе некоторые внутренние рефакторинга на укладки.

Дальнейшие улучшения

Похоже, наш код работает до сих пор, но он не может быть оптимальным. Проблема, которая легко обнаружить, что мы создаем новые прокси на лету для каждого вызова для детей и методов журнала. Хотя это не может быть проблемой с первой — потому что мы бы не звоним .child () Очень часто — это не так для последнего.

Чтобы предотвратить эту проблему, мы могли бы создать прокси для желаемых методов к тому времени, когда мы создаем сам регистратор и поместите их в качестве свойств объекта регистратора. Когда мы называем методы, loggerobjecthandler просто проверил бы, если для текущего метода установлен прокси-сервер. Если это так, он возвращает прокси, в противном случае он возвращает исходное свойство:

Итак, теперь у нас есть наш фабрика регистратора. Теперь нам нужно интегрировать его с нашим приложением. Из окончательного примера из предыдущей статьи мы могли бы рефакторовать:

Код выше, в значительной степени одинаково, что я успешно использовал в производстве иногда и сэкономил меня и команды, которые я работал с большим количеством времени во время отладки.

Если у вас есть какие-либо предложения, которые могут его улучшить, вы более чем приветствуете.

Вам понравилось то, что вы только что прочитали? Купи мне пиво с tippin.me Отказ

Оригинал: «https://dev.to/hbarcelos/give-your-logs-more-context-part-2-264n»