- Home »

Начало работы с Morgan логгером в Node.js
Если ты настраиваешь серверное приложение на Node.js, то наверняка сталкивался с необходимостью логировать HTTP-запросы. Это не просто хорошая практика — это must-have для любого серьёзного проекта. Логи помогают отследить проблемы, анализировать трафик, мониторить производительность и просто понимать, что происходит с твоим приложением.
Morgan — это один из самых популярных и простых в использовании логгеров для Express.js. Он автоматически записывает информацию о каждом HTTP-запросе: метод, URL, статус код, время выполнения и многое другое. Настроить его можно буквально за пару минут, но возможности кастомизации впечатляют.
В этой статье разберём Morgan от А до Я: как он работает под капотом, как быстро его настроить, какие подводные камни могут встретиться и как выжать максимум из этого инструмента. Если ты уже арендовал VPS или думаешь о переходе на выделенный сервер, то правильное логирование станет твоим надёжным помощником в администрировании.
Как работает Morgan под капотом
Morgan работает как middleware для Express.js — он перехватывает каждый входящий запрос и исходящий ответ, собирает нужную информацию и форматирует её согласно заданному шаблону. Вся магия происходит в нескольких ключевых этапах:
- Перехват запроса — Morgan регистрируется как middleware и получает доступ к объектам req и res
- Сбор метрик — засекает время начала обработки, извлекает данные из заголовков
- Мониторинг ответа — отслеживает момент завершения ответа для подсчёта времени выполнения
- Форматирование и вывод — применяет заданный формат и выводит лог в нужное место
Интересный факт: Morgan использует токены (tokens) для форматирования логов. Каждый токен — это функция, которая извлекает определённую информацию из запроса или ответа. Можно создавать собственные токены для специфических нужд.
Быстрая установка и базовая настройка
Начнём с самого простого. Создаём новый проект или используем существующий:
mkdir morgan-example
cd morgan-example
npm init -y
npm install express morgan
Создаём базовый сервер с Morgan:
const express = require('express');
const morgan = require('morgan');
const app = express();
// Подключаем Morgan с форматом 'combined'
app.use(morgan('combined'));
app.get('/', (req, res) => {
res.send('Hello World!');
});
app.get('/api/users', (req, res) => {
res.json({ users: ['Alice', 'Bob'] });
});
app.listen(3000, () => {
console.log('Server running on port 3000');
});
Запускаем сервер:
node app.js
Теперь каждый запрос будет автоматически логироваться. Попробуй открыть http://localhost:3000
в браузере — увидишь что-то вроде:
::1 - - [25/Dec/2023:10:30:15 +0000] "GET / HTTP/1.1" 200 12 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
Встроенные форматы логирования
Morgan поставляется с несколькими предустановленными форматами. Вот самые полезные:
Формат | Описание | Пример вывода | Рекомендации |
---|---|---|---|
combined | Стандартный формат Apache | 127.0.0.1 – – [25/Dec/2023:10:30:15 +0000] “GET / HTTP/1.1” 200 12 | Для продакшена |
common | Упрощённый Apache формат | 127.0.0.1 – – [25/Dec/2023:10:30:15 +0000] “GET / HTTP/1.1” 200 12 | Базовое логирование |
dev | Цветной формат для разработки | GET / 200 4.567 ms – 12 | Только для разработки |
short | Короткий формат | 127.0.0.1 – GET / HTTP/1.1 200 12 – 4.567 ms | Для отладки |
tiny | Минимальный формат | GET / 200 12 – 4.567 ms | Для лёгкого логирования |
Примеры использования:
// Для разработки - цветной и читаемый
app.use(morgan('dev'));
// Для продакшена - полная информация
app.use(morgan('combined'));
// Для высоконагруженных систем - минимум информации
app.use(morgan('tiny'));
Кастомные форматы и токены
Самое интересное начинается, когда нужно создать собственный формат. Morgan позволяет использовать токены для построения логов:
// Создаём кастомный формат
app.use(morgan(':method :url :status :res[content-length] - :response-time ms'));
// Добавляем собственный токен
morgan.token('id', function getId(req) {
return req.id || 'unknown';
});
// Токен для IP адреса (полезно за прокси)
morgan.token('real-ip', function(req) {
return req.headers['x-forwarded-for'] || req.connection.remoteAddress;
});
// Токен для user agent
morgan.token('user-agent', function(req) {
return req.get('User-Agent');
});
// Используем новые токены
app.use(morgan(':real-ip :id :method :url :status :response-time ms'));
Продвинутый пример с условным логированием:
// Логируем только ошибки
app.use(morgan('combined', {
skip: function (req, res) { return res.statusCode < 400 }
}));
// Логируем только медленные запросы
app.use(morgan('combined', {
skip: function (req, res) {
return res.responseTime < 1000; // меньше 1 секунды
}
}));
Запись логов в файлы
В продакшене логи нужно сохранять в файлы. Вот несколько способов:
const fs = require('fs');
const path = require('path');
// Создаём директорию для логов
const logDir = path.join(__dirname, 'logs');
if (!fs.existsSync(logDir)) {
fs.mkdirSync(logDir);
}
// Создаём поток для записи в файл
const accessLogStream = fs.createWriteStream(
path.join(logDir, 'access.log'),
{ flags: 'a' }
);
// Настраиваем Morgan для записи в файл
app.use(morgan('combined', { stream: accessLogStream }));
Для ротации логов можно использовать rotating-file-stream
:
npm install rotating-file-stream
const rfs = require('rotating-file-stream');
// Создаём ротирующийся файл лога
const accessLogStream = rfs.createStream('access.log', {
interval: '1d', // ротация каждый день
path: path.join(__dirname, 'logs'),
size: '10M', // или при достижении 10MB
compress: 'gzip' // сжимаем старые файлы
});
app.use(morgan('combined', { stream: accessLogStream }));
Интеграция с другими системами логирования
Morgan отлично работает с Winston, Bunyan и другими логгерами:
const winston = require('winston');
// Настраиваем 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' })
]
});
// Создаём поток для Morgan
const stream = {
write: function(message) {
logger.info(message.trim());
}
};
app.use(morgan('combined', { stream }));
Мониторинг производительности
Morgan можно использовать для сбора метрик производительности:
// Токен для размера запроса
morgan.token('req-size', function(req) {
return req.get('content-length') || '0';
});
// Токен для размера ответа
morgan.token('res-size', function(req, res) {
return res.get('content-length') || '0';
});
// Детальный формат для анализа производительности
const performanceFormat = ':date[iso] :real-ip :method :url :status :req-size :res-size :response-time ms';
app.use(morgan(performanceFormat, {
stream: fs.createWriteStream('performance.log', { flags: 'a' })
}));
Безопасность и фильтрация чувствительных данных
Важно не логировать чувствительную информацию:
// Фильтруем чувствительные URL
app.use(morgan('combined', {
skip: function(req, res) {
// Не логируем запросы к админке
return req.url.includes('/admin/');
}
}));
// Кастомный токен с фильтрацией
morgan.token('safe-url', function(req) {
let url = req.url;
// Удаляем токены и пароли из URL
url = url.replace(/([?&]token=)[^&]*/, '$1***');
url = url.replace(/([?&]password=)[^&]*/, '$1***');
return url;
});
app.use(morgan(':method :safe-url :status :response-time ms'));
Альтернативы Morgan
Хотя Morgan отличный выбор, есть и другие решения:
- Winston — мощная система логирования с множеством транспортов
- Bunyan — структурированное логирование в JSON формате
- Pino — очень быстрый логгер с низкими накладными расходами
- express-winston — интеграция Winston с Express
Сравнение производительности показывает, что Morgan один из самых быстрых HTTP-логгеров для Node.js, добавляя минимальные накладные расходы.
Продвинутые кейсы использования
Вот несколько нестандартных способов использования Morgan:
// Логирование в базу данных
const stream = {
write: function(message) {
// Парсим лог и сохраняем в MongoDB/PostgreSQL
const logEntry = parseLogMessage(message);
db.logs.insert(logEntry);
}
};
// Отправка критических ошибок в Slack
app.use(morgan('combined', {
skip: function(req, res) { return res.statusCode < 500; },
stream: {
write: function(message) {
sendToSlack(`🚨 Server Error: ${message}`);
}
}
}));
// Геолокация по IP
morgan.token('country', function(req) {
const ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress;
return geoip.lookup(ip)?.country || 'Unknown';
});
app.use(morgan(':method :url :status :country :response-time ms'));
Автоматизация и DevOps
Morgan логи можно легко интегрировать в CI/CD пайплайны:
// Скрипт для анализа логов
const fs = require('fs');
const readline = require('readline');
async function analyzeAccessLogs() {
const fileStream = fs.createReadStream('access.log');
const rl = readline.createInterface({
input: fileStream,
crlfDelay: Infinity
});
let errorCount = 0;
let totalRequests = 0;
const slowRequests = [];
for await (const line of rl) {
totalRequests++;
if (line.includes(' 5')) errorCount++;
const responseTime = line.match(/(\d+\.\d+) ms/);
if (responseTime && parseFloat(responseTime[1]) > 1000) {
slowRequests.push(line);
}
}
console.log(`Total requests: ${totalRequests}`);
console.log(`Error rate: ${(errorCount/totalRequests*100).toFixed(2)}%`);
console.log(`Slow requests: ${slowRequests.length}`);
}
Для Docker контейнеров можно настроить логирование в stdout:
// В продакшене логи идут в stdout для Docker
const isProduction = process.env.NODE_ENV === 'production';
if (isProduction) {
app.use(morgan('combined')); // логи в stdout
} else {
app.use(morgan('dev')); // цветные логи для разработки
}
Заключение и рекомендации
Morgan — это простой, но мощный инструмент для логирования HTTP-запросов в Node.js приложениях. Его главные преимущества: минимальные накладные расходы, гибкость настройки и отличная интеграция с Express.js.
Рекомендации по использованию:
- Для разработки используй формат 'dev' — он цветной и читаемый
- В продакшене выбирай между 'combined' для полной информации или 'tiny' для высоконагруженных систем
- Обязательно настрой ротацию логов, чтобы они не съели всё место на диске
- Фильтруй чувствительную информацию — токены, пароли, API ключи
- Используй условное логирование для фокуса на важных событиях
- Интегрируй с системами мониторинга и алертинга
Если планируешь развернуть приложение на VPS или выделенном сервере, правильно настроенное логирование станет незаменимым инструментом для мониторинга и отладки. Morgan поможет быстро обнаружить проблемы, проанализировать нагрузку и оптимизировать производительность.
Дополнительную информацию можно найти в официальной документации: https://github.com/expressjs/morgan
В этой статье собрана информация и материалы из различных интернет-источников. Мы признаем и ценим работу всех оригинальных авторов, издателей и веб-сайтов. Несмотря на то, что были приложены все усилия для надлежащего указания исходного материала, любая непреднамеренная оплошность или упущение не являются нарушением авторских прав. Все упомянутые товарные знаки, логотипы и изображения являются собственностью соответствующих владельцев. Если вы считаете, что какой-либо контент, использованный в этой статье, нарушает ваши авторские права, немедленно свяжитесь с нами для рассмотрения и принятия оперативных мер.
Данная статья предназначена исключительно для ознакомительных и образовательных целей и не ущемляет права правообладателей. Если какой-либо материал, защищенный авторским правом, был использован без должного упоминания или с нарушением законов об авторском праве, это непреднамеренно, и мы исправим это незамедлительно после уведомления. Обратите внимание, что переиздание, распространение или воспроизведение части или всего содержимого в любой форме запрещено без письменного разрешения автора и владельца веб-сайта. Для получения разрешений или дополнительных запросов, пожалуйста, свяжитесь с нами.