Логирование — критически важная часть любого Node.js приложения. Рассмотрим основные подходы, их преимущества и недостатки.
Простейший подход:
console.log('Запрос получен:', req.url);
console.error('Ошибка:', err);
Плюсы:
Минусы:
Популярная библиотека логирования:
const winston = require('winston');
const logger = winston.createLogger({
level: 'info',
format: winston.format.json(),
transports: [
new winston.transports.File({ filename: 'error.log', level: 'error' }),
new winston.transports.File({ filename: 'combined.log' })
]
});
logger.info('Запрос', { method: req.method, url: req.url });
Плюсы:
Минусы:
Высокопроизводительный логгер:
const pino = require('pino');
const logger = pino({
level: process.env.LOG_LEVEL || 'info',
formatters: {
level: (label) => ({ level: label })
}
});
logger.info({ req }, 'Входящий запрос');
Плюсы:
Минусы:
Структурированное логирование:
const bunyan = require('bunyan');
const log = bunyan.createLogger({
name: 'myapp',
streams: [
{ level: 'error', path: '/var/log/myapp-error.log' }
]
});
log.info({ req }, 'Запрос начат');
Плюсы:
Минусы:
Интеграция с системным логгером:
const syslog = require('modern-syslog');
syslog.init('myapp', syslog.LOG_PID, syslog.LOG_LOCAL0);
syslog.log(syslog.LOG_INFO, 'Запуск приложения');
Плюсы:
Минусы:
Пример с MongoDB:
const { MongoClient } = require('mongodb');
const winston = require('winston');
require('winston-mongodb');
const logger = winston.createLogger({
transports: [
new winston.transports.MongoDB({
db: 'mongodb://localhost/logs',
collection: 'app_logs'
})
]
});
Плюсы:
Минусы:
Пример с ELK Stack:
const { Client } = require('@elastic/elasticsearch');
const client = new Client({ node: 'http://localhost:9200' });
async function logToElastic(data) {
await client.index({
index: 'app-logs',
body: {
timestamp: new Date(),
level: 'info',
message: 'Запрос обработан',
...data
}
});
}
Плюсы:
Минусы:
Характеристика | Stateless | Stateful |
---|---|---|
Масштабируемость | Легко горизонтально масштабируется | Требует синхронизации состояния |
Отказоустойчивость | Выше (нет критичного состояния) | Ниже (потеря состояния = проблема) |
Производительность | Предсказуемая | Может быть выше за счет кэша |
Сложность | Проще | Сложнее (нужно управлять состоянием) |
Использование памяти | Минимальное | Зависит от объема состояния |
Используйте уровни логирования:
Контекст важнее сообщений:
// Плохо
logger.error('Ошибка валидации');
// Хорошо
logger.error('Ошибка валидации', {
input: req.body,
rules: validationRules,
userId: req.user.id
});
Разделяйте логи по назначению:
Не логируйте конфиденциальные данные:
Выбор подхода к логированию зависит от масштаба приложения. Для небольших проектов достаточно Winston, для высоконагруженных систем лучше подойдет Pino. В production обязательно используйте структурированные логи (JSON) и централизованное хранение (ELK, Loki). Помните: хорошие логи — это не просто записанные сообщения, а структурированные данные для последующего анализа.