Логирование и отслеживание ошибок
Логирование и отслеживание ошибок
Технический фундамент наблюдаемости
Логирование это часть наблюдаемости системы. Технически полезный лог должен быть:
- структурированным (объект с фиксированными полями);
- консистентным по формату во всех модулях;
- пригодным для фильтрации по
level,operation,requestId; - безопасным по данным (без секретов и персональных полей в открытом виде).
Инженерный стандарт: сначала определи схему лога, потом пиши сообщения.
Почему без логов отладка превращается в угадайку
Ошибка без контекста почти бесполезна. Сообщение "Something went wrong" не говорит, где упало, при каких данных и как часто это повторяется. Логирование превращает хаос в наблюдаемую систему: ты видишь причину, место и последствия сбоя.
Ключевой момент: лог это не просто console.log, а структурированная запись события, которую можно анализировать.
Проверь себя: какая информация в ошибке помогает исправить баг быстрее всего?
Уровни логов: что и когда писать
На практике удобно думать уровнями:
debug- детали для локальной отладки;info- важные шаги сценария;warn- подозрительные, но не критичные ситуации;error- сбои, влияющие на функциональность.
В учебных примерах часто хватает console.error, console.warn, console.log, но привычка разделять уровни нужна уже сейчас.
function parseProfile(raw) {
try {
return JSON.parse(raw);
} catch (error) {
console.error('parseProfile failed', {
message: error.message,
raw,
});
return null;
}
}
Смотри, что важно: мы логируем не только текст ошибки, но и контекст (raw). Иначе потом трудно воспроизвести проблему.
Что должно быть в хорошем логе
Минимальный полезный набор полей:
- название операции (
operation); - сообщение ошибки (
message); - входные данные или их безопасная часть;
- время события;
- идентификатор пользователя/запроса (если есть).
function logError(operation, error, context = {}) {
console.error({
level: 'error',
operation,
name: error.name,
message: error.message,
stack: error.stack,
timestamp: new Date().toISOString(),
context,
});
}
Смотри, что важно: Error плохо сериализуется через JSON.stringify (у него многие поля не перечислимые), поэтому лучше логировать name/message/stack явно.
const e = new Error('boom');
console.log(JSON.stringify(e)); // {}
Новый термин: корреляция логов - связывание записей по общему requestId/traceId, чтобы видеть полный путь запроса через систему.
Проверь себя: почему один и тот же requestId в нескольких логах сильно ускоряет анализ инцидента?
Локальная отладка против продакшен-логирования
В локальной среде ты можешь писать подробные логи и быстро экспериментировать. В проде нужны ограничения:
- не логировать чувствительные данные (
password, токены, полный номер карты); - не спамить логами в циклах без необходимости;
- сохранять единый формат записи.
Здесь часто путаются: "чем больше логов, тем лучше". На практике шумные логи ухудшают диагностику, потому что полезные записи тонут.
Мини-сценарий: ошибка при сохранении профиля
- Пользователь нажал "Сохранить".
- API вернул ошибку валидации.
- UI показывает сообщение "Проверь данные".
- В лог уходит событие
saveProfileFailedсuserId, полем и причиной.
function handleSaveError(error, userId) {
logError('saveProfile', error, { userId });
return 'Не удалось сохранить профиль. Проверь данные и попробуй еще раз.';
}
Дополнительный пример: маскирование чувствительных полей перед логированием.
function maskEmail(email) {
if (typeof email !== 'string' || !email.includes('@')) return '[invalid-email]';
const [name, domain] = email.split('@');
return `${name.slice(0, 2)}***@${domain}`;
}
Мы не показываем внутреннюю техническую ошибку пользователю, но сохраняем достаточно данных для команды.
Отслеживание ошибок во времени
Логирование отвечает на вопрос "что случилось". Отслеживание (monitoring/tracking) добавляет "как часто и где".
Практически это значит:
- считать частоту ошибок по типам;
- смотреть, после какого релиза выросли падения;
- видеть топ проблемных экранов/операций.
Даже простая метрика вроде "ошибок парсинга за час" может раньше заметить деградацию, чем жалобы пользователей.
Проверь себя: почему единичный TypeError может быть случайностью, а 500 таких же за 10 минут - инцидентом?
Частые ошибки новичков
- Логировать только
error.messageбез контекста. - Ловить ошибку и не логировать вообще.
- Логировать слишком чувствительные данные.
- Использовать разный формат логов в каждом файле.
Анти-провал: заранее определи маленький стандарт лога для проекта и придерживайся его везде.
Что будет, если изменить входные данные
Если в parseProfile передать корректный JSON, error-лог не появится. Если передать поломанную строку, получишь одну понятную запись с контекстом, и это поможет воспроизвести баг в пару шагов.
Так ты переходишь от "иногда падает" к "падает при таком входе, в таком месте, с такой причиной".
Краткий итог
- Логирование нужно, чтобы ошибка была наблюдаемой и воспроизводимой.
- Полезный лог содержит контекст, а не только текст исключения.
- Разделяй уровни логов и не создавай шум.
- В проде соблюдай безопасность данных и единый формат.
- Отслеживание динамики ошибок помогает находить проблемы до массовых жалоб.