Logger

Логгер, вдохновлённый PHP Monolog, предоставляет структурированную систему логирования с поддержкой каналов, обработчиков, процессоров и форматтеров. Реализация следует принципам PSR-3 и паттерну цепочки ответственности.
Мы всё ещё дорабатываем эту страницу. Некоторых данных здесь может не хватать — скоро дополним.

Уровни логирования

Уровни логирования расположены по возрастанию серьёзности — от детальной отладки (0) до критических сбоев (7). Фильтрация работает по включающему принципу: когда задан определённый уровень, логируются сообщения этого уровня и всех более высоких.

УровеньЗначениеКогда использоватьПрактический пример
DEBUG0Детальная отладочная информация для разработчиков
По умолчанию в development
Loaded 1523 records in 45ms
INFO1Информация о нормальной работе приложения
Отслеживание бизнес-логики
User #123 added item to cart
NOTICE2Важные, но некритичные события
Успешные операции с последствиями
System settings changed by administrator
WARNING3Потенциальные проблемы
Приложение работает, но требует внимания
Cache almost full (95%)
ERROR4Ошибки времени выполнения, требующие вмешательства
Часть функциональности недоступна
Failed to connect to database
CRITICAL5Критические сбои компонентов
Требуют срочного вмешательства в рабочее время
Payment gateway unavailable for more than 5 minutes
ALERT6Серьёзные проблемы, требующие немедленного решенияDisk space exhausted at 99%
EMERGENCY7Система неработоспособна
Наивысший уровень срочности
Server farm completely unavailable

Как работает фильтрация по уровням

import { Logger, ConsoleHandler, LogLevel } from '@bitrix24/b24jssdk'

// Пример 1: уровень ERROR
const $logger = new Logger('app');
$logger.pushHandler(new ConsoleHandler(LogLevel.ERROR));

// Эти логи БУДУТ выведены:
$logger.error('Loading error', {}); // ✓ уровень 4 >= 4
$logger.critical('Critical error'); // ✓ уровень 5 >= 4
$logger.alert('Alert'); // ✓ уровень 6 >= 4
$logger.emergency('Emergency'); // ✓ уровень 7 >= 4

// Эти логи НЕ будут выведены:
$logger.debug('Debug'); // ✗ уровень 0 < 4
$logger.info('Info'); // ✗ уровень 1 < 4
$logger.warning('Warning'); // ✗ уровень 3 < 4

Основные типы и интерфейсы

LogRecord Структура записи лога:

{
  channel: string,              // Имя канала логгера
  level: LogLevel,              // Числовой уровень
  levelName: LogLevelName,      // Имя уровня (например, 'DEBUG')
  message: string,              // Текст сообщения
  context: Record<string, any>, // Контекстные данные
  extra: Record<string, any>,   // Дополнительные данные (добавляются процессорами)
  timestamp: Date               // Временная метка
}

LoggerInterface Основной интерфейс логгера:

log(level: LogLevel, message: string, context?: Record<string, any>): Promise<void>
debug(message: string, context?: Record<string, any>): Promise<void>
info(message: string, context?: Record<string, any>): Promise<void>
notice(message: string, context?: Record<string, any>): Promise<void>
warning(message: string, context?: Record<string, any>): Promise<void>
error(message: string, context?: Record<string, any>): Promise<void>
critical(message: string, context?: Record<string, any>): Promise<void>
alert(message: string, context?: Record<string, any>): Promise<void>
emergency(message: string, context?: Record<string, any>): Promise<void>

Handler Обработчик лога:

handle(record: LogRecord): Promise<boolean>  // Обработать запись
isHandling(level: LogLevel): boolean         // Проверить поддержку уровня
shouldBubble(): boolean                      // Продолжать ли цепочку
setFormatter(formatter: Formatter): void     // Установить форматтер
getFormatter(): Formatter | null             // Получить форматтер

Formatter для преобразования LogRecord:

format(record: LogRecord): any

Processor для модификации LogRecord:

(record: LogRecord) => LogRecord

Основные классы

AbstractLogger Абстрактный базовый класс, реализующий удобные методы (debug, info и т.д.).

Logger Основная реализация логгера:

constructor(channel: string)                 // Создать логгер с указанным каналом
pushHandler(handler: Handler): this          // Добавить обработчик
popHandler(): Handler | null                 // Удалить последний обработчик
setHandlers(handlers: Handler[]): this       // Задать список обработчиков
pushProcessor(processor: Processor): this    // Добавить процессор
log(level, message, context): Promise<void>  // Основной метод логирования

NullLogger Заглушка для случаев, когда логирование не требуется. Не выполняет операций.

Фабрика логгеров

LoggerFactory Статические методы для создания логгеров:

createNullLogger(): LoggerInterface
createForBrowser(channel: string, isDevMode: boolean = false): LoggerInterface
createForBrowserDevelopment(channel: string, level: LogLevel = LogLevel.DEBUG): LoggerInterface
createForBrowserProduction(channel: string, level: LogLevel = LogLevel.ERROR): LoggerInterface
forcedLog(logger, action, message, context): Promise<void>  // Принудительное логирование

Процессоры

Процессоры модифицируют записи лога перед обработкой:

Встроенные процессоры:

  • memoryUsageProcessor — добавляет использование памяти
  • pidProcessor — добавляет ID процесса

Создание своего процессора:

import { Processor } from '@bitrix24/b24jssdk'

const customProcessor: Processor = (record) => {
  record.extra.customField = 'value'
  return record
}

Форматтеры

AbstractFormatter Базовый класс форматтера с поддержкой форматирования дат.

LineFormatter Форматирует логи в строку с поддержкой шаблонов:

// По умолчанию: '[{channel}] {levelName}: {message} {context} {extra} {date}'
new LineFormatter(formatString, dateFormat)

Доступные плейсхолдеры:

  • {channel} — имя канала
  • {levelName} — имя уровня
  • {message} — сообщение
  • {context} — контекст в JSON
  • {extra} — дополнительные данные в JSON
  • {timestamp} — unix-таймстамп
  • {date} — дата в заданном формате

JsonFormatter: Форматирует логи в JSON-строку.

TelegramFormatter: Форматирует запись лога для отправки в Telegram. Поддерживает HTML-разметку с экранированными спецсимволами.

Обработчики

AbstractHandler Базовый класс обработчика с поддержкой уровня логирования и всплытия.

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

ConsoleV2Handler Улучшенная версия ConsoleHandler с более читаемым выводом.

MemoryHandler Хранит логи в памяти (полезно для тестирования и отладки):

import { MemoryHandler, LogLevel } from '@bitrix24/b24jssdk'

const handler = new MemoryHandler(LogLevel.DEBUG, { limit: 1000 })
const records = handler.getRecords() // Получить все записи
handler.clear() // Очистить записи

ConsolaAdapter Адаптер для Consola.

WinstonAdapter Адаптер для Winston.

StreamHandler Обработчик потоков Node.js для записи логов в потоки.

TelegramHandlerОтправляет логи в Telegram-чат. В браузере выводит предупреждение в консоль. На сервере отправляет сообщение через Telegram Bot API.

Использование

Базовый пример

import { LoggerFactory } from '@bitrix24/b24jssdk'

const devMode = !!(typeof import.meta !== 'undefined' && (import.meta.dev || import.meta.env?.DEV))
const $logger = LoggerFactory.createForBrowser('Example:getCrmItem', devMode)
$logger.info('User logged in', { userId: 123 })

Расширенная конфигурация

import { Logger, ConsoleV2Handler, LineFormatter, LogLevel, memoryUsageProcessor, pidProcessor } from '@bitrix24/b24jssdk'

const $logger = new Logger('app')
const handler = new ConsoleV2Handler(LogLevel.DEBUG)
handler.setFormatter(new LineFormatter('[{levelName}] {message}'))

$logger
  .pushHandler(handler)
  .pushProcessor(memoryUsageProcessor)
  .pushProcessor(pidProcessor)

$logger.warning('Low memory', { freeMemory: '10MB' })

Создание своего обработчика

// @check-ignore: AbstractHandler is not re-exported from the SDK main index

import { AbstractHandler, LogRecord } from '@bitrix24/b24jssdk'

class CustomHandler extends AbstractHandler {
  async handle(record: LogRecord): Promise<boolean> {
    // Отправить на сервер, записать в файл и т.д.
    return true // Возвращает true, если запись обработана
  }
}

Возможности

  1. Асинхронность: все методы логирования возвращают Promise.
  2. Цепочка ответственности: обработчики вызываются последовательно.
  3. Всплытие: если обработчик возвращает true и shouldBubble() === false, цепочка прерывается.
  4. Каналы: логи группируются по каналам для фильтрации.
  5. Контекст: поддержка структурированных данных через параметр context.

Рекомендации по использованию

Development

  • Используйте LoggerFactory.createForBrowserDevelopment с уровнем DEBUG
  • Добавляйте процессоры для отладочной информации

Production

  • Используйте LoggerFactory.createForBrowserProduction с уровнем ERROR или выше
  • Ограничивайте число обработчиков ради производительности
  • Рассмотрите создание своих обработчиков для отправки логов на сервер

Контекст

// @check-ignore: illustrative snippet — orderId, userId, error are not declared

// Хорошо:
$logger.error('Failed to process order', {
  orderId: 123,
  userId: 456,
  error: error.message
})

// Плохо:
$logger.error(`Failed to process order ${orderId} for user ${userId}: ${error.message}`)