pino-telegram-logger-transport
v2.0.1
Published
A transport for Pino that forwards structured logs to the Telegram Bot API, supports media attachments, and ships ready-made adapters for NestJS, Fastify, and AWS Lambda
Maintainers
Readme
Pino Telegram transport
Русская версия · English version
Транспорт для Pino, пересылающий структурированные логи в Telegram Bot API с поддержкой медиа и адаптерами NestJS, Fastify и AWS Lambda. Поддерживаются личные чаты, супергруппы, темы и медиа-вложения.
Что нового
Последние изменения сосредоточены на трёх вещах: надёжность доставки, безопасное форматирование и снижение шума в Telegram.
Надёжность доставки и runtime
- Поддержка Node.js 18 теперь соответствует реальному runtime-поведению, без прямой runtime-зависимости от
undici. - Медленные запросы к Bot API ограничиваются через
requestTimeoutMs, а timeout-ошибки можно повторно отправлять. logger.flush(callback)теперь ждёт реальную доставку, включая retry и все части split-сообщений.maxQueueSizeиoverflowStrategyограничивают рост очереди в памяти, когда Telegram отвечает медленно.failOnInitErrorдобавляет fail-fast режим для production-окружений.
Безопасность форматирования и доставка длинных сообщений
redactKeysмаскирует чувствительные данные в блокахContext,ErrorиExtras.- Невалидный
timeбольше не ломает форматтер. - HTML-truncation стал безопасным для Telegram и больше не рвёт теги и entities.
splitLongMessagesпозволяет отправлять длинные текстовые логи несколькими частями, а не обрезать их целиком.- HTML-экранирование лучше соответствует ограничениям Telegram Bot API.
Маршрутизация, CLI и снижение шума
- У каждого target теперь может быть свой
minLevel, поэтому ошибки и предупреждения можно разводить по разным чатам. - Встроенные preset'ы
formatPreset: 'compact' | 'verbose'позволяют быстро переключаться между коротким и подробным форматом. dedupWindowMsподавляет повторяющиеся текстовые события в заданном временном окне.pino-telegram-cli check --probe-messageпроверяет не только доступ к чату, но и реальные права на отправку.pino-telegram-cli generate-config --include-tokenделает генерацию конфигурации безопасной по умолчанию.- CI и prerelease-проверки теперь покрывают Node.js
18/20/24иpino@9/10.
Пример production-конфигурации
import pino from 'pino';
const logger = pino({
transport: {
target: 'pino-telegram-logger-transport',
options: {
botToken: process.env.TELEGRAM_BOT_TOKEN!,
chatId: [
{ chatId: process.env.TELEGRAM_ALERTS_CHAT_ID!, minLevel: 'error' },
{ chatId: process.env.TELEGRAM_WARNINGS_CHAT_ID!, minLevel: 'warn' },
],
requestTimeoutMs: 10_000,
maxQueueSize: 1_000,
overflowStrategy: 'dropOldest',
failOnInitError: true,
splitLongMessages: true,
formatPreset: 'compact',
dedupWindowMs: 30_000,
},
},
});Основные возможности
- Отправляй сообщения в несколько чатов и тем с сохранением порядка.
- Маршрутизируй разные уровни логов по разным чатам через глобальный и per-target
minLevel. - Соблюдай лимиты Telegram, управляя задержками и повторами доставки.
- Ограничивай внутреннюю очередь доставки и выбирай стратегию переполнения.
- Подавляй повторяющиеся текстовые события через
dedupWindowMs. - Редактируй чувствительные ключи в
Context,ErrorиExtras. - Разбивай длинные текстовые сообщения на несколько частей через
splitLongMessages. - Используй встроенные preset'ы
compactиverboseили свой форматтер. - Отправляй текст, фото или документы в рамках одного транспорта.
- Переопределяй метод отправки функцией
sendв direct-stream режиме. - Проверяй токен и генерируй конфигурацию через встроенную CLI.
Требования
- Node.js 18+
- Node.js 20+ при использовании
pino@10 - Поддерживаемые сочетания:
pino@^9на Node.js 18+pino@^10на Node.js 20+
- Telegram-бот с правами записи в целевые чаты
Установка
npm install pino@^10 pino-telegram-logger-transport
# или
npm install pino@^9 pino-telegram-logger-transportБыстрый старт
import pino from 'pino';
const logger = pino({
transport: {
target: 'pino-telegram-logger-transport',
options: {
botToken: process.env.TELEGRAM_BOT_TOKEN!,
chatId: process.env.TELEGRAM_CHAT_ID,
threadId: process.env.TELEGRAM_THREAD_ID,
minLevel: 'warn',
minDelayBetweenMessages: 200,
retryAttempts: 3,
},
},
});
logger.info({ context: { requestId: '42' } }, 'Привет, Telegram!');Поведение по умолчанию
Транспорт формирует HTML-сообщение вида:
ℹ️ INFO — <b>Message</b> <b>Time:</b> 2025-09-17T16:35:00.000Z
<b>Context:</b>
<pre>{"requestId":"42"}</pre>При наличии err добавляется блок Error с полями message и stack. Дополнительные свойства записи, кроме level, time, msg, context, err, попадают в секцию Extras.
Повторы отправки
- Повторяй доставку при ответах 429 и 5xx.
- Настраивай задержки опциями
retryAttempts,retryInitialDelay,retryBackoffFactor,retryMaxDelay. - Прерывай медленные запросы к Telegram через
requestTimeoutMsс дефолтом10000мс и повторяй timeout-ошибки. - Учитывай
retry_after, если Telegram вернул рекомендацию по ожиданию. - Отключай повторные попытки значением
retryAttempts: 1.
Работа с медиа
logger.warn({
messageType: 'photo',
mediaUrl: 'https://example.com/path/to/photo',
caption: 'Снимок инцидента',
});По умолчанию форматтер ищет в логе поля messageType (text/photo/document), mediaUrl, mediaBuffer, mediaFilename, mediaContentType и caption.
Для двоичных вложений принимает Buffer, Uint8Array, ArrayBuffer или объекты { type: 'Buffer', data: number[] }.
Telegram ограничивает подпись медиа 1024 символами, поэтому держи caption в этом бюджете.
Кастомизация заголовков
pino({
transport: {
target: 'pino-telegram-logger-transport',
options: {
botToken,
chatId,
headings: {
time: 'Время',
context: 'Контекст',
error: 'Ошибка',
extras: 'Дополнительно',
},
includeExtras: false,
extraKeys: ['requestId', 'userId'],
},
},
});Комбинируй headings, includeExtras, extraKeys, contextKeys, maxMessageLength и splitLongMessages, чтобы адаптировать внешний вид сообщений.
Пользовательский метод отправки send
async function sendToQueue(payload: TelegramSendPayload, method: TelegramMethod) {
console.log('Method:', method);
console.log('Payload:', JSON.stringify(payload, null, 2));
}Опция send получает полезную нагрузку и выбранный метод. Старые обработчики, ожидающие один аргумент, остаются рабочими: второй параметр будет проигнорирован.
Передавай send, formatMessage и onDeliveryError только при прямом создании транспорта (const stream = telegramTransport(options); const logger = pino({}, stream);).
Режим transport.target сериализует опции и должен использоваться только с сериализуемыми значениями.
Интеграция с фреймворками
NestJS
import { LoggerModule } from 'nestjs-pino';
import { createNestLoggerOptions } from 'pino-telegram-logger-transport';
LoggerModule.forRoot(
createNestLoggerOptions(
{
botToken: process.env.TELEGRAM_BOT_TOKEN!,
chatId: process.env.TELEGRAM_CHAT_ID!,
},
{
pinoHttp: {
level: 'info',
},
},
),
);Fastify
import fastify from 'fastify';
import { createFastifyLoggerOptions } from 'pino-telegram-logger-transport';
const app = fastify({
logger: createFastifyLoggerOptions({
botToken: process.env.TELEGRAM_BOT_TOKEN!,
chatId: process.env.TELEGRAM_CHAT_ID!,
}),
});AWS Lambda
import pino from 'pino';
import { createLambdaLoggerOptions } from 'pino-telegram-logger-transport';
const logger = pino(
createLambdaLoggerOptions({
botToken: process.env.TELEGRAM_BOT_TOKEN!,
chatId: process.env.TELEGRAM_CHAT_ID!,
}),
);
export const handler = async (event: unknown) => {
logger.info({ event }, 'Lambda вызвана');
// бизнес-логика
};Документация
Лицензия
MIT
