С лучшими практиками ведения журнала

Если я задам вам вопрос, какая функция JavaScript наиболее полезна для поиска ошибок, ваш очевидный ответ - console.log.

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

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

Что такое ведение журнала и почему оно важно?

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

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

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

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

Вот почему нам нужна краткая, чистая и качественная структура ведения журналов.

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

Таким образом, в конечном итоге эти журналы упростят разработчикам, DevOps, системным администраторам или SecOps получение информации и определение основной причины проблем с приложениями и инфраструктурой.

Уровни регистрации

Это самая важная часть любой системы регистрации. Уровни журнала - это метаданные для журналов. Уровень определяет серьезность зарегистрированного инцидента.

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

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

  • ERROR : Серьезная проблема / сбой при обработке текущей операции. Системные операторы должны обработать это как можно скорее.
  • WARN : Эти журналы представляют собой предупреждения и не блокируют работу приложения, они предоставляют предупреждения при обнаружении неожиданной проблемы с приложением. Для администраторов было бы полезно просмотреть, чтобы решить, следует ли решить эту проблему.
  • INFO : нормальное поведение приложений, в которых указывается, что произошло. Не обязательно требовать, чтобы вы следили за этим.
  • DEBUG : Этот уровень предназначен для разработчиков. Он дает подробную диагностическую информацию. Он используется для получения информации, необходимой для диагностики, устранения неполадок или тестирования приложения.
  • TRACE : этот уровень фиксирует все подробности о поведении приложения. В основном он используется для детального отслеживания логики приложения.

Примечание. Обычное поведение любого регистратора отслеживает только текущий уровень и журналы вышеупомянутого уровня. Таким образом, если вы установите уровень журнала на INFO, вы будете получать события журнала только с уровнями INFO, WARN и ERROR.

Лучшие практики для ведения журнала

Перед внедрением системы ведения журналов вам обязательно следует ознакомиться с передовыми методами, такими как:

1) Ведение журнала должно быть осмысленным и иметь цель

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

Примечание. Мы не должны включать уровень DEBUG или TRACE в рабочей среде, если нет проблем с кодовой базой. (После решения проблемы обязательно переключите его обратно на уровень INFO или ERROR. )

2. Разделите журналы на несколько файлов журналов на случай, если у вас есть приложение с большим трафиком.

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

Он будет заархивировать ваши файлы журналов в зависимости от времени или размера. Эта функция ежедневного скользящего журнала используется в большинстве приложений корпоративного уровня.

3. Ведение журнала должно быть структурировано и выполняться по уровням.

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

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

4. Ведение журнала не должно приводить к возникновению ошибки или исключения.

Иногда журналы могут приводить к серьезным ошибкам. См. Этот пример. Предположим, существует метод обслуживания пользователей, определенный как → getUser(id). Если мы хотим найти пользователя, нам нужно передать его идентификатор. Предположим, вы хотите регистрировать имя пользователя при обработке.

logger.info(`Processing user: ${userService.getUser().getName()}`);

Если вы забудете передать идентификатор, как в этом случае, getUser() вернет значение null, а getName() вызовет исключение. Поэтому убедитесь, что вы не совершаете подобных глупых ошибок.

5) Регистраторы не должны регистрировать конфиденциальную информацию.

При ведении журнала мы должны убедиться, что мы не записываем конфиденциальную информацию, такую ​​как имя пользователя и пароль, финансовую информацию, такую ​​как номер карты, номер CVV и т. Д.

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

Какие у нас есть библиотеки / фреймворки для ведения логов? Существует множество доступных библиотек, которые легко сделают эту работу за вас.

Это самые популярные библиотеки журналов Node.js, доступные в NPM:

  • Winston - Полностью гибкая универсальная библиотека логирования.
  • Morgan - промежуточное ПО для регистратора HTTP-запросов.
  • Pino - сверхбыстрый (очень низкие накладные расходы), естественный регистратор JSON.
  • Loglevel— Минимальное легкое простое ведение журнала для JavaScript.
  • log4js —Фреймворк без зависимостей времени выполнения.

В этой статье мы будем использовать библиотеку Winston.

Почему Winston Logger?

Winston - одна из самых мощных и гибких библиотек журналов с открытым исходным кодом для Node.js. По сути, Winston - регистратор практически для всего!

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

Давайте посмотрим, насколько популярна эта библиотека Winston с тенденциями NPM.

Как вы видели из анализа, вы можете осознать популярность Уинстона. Но по каким причинам он завоевал такую ​​большую аудиторию?

Причина в том, что → Winston предлагает следующее:

  • Централизованный контроль над тем, как и когда регистрироваться - меняйте код в одном месте.
  • Контролируйте, куда отправляются ваши журналы - сохраняйте журналы в нескольких местах назначения (например, AWS S3, Elasticsearch, MongoDB и т. Д.).
  • Пользовательские форматы ведения журнала - префикс с меткой времени, красочные уровни ведения журнала, форматирование JSON и многое другое.

Все в порядке! Мы выбираем один из лучших фреймворков для ведения журнала. Теперь приступим к реализации.

Реализация Winston в Node.js

Я сделал простой REST-сервер, чтобы продемонстрировать сценарий ведения журнала. В настоящее время для простоты у него есть только два API. Структура папок будет следующей:

  • app.js — Основная точка входа
  • routes - для обработки маршрутизации
  • middleware - для обработки аутентификации
  • controllers - для обработки запросов REST API
  • logs - для хранения файлов журнала
  • utils - для реализации логгера

Во-первых, нам нужно добавить библиотеку журналов Winston с помощью следующей команды:

npm i winston

Любой, кто использует yarn, может установить его до yarn add winston. Затем нам нужно инициализировать регистратор. Для этого я уже создал файл в utils как logger.js . Давайте посмотрим, как он запускается с помощью этого кода:

Мы можем инициализировать регистратор, вызвав функцию createLogger в библиотеке Winston. Затем мы должны определить транспорты. Что это за транспорты?

Журналы нужно куда-то сдавать. Транспорт - это место, где сохраняется журнал.

Существует более 30 вариантов транспорта, включая выход в отдельный файл, консоль или в сторонние системы, такие как AWS S3, Elasticsearch, MongoDB и многие другие. Вы можете добавить любые количество транспортов в массив transports:.

Если вы хотите узнать больше об этих транспортах, вы можете посетить эту официальную страницу Winston GitHub.



В объекте транспортера мы можем указать имя файла для хранения наших журналов. Затем начинается самое интересное. Мы можем отформатировать сообщение журнала по своему усмотрению.

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

Однако перезапись и добавление таких параметров, как предопределенные токены, временные метки, цвета и т. Д., Выполняется просто, как показано выше.

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

const logger = require("./utils/logger");
app.listen(port, () => {
  logger.info(`Server Started in port : ${port}!`);
});

Посмотри, как это просто. Мы можем увидеть результат в logs/server.log файле следующим образом.

Мы также можем изменить уровни журнала. Посмотрим, как это работает. Я добавил этот регистратор в свой обработчик аутентификации.

if (!req.get("Authorization")) {
    logger.error("Not Authenticated!");
    return res.status(401).json({ message: "User Not Authenticated!" });

Затем мы можем попробовать запустить этот API без заголовка авторизации, и тогда вы увидите журнал ошибок в файле журнала.

Эти конечные точки API четко определены в моем файле readme в репозитории. Вы можете попробовать это. Ссылку на полную реализацию кода можно увидеть в разделе ресурсов.

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

Множественные транспорты

У нас может быть несколько транспортов. Измените функцию createLogger, как показано ниже в logger.js:

В папке журнала вы увидите, что новые файлы были созданы после запуска сервера.

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



Несколько регистраторов

Winston позволяет создавать собственные регистраторы. Это дает вам возможность контролировать и настраивать определенные регистраторы в зависимости от служб вашего приложения.

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

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

В пользовательском сервисе мы можем использовать следующий код:

В сервисе аутентификации будет использоваться этот код:

Как видите, наши логи будут отображаться отдельно.

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

Файлы журнала Daily Rolling

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

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

Но для этого вам потребуется дополнительная библиотека Winston.

npm install winston-daily-rotate-file

Теперь мы можем добавить новый транспорт в logger.js файл с помощью этого кода:

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

  • maxSize: максимальный размер файла, после которого он будет вращаться. Это может быть количество байтов или единицы в килобайтах, мегабайтах или гигабайтах. Если вы используете единицы измерения, добавьте в качестве суффикса «k», «m» или «g».
  • maxFiles: максимальное количество файлов / дней для хранения журналов. По истечении этого периода самый старый файл журнала будет удален. Это может быть количество файлов или количество дней. Если вы используете дни, добавьте в качестве суффикса "d".

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

Это все для этого урока. Надеюсь, я затронул самые важные области лесозаготовок.

Заключение

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

Вкратце, мы узнали:

  • Что такое логирование и почему это важно?
  • Каковы уровни ведения журнала?
  • Лучшие практики для ведения журнала
  • Платформа ведения журналов Winston
  • Реализация с node.js
  • Дополнительные возможности Winston

Теперь вы полностью готовы реализовать ведение журнала в своем следующем приложении.

Спасибо за прочтение. Удачной регистрации!

Ресурсы