Логи, мониторинг и отладка Nginx
Лог — это чёрный ящик сервера. Когда что-то идёт не так (а оно пойдёт), именно логи Nginx первыми расскажут правду.
«Не знаешь, почему 502? Открой error.log. Не знаешь, кто тебя долбит? Посчитай IP в access.log. Ответ почти всегда там.»
Прод без наблюдаемости — это полёт вслепую. Nginx ведёт два основных лога и умеет отдавать базовые метрики. Научимся их читать и настраивать под себя.
Два главных лога
http {
access_log /var/log/nginx/access.log; # каждый запрос
error_log /var/log/nginx/error.log warn; # ошибки и предупреждения
}
access.log пишет каждый запрос: кто, когда, что, какой код ответа. error.log — проблемы: недоступный бэкенд, ошибки конфигурации, отказы. Уровень (warn, error, info, debug) задаёт подробность; на проде обычно warn или error.
Свой формат лога
log_format main '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'rt=$request_time uct=$upstream_connect_time '
'urt=$upstream_response_time';
access_log /var/log/nginx/access.log main;
Переменные вроде $request_time (полное время запроса) и $upstream_response_time (сколько думал бэкенд) бесценны для поиска медленных мест: видно, тормозит сам бэкенд или сеть до него.
Статус-страница
location /nginx_status {
stub_status;
allow 127.0.0.1; # только локально
deny all;
}
stub_status отдаёт базовые счётчики: активные соединения, принято/обработано запросов, число в состояниях reading/writing/waiting. Это скармливают системам мониторинга.
Распарсим лог-строку на Python
line = '203.0.113.7 - - [10/Oct/2025:13:55:36 +0000] "GET /api/users HTTP/1.1" 200 1340'
import re
m = re.match(r'(\S+) \S+ \S+ \[([^\]]+)\] "(\S+) (\S+) [^"]+" (\d+) (\d+)', line)
if m:
ip, when, method, path, status, size = m.groups()
print("IP: ", ip)
print("Время: ", when)
print("Метод: ", method, path)
print("Статус:", status, "| Размер:", size, "байт")
if status.startswith("5"):
print(" -> ВНИМАНИЕ: серверная ошибка!")
else:
print(" -> запрос успешен")
Попробуй сам ▶ Так выглядит разбор одной строки access.log. Накрутив подсчёт по IP или по статусам, ты быстро находишь, кто шлёт больше всех запросов или сколько у тебя пятисоток.
Как работает под капотом
Nginx пишет в лог в конце обработки запроса. Чтобы запись не тормозила воркер на медленном диске, есть буферизация (buffer=) и условное логирование (if=) — например, не писать успешные ответы статики. После ротации логов (logrotate переименовывает файл) Nginx надо сказать переоткрыть дескрипторы: nginx -s reopen (сигнал USR1) — иначе он продолжит писать в уже переименованный/удалённый файл, и место на диске «утечёт».
Частые ошибки
- Игнорировать error.log при отладке. Самая частая ошибка новичка — гадать вместо того, чтобы посмотреть в лог ошибок.
- Не настроить ротацию. access.log без ротации съест весь диск за недели.
- Логировать всю статику. Каждая иконка в лог — гигабайты шума;
access_log offдля ассетов. - Открыть
stub_statusнаружу. Внутренние метрики не для всего интернета — ограничь по IP.
Best practices
- Кастомный
log_formatс$request_timeи$upstream_response_time— для поиска тормозов. - Ротация через logrotate +
nginx -s reopenпосле неё. stub_statusтолько для localhost/мониторинга.- Отправляй логи в централизованную систему (ELK, Loki) на нагруженных проектах.
От сырых логов к ответам на вопросы
Логи ценны не сами по себе, а тем, на какие вопросы они отвечают. «Почему сайт медленный?» — добавь в log_format поля $request_time и $upstream_response_time и сравни их: если первое большое, а второе маленькое — тормозит сеть до клиента или сам Nginx; если оба большие — виноват бэкенд. «Кто устроил наплыв?» — посчитай запросы по $remote_addr за период. «Откуда поток 500-х?» — отфильтруй по статусу и посмотри, какие URL их дают. Один продуманный формат лога превращает Nginx в источник наблюдаемости, а не просто в журнал.
На масштабе сырые текстовые логи на диске перестают справляться — их физически тяжело читать глазами, и они занимают много места. Тогда логи отправляют в централизованные системы: связку Elasticsearch + Kibana (ELK), Grafana Loki, облачные сервисы. Туда же стекаются метрики со stub_status (а в продвинутых сборках — с модулей расширенной статистики), и поверх строят дашборды и алерты: «доля 5xx превысила 1% — разбуди дежурного». Но даже без тяжёлой инфраструктуры базовая гигиена обязательна: настрой ротацию логов через logrotate (иначе диск переполнится за недели), не логируй каждую иконку, и помни про nginx -s reopen после ротации. Наблюдаемость — это то, что отличает «работает на моей машине» от настоящего продакшена, где ты узнаёшь о проблеме из дашборда раньше, чем из жалоб пользователей.
Итоги
access.log фиксирует каждый запрос, error.log — проблемы; кастомный log_format с таймингами помогает находить узкие места, а stub_status отдаёт базовые метрики. Не забывай про ротацию и reopen. Логи — первый инструмент диагностики. В финальном уроке соберём всё изученное в один продакшен-готовый конфиг.