Введение: Почему вашему TypeScript проекту нужен мониторинг и логирование
Представьте ситуацию: вы запустили крутой сервис на TypeScript. Всё работает идеально... до первого звонка от пользователя: «Сайт тормозит!» или «Данные не сохраняются!». Вы лезете в код, но не можете воспроизвести баг. Знакомо?
TypeScript даёт нам мощную статическую типизацию, но он не защищает от логических ошибок, утечек памяти или неожиданных исключений в рантайме. Именно здесь на сцену выходят мониторинг и логирование. Это не просто «галочка» в чек-листе, а настоящий спасательный круг для разработчика.
В этой статье мы разберём, как правильно настроить мониторинг и логирование в TypeScript приложениях (как на бэкенде с Node.js, так и на фронтенде), какие инструменты выбрать и как не утонуть в море логов. Поехали!
Зачем это нужно? Три главные причины
1. Отладка в реальном времени
Логирование позволяет заглянуть внутрь работающего приложения. Вместо того чтобы гадать, вы видите конкретные значения переменных, стек вызовов и последовательность событий.
2. Производительность
Мониторинг TypeScript приложений помогает отследить «тяжёлые» функции, которые тормозят UI или забивают память. Вы увидите, где приложение тратит больше всего времени.
3. Безопасность и аудит
Логи — это первое, что вы покажете при расследовании инцидента. Кто, когда и какие данные запрашивал? Правильный лог спасёт вашу репутацию.
Инструменты для мониторинга и логирования в TypeScript
Давайте посмотрим, что реально используют в продакшне. Выбор инструмента зависит от того, что вы пишете: бэкенд на Node.js или фронтенд в браузере.
Для бэкенда (Node.js + TypeScript)
- Winston — самый популярный логгер. Гибкий, с кучей транспортов (файл, консоль, удалённый сервер).
- Pino — сверхбыстрый, если производительность критична.
- Morgan — для HTTP-запросов (отлично работает с Express).
Для фронтенда (браузерный TypeScript)
- Sentry — король мониторинга ошибок. Ловит исключения, краши, медленные запросы.
- LogRocket — записывает сессии пользователей + логи.
- Datadog / New Relic — для enterprise-решений.
Настройка логирования в TypeScript: пошаговый гайд
Начнём с классического бэкенда. Установим Winston — он идеально дружит с TypeScript.
Шаг 1: Установка и базовая конфигурация
npm install winston
npm install @types/winston --save-dev
Создадим файл logger.ts:
import winston from 'winston';
const logger = winston.createLogger({
level: 'info',
format: winston.format.combine(
winston.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }),
winston.format.errors({ stack: true }),
winston.format.json()
),
defaultMeta: { service: 'user-service' },
transports: [
new winston.transports.File({ filename: 'error.log', level: 'error' }),
new winston.transports.File({ filename: 'combined.log' }),
],
});
if (process.env.NODE_ENV !== 'production') {
logger.add(new winston.transports.Console({
format: winston.format.simple(),
}));
}
export default logger;
Теперь в любом месте вашего TypeScript кода можно писать:
import logger from './logger';
logger.info('Пользователь успешно зарегистрирован', { userId: 123 });
logger.error('Ошибка подключения к БД', { error: err.message });
Обратите внимание: мы используем winston.format.errors({ stack: true }). Это значит, что при логировании ошибки, стек вызовов будет сохранён — золото для отладки.
Шаг 2: Добавляем контекст с помощью Mapped Diagnostic Context (MDC)
В реальном приложении вам нужно знать, какой пользователь вызвал ошибку. Winston позволяет динамически добавлять контекст через child:
function createUserLogger(userId: number) {
return logger.child({ userId });
}
// Использование:
const userLogger = createUserLogger(42);
userLogger.warn('Попытка доступа к несуществующему ресурсу', { resourceId: 99 });
Теперь каждый лог будет содержать ID пользователя — супер-удобно для мониторинга.
Мониторинг производительности TypeScript: не дайте приложению «упасть»
Логирование — это половина дела. Вторая половина — мониторинг. Следите за метриками: время ответа, загрузка CPU, память.
Собираем метрики вручную (для Node.js)
Используем встроенный модуль perf_hooks и process:
import { performance, PerformanceObserver } from 'perf_hooks';
function measureAsyncDuration<T>(fn: () => Promise<T>, label: string): Promise<T> {
const start = performance.now();
return fn().finally(() => {
const duration = performance.now() - start;
logger.info(`Метрика: ${label}`, { durationMs: duration });
// Здесь можно отправить метрику в Prometheus или Datadog
});
}
// Использование:
const data = await measureAsyncDuration(() => fetchDataFromDB(), 'fetchDataFromDB');
Этот паттерн позволяет отслеживать, какие функции в вашем TypeScript приложении самые медленные.
Подключаем Sentry для автоматического мониторинга ошибок
Sentry — must have для любого продакшена. Он ловит исключения, которые вы забыли обработать, и показывает, на какой строчке кода всё сломалось.
npm install @sentry/node @sentry/tracing
Настройка в app.ts:
import * as Sentry from '@sentry/node';
import * as Tracing from '@sentry/tracing';
Sentry.init({
dsn: 'https://your-dsn@sentry.io/123456',
environment: process.env.NODE_ENV,
tracesSampleRate: 1.0, // В продакшне лучше 0.2
integrations: [
new Sentry.Integrations.Http({ tracing: true }),
new Tracing.Integrations.Express({ app }),
],
});
// Если используете Express, добавьте middleware:
app.use(Sentry.Handlers.requestHandler());
app.use(Sentry.Handlers.tracingHandler());
// И обработчик ошибок в конце:
app.use(Sentry.Handlers.errorHandler());
Теперь любая необработанная ошибка в вашем TypeScript коде улетит в Sentry, и вы получите уведомление на почту или в Telegram.