Миф: логи нужны только когда что-то сломалось
«Логи? Ну, стоят где-то, ошибки пишут — если что-то упадёт, посмотрим». Так думает большинство команд, и это не глупость: логи действительно спасают в момент сбоя. Проблема в слове «только». Если логирование настроено исключительно как инструмент на чёрный день, вы теряете как минимум четыре других способа использовать те же данные — и часто узнаёте об этом уже тогда, когда данных для них попросту не осталось.
Содержание
- Рациональное зерно: почему миф вообще возник
- Проактивное обнаружение деградации: паттерн виден раньше алерта
- Логи как основа для метрик и алертинга
- Forensics: расследование инцидентов безопасности, а не только сбоев
- Аудит и комплаенс: логи как доказательная база
- Как настроить логирование заранее — под разные сценарии
Рациональное зерно: почему миф вообще возник
Первое знакомство большинства инженеров с логами происходит именно в кризисный момент: сервис упал, нужно понять почему, и единственный источник правды — файл с текстом ошибок. journalctl -u myapp --since "20 min ago" | grep -i error, потом tail -f /var/log/nginx/error.log, потом облегчение, когда строчка с трейсбеком найдена. Этот опыт закрепляется быстро и прочно: логи = то, что читают после того, как всё сломалось.
Дальше это убеждение материализуется в конфигурации. Типичная минимальная настройка выглядит так: уровень логирования error или warn (чтобы «не засорять диск»), ротация раз в неделю с удалением через 2-4 недели, хранение только локально на том же сервере, никакой структуры — обычный текст, который человек читает глазами через grep. Для единственной задачи «найти причину вчерашнего падения» этого действительно достаточно. Проблема в том, что у логов есть ещё как минимум четыре задачи, и под каждую из них такая конфигурация — почти гарантированный отказ в тот момент, когда данные понадобятся.
Проактивное обнаружение деградации: паттерн виден раньше алерта
Алерт срабатывает, когда метрика пересекла порог. Но до этого порога деградация обычно нарастает постепенно, и она видна именно в логах — если есть история, с чем сравнивать.
Классический пример: p95 времени ответа /checkout растёт со 180 мс до 220 мс, потом до 260 мс — каждое отдельное значение ещё не бьёт по алерту «латентность выше 500 мс», но тренд уже говорит, что через неделю-другую порог будет пробит. Такой тренд не выловить одним запросом «покажи текущее состояние» — нужна возможность сравнить сегодняшний день с прошлой неделей:
# Loki: медиана времени ответа за последние 7 дней с шагом в час
quantile_over_time(0.95,
{app="checkout"} | json | unwrap request_time [1h]
)
Похожая логика работает и для менее явных сигналов: постепенный рост доли повторных запросов (retry) от фронтенда, рост числа неудачных попыток авторизации, размазанных по множеству разных IP (ранний признак credential stuffing, а не грубого перебора с одного адреса), учащение предупреждения, которое раньше встречалось раз в сутки, а теперь — раз в час. Ни один из этих паттернов не превращается в инцидент за одну секунду — они накапливаются днями и неделями.
Если под рукой нет централизованного сборщика логов, тот же принцип работает и в упрощённом виде — cron-скрипт, который раз в сутки считает распределение кодов ответа и складывает в CSV для сравнения:
#!/bin/bash
# /usr/local/bin/daily-status-report.sh
DATE=$(date +%F)
awk '{print $9}' /var/log/nginx/access.log \
| sort | uniq -c | sort -rn \
>> /var/log/reports/status-codes-${DATE}.txt
Ключевое условие для обеих схем — глубина хранения. Если ротация настроена на «3 дня и удалить», сравнивать сегодня попросту не с чем: тренд длиной в три дня почти не отличим от шума.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверЛоги как основа для метрик и алертинга
Часть метрик, на которые настроены ваши алерты, не собирается напрямую — она вычисляется из логов. Простой пример: «доля успешных оформлений заказа» или «время обработки задачи в очереди» редко существует как готовый счётчик где-то в коде — обычно это парсинг лог-строк с последующей агрегацией.
Promtail (агент Grafana Loki) умеет извлекать метрики прямо из потока логов на стадии pipeline, ещё до того, как строка попадёт в хранилище:
pipeline_stages:
- regex:
expression: '^(?P<remote_addr>\S+) .* "(?P<method>\S+) (?P<path>\S+).*" (?P<status>\d{3}) (?P<bytes>\d+) .* (?P<request_time>[\d\.]+)$'
- metrics:
http_requests_total:
type: Counter
source: status
config:
match_all: true
action: inc
http_request_duration_seconds:
type: Histogram
source: request_time
config:
buckets: [0.1, 0.3, 0.5, 1, 3, 5]
Похожий подход есть и у связки Prometheus + mtail/grok_exporter: они «сканируют» текстовые логи и превращают совпадения по паттерну в счётчики и гистограммы, которые дальше уходят в стандартный пайплайн алертинга.
Здесь и кроется практическая ловушка «логи только для отладки»: если формат строки логов никогда не проектировался под парсинг — вперемешку текст на русском и английском, непостоянный порядок полей, время без таймзоны, — то регулярное выражение для извлечения метрики превращается в хрупкий костыль, который ломается при любом изменении формата вывода. Разница между логами, метриками и трейсами и то, как они дополняют друг друга, подробно разобрана в статье логи, метрики и трассы: чем отличаются — короткий вывод оттуда: метрики и алерты в реальных системах почти никогда не существуют полностью независимо от логов, они на них опираются.
Forensics: расследование инцидентов безопасности, а не только сбоев
Сбой приложения оставляет стектрейс. Взлом оставляет злоумышленника, у которого есть мотив этот стектрейс — точнее, любые следы своей активности — стереть. Это принципиально другая задача по сравнению с «найти причину бага», и минимальный набор «error-логи за последнюю неделю» для неё почти бесполезен.
При разборе инцидента безопасности обычно нужно восстановить цепочку: кто зашёл, когда, с какого IP, что выполнил, к каким файлам обратился, куда переместился дальше по сети. Это совсем другой набор источников:
# кто и откуда подбирал пароль по SSH
grep "Failed password" /var/log/auth.log | awk '{print $(NF-3)}' | sort | uniq -c | sort -rn | head
# успешные входы за последние сутки
grep "Accepted" /var/log/auth.log | awk '{print $1,$2,$3,$9,$11}'
# что менялось в критичных файлах, если настроен auditd
ausearch -f /etc/passwd -ts today
Два условия делают эти данные пригодными для расследования — и оба обычно отсутствуют в конфигурации «на всякий случай». Во-первых, нужен auditd или аналог, который пишет не просто «ошибка приложения», а системные события: кто запустил процесс, кто прочитал файл, кто изменил права. Во-вторых, логи должны быть защищены от изменения тем, у кого есть root на скомпрометированном сервере, — иначе злоумышленник с привилегированным доступом просто вычистит нужные строки перед уходом. Практический способ такой защиты — отправка логов на отдельный сервер сразу в момент записи (rsyslog/Promtail в push-режиме) и/или append-only хранение. Это разобрано отдельно в статье как хранить логи, чтобы их нельзя было переписать.
Аудит и комплаенс: логи как доказательная база
Отдельная категория, где логи нужны не разработчику и не безопаснику, а внешнему проверяющему. Если сайт обрабатывает персональные данные, попадает под 152-ФЗ, платёжные данные — под требования уровня PCI DSS, а данные клиентов из ЕС — под GDPR, то в какой-то момент возникает вопрос «кто и когда имел доступ к записи такого-то клиента» — и на него должен быть ответ, подкреплённый логами, а не памятью сотрудника.
Требования здесь не про «побольше текста», а про конкретные поля и конкретные сроки: кто выполнил действие (учётная запись, а не общий сервисный аккаунт), когда, к какому объекту данных, какого рода операция (чтение, изменение, удаление). Конфигурация «error-уровень плюс две недели хранения» не отвечает почти ни на один из этих вопросов: обычные пользовательские действия там просто не пишутся, а даже если бы писались — данные истекли задолго до запроса аудитора. Что конкретно и на какой срок стоит хранить с точки зрения закона, без придумывания цифр от себя, разобрано в статье что хранить в логах по закону.
Для компаний с несколькими серверами и требованием единой картины событий обычно на этом этапе появляется SIEM-подход — централизованный сбор логов со всей инфраструктуры в одно место с контролем доступа к самим логам (не каждый, кто читает логи приложения, должен иметь доступ к логам аутентификации).
Как настроить логирование заранее — под разные сценарии
Если логи должны работать не только на отладку, конфигурировать их «чтобы было, если сломается» недостаточно — нужно заранее решить, под какие пять сценариев вы вообще пишете данные, потому что требования у них разные:
| Сценарий | Что реально нужно от логов | Типичная ошибка «настройки на всякий случай» |
|---|---|---|
| Реактивная отладка сбоя | Несколько часов истории, уровень warn/error | Обычно единственное, что вообще настроено |
| Проактивное обнаружение деградации | Недели истории, возможность сравнивать тренды | Ротация на 1-3 дня — сравнивать не с чем |
| Метрики и алертинг | Устойчивый парсируемый формат, поля вроде status/request_time | Неструктурированный текст, формат меняется без предупреждения |
| Forensics при инциденте | auditd/аудит-логи, защита от переписывания, месяцы хранения | Только логи приложения, всё локально и без защиты |
| Аудит и комплаенс | Who-did-what-when по каждому объекту данных, годы хранения по регламенту | Пользовательские действия вообще не логируются |
Практический список того, что стоит сделать на старте проекта, а не после первого запроса от аудитора:
- Структурированный формат с самого начала. JSON вместо произвольного текста — это разница между «grep и молитва» и «одна строка LogQL/jq через год». Пример для nginx:
log_format json_combined escape=json
'{'
'"time":"$time_iso8601",'
'"remote_addr":"$remote_addr",'
'"request":"$request",'
'"status":$status,'
'"request_time":$request_time,'
'"upstream_response_time":"$upstream_response_time",'
'"request_id":"$request_id"'
'}';
access_log /var/log/nginx/access.json.log json_combined;
- Request ID сквозь весь стек. Один идентификатор, проброшенный от балансировщика до фонового воркера, превращает «раскиданные по десяти файлах строки» в одну цепочку событий — критично и для отладки, и для forensics.
- Явное разделение уровней логирования по назначению, а не только по серьёзности: технический debug/info/warn/error отдельно, а события безопасности (вход, смена пароля, доступ к чувствительным данным) — отдельным потоком с собственным сроком хранения, который обычно длиннее.
- Централизация с самого начала, а не «когда серверов станет пять». Даже с одним VPS разумно сразу поднять Loki или Graylog рядом, а не хранить логи только локально — иначе при компрометации сервера теряются и данные для расследования этой же компрометации.
- Многоуровневое хранение: горячие данные (недели) — на быстром диске для повседневного анализа, холодный архив (месяцы-годы, по требованиям закона) — в сжатом виде на более дешёвом хранилище.
- Контроль доступа к самим логам. Кто может читать логи аутентификации — не то же самое, что кто может читать логи приложения; кто может их удалять — отдельный, ещё более узкий список.
Ретроактивно донастроить всё это тяжелее, чем кажется: пока не было структуры и request ID, старые логи не переиндексировать задним числом, а пока не было централизации — расследовать инцидент месячной давности по логам, которых уже физически нет, невозможно в принципе. Именно поэтому вопрос «а что мы вообще будем делать с этими данными кроме отладки» стоит закрыть до того, как проект попадёт под реальный аудит или реальную атаку — практический разбор того, какие события фиксировать заранее и почему это откладывают до последнего, есть в статье логи не пишут, кто что сделал — настраиваем заранее.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверНужны сами нейросети для контента?
Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.
Частые вопросы
Разве расширенное логирование не увеличивает нагрузку на диск и бюджет?
Да, увеличивает, и это нужно закладывать в планирование ресурсов заранее, а не как сюрприз после роста трафика. Конкретные цифры сильно зависят от трафика и выбранного стека, поэтому ориентируйтесь на порядок величины, а не на чужой прайс, и закладывайте запас при выборе конфигурации сервера.
С чего начать, если сейчас логи настроены только «на случай сбоя»?
С малого: перевести access-логи в структурированный формат (JSON), добавить request ID, увеличить срок хранения хотя бы до нескольких недель и вынести хранение логов аутентификации на отдельный сервер. Это не требует немедленной миграции на полноценный SIEM, но закрывает большинство сценариев из статьи.
Обязательно ли использовать Loki/Graylog, или можно обойтись файлами и cron-скриптами?
Для небольшого проекта cron-скрипты с awk/grep действительно закрывают базовые задачи анализа трендов. Но forensics и комплаенс почти всегда требуют централизации и защиты от переписывания — их на голых текстовых файлах на одном сервере обеспечить сложно.
Сколько именно хранить логи для соответствия закону?
Единого числа для всех случаев нет — срок зависит от типа данных и применимого регламента (152-ФЗ, отраслевые требования, договорные обязательства с клиентом). Конкретика по типам логов и срокам разобрана в статье про хранение логов по закону, ссылка выше.
Что делать в первую очередь при ограниченном бюджете?
Приоритет обычно такой: защита от переписывания логов аутентификации (дёшево — просто отправлять их на другой сервер по syslog), затем структурированный формат (бесплатно, только время на конфигурацию), и только потом — полноценная централизованная система вроде Loki, если бюджет позволяет отдельный сервер под неё.
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →