05 Система журналирования
Logger
Logger является неотъемлемой частью ядра и его экземпляр всегда доступен в сервисе по адресу this.Logger
Инициализация логгера:
import {ServiceHost,Logger} from '@morphcluster/core'
import {LoggerBackendStore } from '@morphcluster/logger'
...
host = new ServiceHost("TestHost")
const logger = new Logger()
//Добавление бэкэнда (об этом ниже)
logger.backends.push(new LoggerBackendStore(host))
//Добавляем логгер в хост, чтобы он автоматически распространил его по сервисам в хосте
host.Logger = logger
//Ниже, начинаем добавление сервисов
host.addService(new Test())
LoggerBackend
LoggerBackend - специальный клиент для отправки данных полученным логгером. Встроенный LoggerBackendStore работает с сервисом (в т.ч. удаленно) LogStorePlain, который сохраняет данные в PostgreSQL.
Инициализация LogStorePlain:
import {LogStorePlain} from '@morphcluster/logger'
...
//Ниже, начинаем добавление сервисов
//Хранилище логов
host.addService(new LogStorePlain(host,{
"pg": {
//uri для подключения postgresql
"uri": "postgresql://postgres:123@127.0.0.1:5432/carabi",
//schema из postgresql
"schema": "logger",
//timezone pg клиента
"timezone": "Europe/Moscow"
}
}))
Отправка сообщений
Чтобы написать начальное сообщение необходимо создать цепочку.
//payload - любой объект, который будет сохранен в журнале (или null)
let payload = {"test":123}
//options - опции записи журнала
let options = {
//Уровень важности сообщения:
//1 - отладка, 10 - обычный, 50 - предупр., 100 - ошибка
level:10,
//Сервис, который создал цепочку (обычно this.name)
service: "HelloWorld",
//Логин текущего пользователя сессии (если есть)
username: options.username
}
let log = await this.Logger.createWriter("Сообщение", payload, options)
createWriter вернет дочерний объект класса Logger. Этим объектом можно продолжить цепочку, и его, желательно, передать во все вызовы внутри этого работы. Если в полученном объекте (log в примере) вызвать еще раз createWriter, то получится древовидная структура (необходимо для сетевых запросов).
Продолжить цепочку (следующее сообщение) можно командой:
let payload = {"test":123}
await log.write("Сообщение", payload, {level:10})
После окончания цепочки (текущей работы), ее необходимо закрыть:
log.close()
Для логирования исключения есть специальный метод writeException, который опубликует исключение и закроет цепочку:
let log = await this.Logger.createWriter(...)
try {
...
log.close()
} catch(e) {
log.writeException(e)
...
}
Если перехватывать сообщение не нужно, можно использовать следующую конструкцию:
let log = await this.Logger.createWriter(...)
await log.wrap(async() => {
//Здесь можно использовать log
log.write(...)
})
//Здесь log уже будет закрыт, если произошло исключение - оно будет записано
//Но само исключение не будет перехвачено
Журналирование между сервисами
Чтобы цепочка сохранялась между вызовами сервисов, третьим параметром передается созданный зараннее log.
await this.HelloWorld.hello(data, workspace, log)
Исключение - если в схеме сервиса у этого запроса "noLogs":true
И наоборот, если ваш сервис вызывает, например FastifyRest по http запросу, то у вас уже есть готовая цепочка:
async hello(request, workspace, log) {
await log.write("Hello to Logger")
...
}
Закрывать лог дожен тот метод, где он создан.
Когда для выполнения необходим логгер (напр. выполнение запроса), но записывать журнал не нужно, можно передать лог-заглушку, без заполнения backends:
const log = new Logger()
await this.HelloWorld.hello(data, workspace, log)
No Comments