Публикация была переведена автоматически. Исходный язык: Русский
В мире Node.js, где производительность часто упирается в один поток (Single Thread), любая синхронная операция имеет высокую цену. Традиционное логирование может стать «тихим убийцей» производительности вашего приложения.
Pino — это логгер, созданный с одной главной целью: скорость. Он позиционирует себя как библиотека с очень низкими накладными расходами (very low overhead), которая в некоторых сценариях работает в 5 раз быстрее аналогов (Winston, Bunyan).
Когда вы используете console.log или тяжелые библиотеки логирования, Node.js тратит ресурсы CPU на:
- Форматирование строки.
- Сериализацию объектов.
- Блокирующую запись в поток вывода (stdout/stderr).
Если ваше приложение обрабатывает тысячи запросов в секунду, «тяжелый» логгер может заблокировать Event Loop, увеличивая задержку (latency) для пользователей. Pino решает эту проблему радикально.
Главный секрет скорости Pino заключается в отказе от форматирования логов внутри процесса приложения.
Pino пишет сырой JSON прямо в stdout. Вся «красота», фильтрация и транспортировка логов в базу данных должны происходить в отдельном процессе.
Это позволяет основному приложению Node.js заниматься бизнес-логикой, а не тратить циклы процессора на раскрашивание текста.
- JSON по умолчанию: Идеален для машин и агрегаторов логов (ELK Stack, Datadog, Splunk).
- Минимальная аллокация памяти: Pino агрессивно оптимизирован, чтобы создавать как можно меньше мусора (Garbage Collection).
- Асинхронность: Использование библиотеки sonic-boom для невероятно быстрой записи в дескрипторы файлов.
Установка предельно проста:
npm install pinoБазовое использование:
const pino = require('pino');
const logger = pino();
logger.info('Привет, мир!');
logger.error({ err: new Error('Упс!') }, 'Что-то пошло не так');Что вы увидите в консоли:
{"level":30,"time":1638367492011,"pid":1234,"hostname":"MacBook","msg":"Привет, мир!"}
{"level":50,"time":1638367492012,"pid":1234,"hostname":"MacBook","err":{"type":"Error","message":"Упс!","stack":"..."},"msg":"Что-то пошло не так"}Поскольку читать JSON глазами сложно, Pino предлагает инструмент pino-pretty для разработки.
Важно: Используйте pino-pretty только в режиме разработки или через pipeline (конвейер), но не как зависимость внутри продакшн-кода.
Ваше приложение продолжает быстро писать JSON, а отдельный процесс его форматирует
npm install -g pino-pretty
node app.js | pino-prettyВ новых версиях Pino (v7+) появилась поддержка Transports. Это позволяет выполнять операции ввода-вывода (запись в файл, отправку в HTTP) в отдельном рабочем потоке (Worker Thread).
Это означает, что даже если диск медленный или сеть лагает, основной поток вашего приложения не заблокируется.
const pino = require('pino');
const transport = pino.transport({
target: 'pino/file',
options: { destination: './app.log' }
});
const logger = pino(transport);Вместо того чтобы создавать объект с контекстом каждый раз заново, используйте дочерние логгеры. Это снижает нагрузку на сериализацию.
// Плохо (дублирование контекста)
logger.info({ requestId: '123', module: 'auth' }, 'User logged in');
logger.info({ requestId: '123', module: 'auth' }, 'Token generated');
// Хорошо (Pino way)
const child = logger.child({ requestId: '123', module: 'auth' });
child.info('User logged in');
child.info('Token generated');Pino позволяет динамически менять уровень логирования. В продакшене ставьте уровень info или warn.
// Логи уровня 'debug' не будут даже сериализоваться,
// если текущий уровень 'info'. Экономия CPU!
logger.debug('Этот тяжелый объект не будет обработан');Безопасность важна, но она не должна тормозить. Pino имеет встроенный высокопроизводительный механизм скрытия чувствительных данных (паролей, токенов).
nst logger = pino({
redact: ['req.headers.authorization', 'user.password']
});
logger.info({ user: { password: 'secret' } }, 'User info');
// Вывод: {"user":{"password":"[Redacted]"},...}Хотя точные цифры зависят от железа, бенчмарки (доступные в репозитории Pino) показывают следующую картину при высокой нагрузке:
| Библиотека | Операций в секунду (примерно) |
| Pino | ~12 000 |
| Winston | ~2 500 |
| Bunyan | ~2 000 |
| Debug | ~1 000 |
Pino — это стандарт де-факто для современных высоконагруженных приложений на Node.js (например, он встроен по умолчанию в фреймворк Fastify).
Если вам нужна максимальная пропускная способность (RPS) и вы хотите следовать принципам 12-factor app (логи как поток событий), Pino — ваш лучший выбор.
- Замените console.log на вызовы logger.
- Перестаньте форматировать строки внутри кода (забудьте про шаблонные строки в логах), передавайте объекты.
- Настройте pino-pretty только для локальной разработки.
В мире Node.js, где производительность часто упирается в один поток (Single Thread), любая синхронная операция имеет высокую цену. Традиционное логирование может стать «тихим убийцей» производительности вашего приложения.
Pino — это логгер, созданный с одной главной целью: скорость. Он позиционирует себя как библиотека с очень низкими накладными расходами (very low overhead), которая в некоторых сценариях работает в 5 раз быстрее аналогов (Winston, Bunyan).
Когда вы используете console.log или тяжелые библиотеки логирования, Node.js тратит ресурсы CPU на:
- Форматирование строки.
- Сериализацию объектов.
- Блокирующую запись в поток вывода (stdout/stderr).
Если ваше приложение обрабатывает тысячи запросов в секунду, «тяжелый» логгер может заблокировать Event Loop, увеличивая задержку (latency) для пользователей. Pino решает эту проблему радикально.
Главный секрет скорости Pino заключается в отказе от форматирования логов внутри процесса приложения.
Pino пишет сырой JSON прямо в stdout. Вся «красота», фильтрация и транспортировка логов в базу данных должны происходить в отдельном процессе.
Это позволяет основному приложению Node.js заниматься бизнес-логикой, а не тратить циклы процессора на раскрашивание текста.
- JSON по умолчанию: Идеален для машин и агрегаторов логов (ELK Stack, Datadog, Splunk).
- Минимальная аллокация памяти: Pino агрессивно оптимизирован, чтобы создавать как можно меньше мусора (Garbage Collection).
- Асинхронность: Использование библиотеки sonic-boom для невероятно быстрой записи в дескрипторы файлов.
Установка предельно проста:
npm install pinoБазовое использование:
const pino = require('pino');
const logger = pino();
logger.info('Привет, мир!');
logger.error({ err: new Error('Упс!') }, 'Что-то пошло не так');Что вы увидите в консоли:
{"level":30,"time":1638367492011,"pid":1234,"hostname":"MacBook","msg":"Привет, мир!"}
{"level":50,"time":1638367492012,"pid":1234,"hostname":"MacBook","err":{"type":"Error","message":"Упс!","stack":"..."},"msg":"Что-то пошло не так"}Поскольку читать JSON глазами сложно, Pino предлагает инструмент pino-pretty для разработки.
Важно: Используйте pino-pretty только в режиме разработки или через pipeline (конвейер), но не как зависимость внутри продакшн-кода.
Ваше приложение продолжает быстро писать JSON, а отдельный процесс его форматирует
npm install -g pino-pretty
node app.js | pino-prettyВ новых версиях Pino (v7+) появилась поддержка Transports. Это позволяет выполнять операции ввода-вывода (запись в файл, отправку в HTTP) в отдельном рабочем потоке (Worker Thread).
Это означает, что даже если диск медленный или сеть лагает, основной поток вашего приложения не заблокируется.
const pino = require('pino');
const transport = pino.transport({
target: 'pino/file',
options: { destination: './app.log' }
});
const logger = pino(transport);Вместо того чтобы создавать объект с контекстом каждый раз заново, используйте дочерние логгеры. Это снижает нагрузку на сериализацию.
// Плохо (дублирование контекста)
logger.info({ requestId: '123', module: 'auth' }, 'User logged in');
logger.info({ requestId: '123', module: 'auth' }, 'Token generated');
// Хорошо (Pino way)
const child = logger.child({ requestId: '123', module: 'auth' });
child.info('User logged in');
child.info('Token generated');Pino позволяет динамически менять уровень логирования. В продакшене ставьте уровень info или warn.
// Логи уровня 'debug' не будут даже сериализоваться,
// если текущий уровень 'info'. Экономия CPU!
logger.debug('Этот тяжелый объект не будет обработан');Безопасность важна, но она не должна тормозить. Pino имеет встроенный высокопроизводительный механизм скрытия чувствительных данных (паролей, токенов).
nst logger = pino({
redact: ['req.headers.authorization', 'user.password']
});
logger.info({ user: { password: 'secret' } }, 'User info');
// Вывод: {"user":{"password":"[Redacted]"},...}Хотя точные цифры зависят от железа, бенчмарки (доступные в репозитории Pino) показывают следующую картину при высокой нагрузке:
| Библиотека | Операций в секунду (примерно) |
| Pino | ~12 000 |
| Winston | ~2 500 |
| Bunyan | ~2 000 |
| Debug | ~1 000 |
Pino — это стандарт де-факто для современных высоконагруженных приложений на Node.js (например, он встроен по умолчанию в фреймворк Fastify).
Если вам нужна максимальная пропускная способность (RPS) и вы хотите следовать принципам 12-factor app (логи как поток событий), Pino — ваш лучший выбор.
- Замените console.log на вызовы logger.
- Перестаньте форматировать строки внутри кода (забудьте про шаблонные строки в логах), передавайте объекты.
- Настройте pino-pretty только для локальной разработки.