npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@vvlad1973/pino-logger-tree

v1.1.0

Published

Hierarchical logger tree for Pino with automatic child registration, configuration cascading, decorators and LoggerAware pattern support

Downloads

16

Readme

@vvlad1973/pino-logger-tree

Библиотека для организации иерархического логирования на базе Pino с каскадной конфигурацией и автоматической регистрацией дочерних логгеров.

Возможности

  • Иерархическая структура логгеров - организация логгеров в древовидную структуру с путями вида app.service.api
  • Каскадная конфигурация - автоматическое наследование настроек от родительских узлов к дочерним
  • Полная совместимость с Pino - прозрачное делегирование всех методов Pino через Proxy
  • Автоматическая регистрация - метод child() автоматически создает узлы в дереве
  • Динамические обновления - изменение конфигурации с опциональным распространением на потомков
  • Автоматическая привязка - встроенная система binding для LoggerAware объектов
  • Декораторы для методов и классов - @LogMethod, @LogSyncMethod, @LogClass с автоматическим логированием и маскированием чувствительных данных
  • LoggerAwareBase - базовый класс для унифицированной инициализации логгеров
  • Трассировка функций - методы logFunctionStart/End с автоматическим определением имени функции
  • TypeScript first - полная типизация с strict mode
  • Высокая производительность - минимальный overhead благодаря Proxy и кэшированию
  • Покрытие тестами 90%+ - комплексные тесты всех компонентов

Установка

npm install @vvlad1973/pino-logger-tree pino

Опционально для красивого вывода в разработке:

npm install --save-dev pino-pretty

Быстрый старт

import { LoggerTree } from '@vvlad1973/pino-logger-tree';

// Создаем дерево логгеров с базовой конфигурацией
const tree = new LoggerTree({
  level: 'info',
  name: 'my-app'
});

// Создаем логгер для модуля приложения
const appLogger = tree.createLogger('app');
appLogger.info('Application started');

// Создаем логгер с повышенной детализацией
const apiLogger = tree.createLogger('app.api', { level: 'debug' });
apiLogger.debug('API module initialized');

// Дочерний логгер наследует конфигурацию родителя
const dbLogger = apiLogger.child('database');
dbLogger.debug('Connected to database');
// Путь: 'app.api.database', уровень: 'debug' (унаследован)

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

Создание и настройка дерева

import pino from 'pino';
import { LoggerTree } from '@vvlad1973/pino-logger-tree';

// Базовая конфигурация
const tree = new LoggerTree({
  level: 'info',
  name: 'my-app'
});

// С опциональным destination
const destination = pino.destination('./app.log');
const treeWithDest = new LoggerTree(
  { level: 'info' },
  destination
);

Каскадная конфигурация

const tree = new LoggerTree({ level: 'warn' });

// Родитель с уровнем debug
tree.createLogger('app', { level: 'debug' });

// Дочерний логгер автоматически наследует debug
const serviceLogger = tree.createLogger('app.service');
serviceLogger.debug('Service initialized'); // ✓ Видно

// Внук переопределяет уровень
const apiLogger = tree.createLogger('app.service.api', { level: 'trace' });
apiLogger.trace('Detailed trace'); // ✓ Видно

Динамическое обновление конфигурации

const logger = tree.createLogger('app');

// Обновление только для текущего узла
tree.updateParam('app', 'level', 'debug');

// Обновление с распространением на всех потомков
tree.updateParam('app', 'level', 'trace', { force: true });

// Ссылка на logger остается той же, но конфигурация обновлена
logger.trace('Now visible'); // ✓ Видно

Автоматическая привязка к объектам

import { LoggerAware, TreeLogger } from '@vvlad1973/pino-logger-tree';

class UserService implements LoggerAware {
  logger!: TreeLogger;

  async getUser(id: number) {
    this.logger.info('Fetching user', { userId: id });
    // ... логика
  }
}

const service = new UserService();

// Привязываем логгер к сервису
tree.bind('app.user-service', service);

// service.logger автоматически установлен и будет обновляться
service.getUser(42);

// При обновлении конфигурации логгер в service обновится автоматически
tree.updateParam('app.user-service', 'level', 'debug');

Трассировка функций

const logger = tree.createLogger('app', { level: 'trace' });

function processData(id: number, options: object) {
  // Автоматическое определение имени функции + логирование параметров
  logger.logFunctionStart('processData', { id, options });

  // ... обработка данных

  logger.logFunctionEnd('processData');
}

processData(42, { mode: 'fast' });
// → {"level":10,"params":{"id":42,"options":{"mode":"fast"}},"msg":"Function start: processData"}
// → {"level":10,"msg":"Function end: processData"}

Bindings и контекст

// Создание с bindings
const logger = tree.createLogger('app', {
  bindings: {
    service: 'user-service',
    version: '1.0.0'
  }
});

logger.info('Service ready');
// → {"level":30,"service":"user-service","version":"1.0.0","msg":"Service ready"}

// Добавление контекста через child()
const requestLogger = logger.child({ requestId: 'req-123' });
requestLogger.info('Processing request');
// → {"level":30,"service":"user-service","requestId":"req-123","msg":"Processing request"}

API

LoggerTree

Constructor

constructor(baseOptions?: PinoLoggerOptions, destination?: DestinationStream)

Создает новое дерево логгеров с базовой конфигурацией.

createLogger

createLogger(path: string, options?: TreeLoggerOptions): TreeLogger

Создает или возвращает существующий логгер для указанного пути.

  • path - точка-разделенный путь (например, 'app.service.api')
  • options - опции конфигурации и bindings

updateParam

updateParam(path: string, key: string, value: unknown, options?: UpdateParamOptions): void

Обновляет параметр конфигурации для узла.

  • path - путь к узлу
  • key - ключ параметра (например, 'level')
  • value - новое значение
  • options.force - распространить на всех потомков

bind / unbind

bind(path: string, target: LoggerAware): void
unbind(path: string, target: LoggerAware): void

Привязывает/отвязывает LoggerAware объект к пути в дереве.

TreeLogger

TreeLogger полностью совместим с Pino Logger и предоставляет все его методы:

  • trace(msg, ...args) / trace(obj, msg, ...args)
  • debug(msg, ...args) / debug(obj, msg, ...args)
  • info(msg, ...args) / info(obj, msg, ...args)
  • warn(msg, ...args) / warn(obj, msg, ...args)
  • error(msg, ...args) / error(obj, msg, ...args)
  • fatal(msg, ...args) / fatal(obj, msg, ...args)
  • level - getter/setter для уровня логирования
  • bindings() - получение текущих bindings
  • flush() - сброс буферов

Дополнительные методы TreeLogger

child
child(path: string, bindings?: Record<string, unknown>): TreeLogger
child(bindings: Record<string, unknown>): TreeLogger

Создает дочерний логгер с автоматической регистрацией в дереве.

getPath
getPath(): string

Возвращает путь логгера в дереве.

getTree
getTree(): LoggerTree

Возвращает экземпляр LoggerTree, управляющий этим логгером.

logFunctionStart
logFunctionStart(name?: string, params?: Record<string, unknown>): void

Логирует начало функции на уровне trace. Автоматически определяет имя функции, если не указано.

logFunctionEnd
logFunctionEnd(name?: string): void

Логирует конец функции на уровне trace.

Вспомогательные классы

LoggerAwareBase

Абстрактный базовый класс для унифицированной инициализации логгеров через наследование.

abstract class LoggerAwareBase implements LoggerAware {
  logger!: TreeLogger;

  protected initializeLogger(
    options: BaseLoggerOptions | undefined,
    defaultPath: string
  ): void;

  protected cleanupLogger(): void;

  protected getChildLogger(childPath: string): TreeLogger;
}

initializeLogger

Инициализирует логгер с тремя режимами работы:

  1. Прямой логгер - использует options.logger напрямую
  2. Привязка к дереву - использует options.loggerTree для автоматической привязки
  3. Собственное дерево - создает изолированное дерево логгеров
class MyService extends LoggerAwareBase {
  constructor(options?: BaseLoggerOptions) {
    super();
    this.initializeLogger(options, 'my-service');
  }
}

cleanupLogger

Отвязывает объект от дерева логгеров при уничтожении.

getChildLogger

Создает дочерний логгер с иерархическим путем.

LoggerManager

Менеджер логгеров для композиционного подхода (когда наследование невозможно).

class LoggerManager {
  logger: TreeLogger;

  constructor(
    options: BaseLoggerOptions | undefined,
    defaultPath: string,
    target?: LoggerAware
  );

  cleanup(): void;

  getChildLogger(childPath: string): TreeLogger;
}

Особенности

Предоставляет ту же функциональность, что и LoggerAwareBase, но через композицию:

  1. Те же три режима инициализации: прямой логгер, привязка к дереву, собственное дерево
  2. Опциональная привязка к target: автоматически устанавливает target.logger
  3. Управление жизненным циклом: метод cleanup() для корректной отвязки
class MyService {
  private loggerManager: LoggerManager;

  constructor(options?: BaseLoggerOptions) {
    this.loggerManager = new LoggerManager(options, 'my-service');
  }

  get logger(): TreeLogger {
    return this.loggerManager.logger;
  }

  doWork() {
    this.logger.info('Working...');
  }

  destroy() {
    this.loggerManager.cleanup();
  }
}

// С автоматической привязкой к target
class ServiceWithBinding implements LoggerAware {
  logger!: TreeLogger;
  private loggerManager: LoggerManager;

  constructor(options?: BaseLoggerOptions) {
    this.loggerManager = new LoggerManager(options, 'service', this);
    // this.logger уже установлен автоматически
  }

  destroy() {
    this.loggerManager.cleanup();
  }
}

Декораторы

@LogMethod

Декоратор для автоматического логирования асинхронных методов.

interface LogMethodOptions extends ParameterLoggingOptions {
  level?: LoggerLevel;           // Уровень логирования (default: 'trace')
  startMessage?: string;         // Кастомное сообщение старта
  endMessage?: string;           // Кастомное сообщение завершения
  errorMessage?: string;         // Кастомное сообщение ошибки
  logResult?: boolean;           // Логировать результат (default: false)
  rethrow?: boolean;             // Пробрасывать ошибки (default: true)
}

Особенности:

  • Автоматически логирует начало, завершение и ошибки метода
  • Извлекает имена параметров из сигнатуры функции
  • Маскирует чувствительные данные (password, apiKey, token, secret, и др.)
  • Поддерживает кастомные сообщения и контекстные поля
class ApiService extends LoggerAwareBase {
  @LogMethod({
    level: 'info',
    logResult: true,
    contextFields: ['userId']
  })
  async fetchUser(id: number): Promise<User> {
    // ...
  }
}

@LogSyncMethod

Декоратор для автоматического логирования синхронных методов.

interface LogSyncMethodOptions extends ParameterLoggingOptions {
  level?: LoggerLevel;           // Уровень логирования (default: 'trace')
  startMessage?: string;         // Кастомное сообщение старта
  endMessage?: string;           // Кастомное сообщение завершения
  errorMessage?: string;         // Кастомное сообщение ошибки
  logResult?: boolean;           // Логировать результат (default: false)
  rethrow?: boolean;             // Пробрасывать ошибки (default: true)
}

Идентичен @LogMethod, но для синхронных методов.

class Calculator extends LoggerAwareBase {
  @LogSyncMethod({ level: 'debug', logResult: true })
  add(a: number, b: number): number {
    return a + b;
  }
}

@LogClass

Декоратор класса для автоматического применения логирования ко всем методам.

interface LogClassOptions {
  asyncMethodOptions?: LogMethodOptions;      // Опции для async методов
  syncMethodOptions?: LogSyncMethodOptions;   // Опции для sync методов
  exclude?: string[];                         // Исключить методы
  include?: string[];                         // Включить только эти методы
  logConstructor?: boolean;                   // Логировать конструктор
}

Особенности:

  • Автоматически определяет async/sync методы
  • Исключает стандартные методы: constructor, toString, toJSON, valueOf
  • Поддерживает белые (include) и черные (exclude) списки методов
  • Применяет разные опции для async и sync методов
@LogClass({
  asyncMethodOptions: { level: 'info', logResult: true },
  syncMethodOptions: { level: 'debug' },
  exclude: ['internalHelper']
})
class UserRepository extends LoggerAwareBase {
  async findById(id: number) { /* ... */ }
  validateId(id: number) { /* ... */ }
  internalHelper() { /* не логируется */ }
}

ParameterLoggingOptions

Базовые опции для логирования параметров (используются всеми декораторами).

interface ParameterLoggingOptions {
  logParams?: boolean;                    // Логировать параметры (default: true)
  maskSensitive?: boolean;                // Маскировать чувствительные данные (default: true)
  sensitivePatterns?: string[];           // Кастомные паттерны для маскирования
  excludeParams?: string[];               // Исключить определенные параметры
  contextFields?: string[];               // Добавить поля из контекста this
}

Автоматическое маскирование:

По умолчанию маскируются поля со следующими паттернами (регистронезависимо):

  • password
  • secret
  • token
  • apikey / api_key
  • accesstoken / access_token
  • refreshtoken / refresh_token
  • privatekey / private_key
  • credentials
  • authorization
@LogMethod({
  excludeParams: ['internalFlag'],
  contextFields: ['requestId', 'userId'],
  sensitivePatterns: ['ssn', 'creditCard']
})
async processPayment(
  amount: number,
  creditCard: string,
  internalFlag: boolean
) {
  // Логирует: { amount: 100, creditCard: '***MASKED***', requestId: '...', userId: '...' }
  // internalFlag не логируется
}

Типы

LoggerAware

interface LoggerAware {
  logger: TreeLogger;
}

Интерфейс для объектов с автоматической инъекцией логгера.

TreeLoggerOptions

interface TreeLoggerOptions extends PinoLoggerOptions {
  bindings?: Record<string, unknown>;
}

Опции для создания TreeLogger.

BaseLoggerOptions

interface BaseLoggerOptions {
  logger?: TreeLogger;           // Прямой логгер
  loggerTree?: LoggerTree;       // Дерево для привязки
  loggerPath?: string;           // Путь в дереве
  logLevel?: LoggerLevel;        // Уровень логирования
  loggerOptions?: PinoLoggerOptions; // Опции Pino
}

Опции для инициализации логгера в LoggerAwareBase.

UpdateParamOptions

interface UpdateParamOptions {
  force?: boolean;
}

Опции для обновления параметров конфигурации.

LoggerLevel

type LoggerLevel = 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'fatal' | 'silent';

Доступные уровни логирования.

LoggerNode

interface LoggerNode {
  config: PinoLoggerOptions;
  logger?: TreeLogger;
  children: Map<string, LoggerNode>;
}

Узел в дереве логгеров (используется внутри LoggerTree).

Утилиты

getCallerName

function getCallerName(level?: number): string

Получает имя вызывающей функции из stack trace.

Параметры:

  • level - уровень стека (опционально, для автоматического режима не указывать)

Возвращает: имя функции или 'anonymous'

function myFunction() {
  const caller = getCallerName();
  console.log(caller); // 'myFunction'
}

LoggerLevels

const LoggerLevels = {
  TRACE: 'trace',
  DEBUG: 'debug',
  INFO: 'info',
  WARN: 'warn',
  ERROR: 'error',
  FATAL: 'fatal',
  SILENT: 'silent',
} as const;

Константа с уровнями логирования для type-safe использования.

import { LoggerLevels } from '@vvlad1973/pino-logger-tree';

const logger = tree.createLogger('app', { level: LoggerLevels.DEBUG });

extractParameterNames

function extractParameterNames(fn: Function): string[]

Извлекает имена параметров из сигнатуры функции.

function example(userId: number, email: string) {}
const names = extractParameterNames(example);
// ['userId', 'email']

mapArgumentsToParams

function mapArgumentsToParams(
  fn: Function,
  args: unknown[],
  context?: object,
  options?: ParameterLoggingOptions
): Record<string, unknown> | undefined

Преобразует аргументы функции в объект параметров с учетом опций маскирования.

isSensitiveField

function isSensitiveField(
  key: string,
  sensitivePatterns?: string[]
): boolean

Проверяет, является ли поле чувствительным для маскирования.

maskSensitiveData

function maskSensitiveData(
  data: unknown,
  sensitivePatterns?: string[]
): unknown

Рекурсивно маскирует чувствительные данные в объекте.

DEFAULT_SENSITIVE_PATTERNS

const DEFAULT_SENSITIVE_PATTERNS: string[]

Стандартные паттерны для поиска чувствительных полей:

  • password, secret, token, apikey, api_key
  • accesstoken, access_token, refreshtoken, refresh_token
  • privatekey, private_key, credentials, authorization

prepareParamsForLogging

function prepareParamsForLogging(
  fn: Function,
  args: unknown[],
  context?: object,
  options?: ParameterLoggingOptions
): Record<string, unknown> | undefined

Подготавливает параметры для логирования с применением всех правил (извлечение имен, маскирование, контекстные поля).

Примеры использования

Express/Fastify интеграция

import express from 'express';
import { v4 as uuid } from 'uuid';
import { loggerTree } from './logger';

const app = express();

app.use((req, res, next) => {
  req.logger = loggerTree
    .createLogger('app.api')
    .child({
      requestId: uuid(),
      method: req.method,
      url: req.url
    });

  req.logger.info('Request started');
  next();
});

app.get('/users', (req, res) => {
  req.logger.debug('Fetching users');
  // ...
});

Класс с автоматической привязкой

import { LoggerAware, TreeLogger } from '@vvlad1973/pino-logger-tree';

class DatabaseService implements LoggerAware {
  logger!: TreeLogger;

  async connect() {
    this.logger.info('Connecting to database');
    // ...
  }

  async query(sql: string) {
    this.logger.debug('Executing query', { sql });
    // ...
  }
}

const db = new DatabaseService();
tree.bind('app.database', db);

// db.logger автоматически установлен и управляется деревом
db.connect();

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

import { LoggerAwareBase } from '@vvlad1973/pino-logger-tree';

class UserService extends LoggerAwareBase {
  constructor(options?: BaseLoggerOptions) {
    super();
    // Автоматическая инициализация логгера с тремя режимами:
    // 1. Если передан logger - использовать его
    // 2. Если передан loggerTree - привязаться к дереву
    // 3. Иначе создать собственное дерево
    this.initializeLogger(options, 'user-service');
  }

  async createUser(username: string, email: string) {
    this.logger.info('Creating user', { username, email });
    // ...
  }

  destroy() {
    // Очистка при уничтожении сервиса
    this.cleanupLogger();
  }
}

// Режим 1: С существующим деревом
const service1 = new UserService({ loggerTree: tree });

// Режим 2: С прямым логгером
const service2 = new UserService({ logger: tree.createLogger('custom') });

// Режим 3: Создаст собственное дерево
const service3 = new UserService({ logLevel: 'debug' });

Использование декораторов

import { LoggerAwareBase, LogMethod, LogSyncMethod, LogClass } from '@vvlad1973/pino-logger-tree';

class PaymentService extends LoggerAwareBase {
  constructor() {
    super();
    this.initializeLogger({}, 'payment-service');
  }

  // Декоратор для асинхронных методов
  @LogMethod({ level: 'info', logResult: true })
  async processPayment(amount: number, currency: string): Promise<PaymentResult> {
    // Автоматически логирует:
    // INFO: Method processPayment started { amount: 100, currency: 'USD' }
    // INFO: Method processPayment completed { result: {...} }
    return { transactionId: '123', status: 'completed' };
  }

  // Декоратор для синхронных методов
  @LogSyncMethod({ level: 'debug' })
  validateAmount(amount: number): boolean {
    // Автоматически логирует:
    // DEBUG: Method validateAmount started { amount: 100 }
    // DEBUG: Method validateAmount completed
    return amount > 0;
  }

  // Автоматическое маскирование чувствительных данных
  @LogMethod()
  async authenticate(apiKey: string, secret: string): Promise<string> {
    // Логирует: { apiKey: '***MASKED***', secret: '***MASKED***' }
    return 'token-123';
  }
}

// Декоратор для всего класса
@LogClass({
  asyncMethodOptions: { level: 'info', logResult: true },
  syncMethodOptions: { level: 'debug' },
  exclude: ['internalMethod']
})
class AutoLoggedService extends LoggerAwareBase {
  constructor() {
    super();
    this.initializeLogger({}, 'auto-logged');
  }

  // Автоматически логируется (async)
  async fetchData(id: number) {
    return { id, data: 'example' };
  }

  // Автоматически логируется (sync)
  processData(data: string) {
    return data.toUpperCase();
  }

  // Не логируется (в exclude)
  internalMethod() {
    // ...
  }
}

Модульная структура приложения

// logger.ts
export const loggerTree = new LoggerTree({
  level: process.env.LOG_LEVEL || 'info',
  name: 'my-app'
});

// services/user.service.ts
import { loggerTree } from '../logger';

const logger = loggerTree.createLogger('app.services.user');

export class UserService {
  async createUser(data: UserData) {
    logger.info('Creating user', { email: data.email });
    // ...
  }
}

// services/auth.service.ts
import { loggerTree } from '../logger';

const logger = loggerTree.createLogger('app.services.auth', { level: 'debug' });

export class AuthService {
  async login(credentials: Credentials) {
    logger.debug('Login attempt', { username: credentials.username });
    // ...
  }
}

Продакшен конфигурация

import pino from 'pino';
import { LoggerTree } from '@vvlad1973/pino-logger-tree';

const tree = new LoggerTree({
  level: process.env.LOG_LEVEL || 'info',
  name: process.env.APP_NAME,

  // Structured timestamps
  timestamp: pino.stdTimeFunctions.isoTime,

  // Редактирование чувствительных данных
  redact: {
    paths: ['password', 'secret', 'token', '*.password', 'headers.authorization'],
    remove: true
  },

  // Сериализаторы для ошибок
  serializers: {
    err: pino.stdSerializers.err,
    req: pino.stdSerializers.req,
    res: pino.stdSerializers.res
  }
});

Производительность

  • Минимальный overhead: Proxy напрямую делегирует методы Pino
  • Кэширование: Каждый логгер создается один раз и переиспользуется
  • Lazy initialization: Узлы создаются только при необходимости
  • Эффективная агрегация: Конфигурация собирается только при создании логгера

Бенчмарки показывают, что overhead библиотеки составляет менее 1% по сравнению с прямым использованием Pino.

Требования

  • Node.js >= 18.0
  • TypeScript >= 5.0 (для разработки)
  • Pino >= 10.0

Разработка

# Установка зависимостей
npm install

# Сборка
npm run build

# Тесты
npm test

# Тесты с покрытием
npm run test:coverage

# Линтинг
npm run lint

# Генерация документации
npm run doc

Тестирование

Библиотека имеет комплексное покрытие тестами:

npm test

Результаты:

  • 125 тестов полностью пройдены в 5 тестовых файлах:
    • 31 тест для LoggerTree
    • 33 теста для TreeLogger
    • 46 тестов для декораторов (@LogMethod, @LogSyncMethod, @LogClass)
    • 9 тестов для LoggerAwareBase
    • 6 тестов для LoggerManager
  • Покрытие кода: соответствует требуемым стандартам (80%+)
  • Все критические компоненты покрыты тестами

Тестовые наборы:

  • LoggerTree - создание, каскадная конфигурация, динамические обновления, binding
  • TreeLogger - методы логирования, child логгеры, bindings, функциональная трассировка
  • Декораторы - автоматическое логирование, маскирование параметров, обработка ошибок
  • LoggerAwareBase - три режима инициализации, управление жизненным циклом
  • LoggerManager - композиционный подход, привязка к target объектам

Документация

Лицензия

MIT

Автор

Vladislav Vnukovskiy [email protected]

Связанные проекты

  • Pino - Fast JSON logger for Node.js
  • Pino-pretty - Beautiful logs for development

Поддержка