При работе веб-приложения происходит огромное количество синхронных и асинхронных событий. И, если появляется необходимость ответить на вопросы когда, где и почему что-либо случилось, то сделать это невозможно при отсутствии истории. Использование журналирования помогает быстрее реагировать и разрешать нештатные ситуации.
В приложении, построенном на декларативном фреймворке Evado, за ведение журнала событий отвечает компонент logger. Как и для других компонентов, его настройка задаётся в файлах конфигурации.
Фреймворк Evado построен на базе фреймворка Areto, который обеспечивает базовый функционал веб-приложения.
Конфигурация журнала
В компоненте logger имеются следующие сущности - это хранилище записей и тип событий. Рассмотрим параметры конфигурации компонента.
- defaultStores - карта конфигураций основных хранилищ записей (см. ниже). Ключами являются кодовые названия хранилищ. Например, common, error.
- stores - карта дополнительных конфигураций хранилищ. Данные из этой конфигурации перекрывают / расширяют данные из defaultStores. Этот параметр удобно использовать, если необходимо изменить или добавить хранилища, сохранив существующие.
- typeNames - список кодовых имен для типов событий. По умолчанию содержит следующие значения - trace, debug, info, warn, error, fatal. Порядок имен имеет значение для переключения текущего уровня ведения журнала (см. ниже параметр level).
- LogType - общая конфигурация для создания объектов типа событий (см. ниже). По кодовым имена из списка typeNames будут созданы соответствующие объекты. По умолчанию в конфигурации указано единственное хранилище - common.
- defaultTypes - карта индивидуальных конфигураций для создания объектов типа событий. Ключами являются кодовые имена типов. Данные из этой конфигурации перекрывают / расширяют данные из LogType. По умолчанию для событий error и fatal указаны два хранилища - error и common. Это значит, что события этих типов будет записаны сразу в оба. В первом случае - это удобно для фильтрации ошибок. Во втором - для анализа предшествующих ошибке событий.
- types - карта дополнительных конфигураций для создания объектов типа событий. Данные из этой конфигурации перекрывают данные из LogType и defaultTypes. Этот параметр удобно использовать, если необходимо изменить или добавить тип, сохранив существующие.
- level - кодовое имя типа, которое определяет текущий уровень ведения журнала. Все события из списка typeNames, которые находятся до level будут игнорироваться. То есть, если указан уровень info, то события info, warn, error, fatal будут записаны в журнал, а trace и debug - нет. Это позволяет регулировать количество записей в журнал на разных этапах работы приложения - разработка, отладка, эксплуатация.
- consoleOutput - флаг, означающий дублирование записи события в консольный вывод сервера. В конфигурации конкретного типа можно настроить дополнительные параметры консольного вывода. По умолчанию включен.
- errorConsoleLevel - кодовое имя типа события , которое переключает консольный метод отображения записи с console.log на console.error. По умолчанию включается при событиях warn и следующих - error, fatal.
Хранилища записей
Во фреймворке Evado реализованы два способа хранения записей журнала - файловая система и база данных. При необходимости вы можете назначить собственный класс реализации для любого другого вида хранилища.
Файловое хранилище
Записи добавляются в конец файла с названием хранилища (например, common.log). При достижении максимального размера происходит ротация в соответствии с заданным количеством файлов. Первый файл становится вторым, второй - третьим и т.д. (common.log -> common-1.log -> common-2.log). После этого начальный файл очищается.
За хранение в файловой системе отвечает класс FileLogStore. Рассмотрим конфигурацию создания объекта данного класса.
- basePath - относительный путь до директории хранения файлов журнала. Путь разрешается относительно текущего модуля, в котором определен компонент журнала. В общем случае - это само приложение. По умолчанию задана директория log.
- maxFileSize - максимальный размер файла с записями. Значение задается в мегабайтах. По умолчанию 2 мегабайта.
- maxFiles - максимальное количество сохраняемых файлов с записями. По умолчанию 1.
- observePeriod - период отслеживания размера файлов с записями. При достижении лимита происходит ротация файлов. Значение задается в секундах. Null - отключение. По умолчанию 30 секунд.
Ротация файлов достаточно ресурсоемкая операция, поэтому она не синхронизирована с добавлением записей.
Файлы логов приложения можно скачать через веб-интерфейс модуля «Администрирование».
Хранилище в базе данных
В базу данных записи сохраняются со следующими полями - тип события, дата события, текстовое описание и дополнительные данные. При достижении заданного лимита старые записи удаляются.
Для надежной работы системы журналирования рекомендуется использовать отдельную базу данных.
За хранение журнала в базе данных отвечает класс DatabaseLogStore. Рассмотрим конфигурацию создания объекта данного класса.
- db - идентификатор базы данных. Если не задан, то по умолчанию используется основная база приложения.
- table - наименование таблицы / коллекции в базе данных. По умолчанию log.
- key - наименование ключевого атрибута в таблице. По умолчанию _id.
- maxRows - максимальное количество записей в таблице. По умолчанию 10000. При превышении лимита старые записи удаляются.
- observePeriod - период отслеживания количества записей в таблице. По умолчанию 60 секунд.
Типы событий
Типы событий могут различаться не только по наименованию, но и по функциональности (например, некоторые события могут записываться в дополнительное хранилище). Для этого типы событий создаются как объекты класса LogType. Рассмотрим параметры их конфигурации.
- stores - массив названий хранилищ, в которые будут записываться события данного типа. По умолчанию пусто.
- consoleOutput - флаг, отвечающий за дублирование записи в консольный вывод сервера. По умолчанию включен.
- consoleMethod - наименование консольного метода для вывода записи данного типа (например, log, error, warn). По умолчанию log.
- stringifyOptions - опции для строкового представления дополнительных данных события. По умолчанию {depth: 10}. Для приведения данных к строке используется метод util.inspect. Опции передаются как второй аргумент.
Использование в коде
Для удобства использования в различных частях приложения имеется множество методов для логирования событий. Но, по факту, все они являются декораторами для вызова метода log из компонента logger, который принимает три аргумента:
- type - тип события.
- message - текстовое сообщение.
- data - дополнительные данные (необязательно). Могут быть любым объектом, который можно сeриализовать до строки.
Заключение
Нельзя избавиться от всех ошибок, но быстро о них узнать и локализовать - это свойство надёжного приложения. Фреймворк Evado содержит готовые инструменты журналирования для разных этапов жизненного цикла веб-приложения.
Попробовать декларативную разработку на фреймворке можно запустив демо-приложение Evado, как сразу в Docker, так и непосредственно, в окружении Node.js и MongoDB.