1. 1
  2. 2
  3. 3
  4. 4
  5. 5

# конспект · шаг 5 из 5

Конспект: логи и формат

выжимка - её можно унести в заметки

Решение №6: что записать в лог - и как этим потом пользоваться.

Две ленты

Лента Когда пишется На что отвечает
access_log одной строкой после ответа что случилось
error_log по ходу дела, сколько угодно строк почему

Уровни error_log: debug info notice warn error crit alert emerg. Заданный уровень означает «этот и всё, что серьёзнее». Объяснения 400 и 499 идут на info, отказ по лимиту - на error, беды всего сервера - на alert.

Строка combined по костям

Кусок Переменная Что означает
192.168.1.44 $remote_addr кто подключился к nginx
[07/Aug/2026:…] $time_local момент окончания обработки
"GET /catalog/42 HTTP/1.1" $request метод, URI, версия
200 $status код ответа
4821 $body_bytes_sent байт тела; весь ответ - $bytes_sent
"https://shop.local/" $http_referer откуда пришли
"Mozilla/5.0 …" $http_user_agent чем пришли

Позиции для awk: $1 - адрес, $7 - URI, $9 - код. Верны только для combined.

Что стоит добавить в свой формат

Переменная Зачем
$host без него строки пяти сайтов неразличимы
$request_time сколько заняло всё, включая чтение запроса и отдачу
$upstream_response_time сколько думал и отдавал бэкенд
$upstream_status, $upstream_addr кто ответил и каким кодом
$upstream_cache_status HIT/MISS/EXPIRED - иначе кеш не отладить
$request_id связать строку в логе с логом приложения

$request_time против $upstream_response_time - главная пара раздела: разность - это всё, что бэкенда не касается. Замер на стенде: rt=4.242 при urt=0.088 - виноват канал до клиента.

Запятая в upstream-полях означает повторную попытку. us=502, 200 при $status 200 значит, что первый сервер отказал, а пользователь этого не заметил.

Четыре команды

$  команда
nginx -T | grep -E "access_log|error_log"                    # где логи на самом деле
tail -f /var/log/nginx/access.log                            # смотреть вживую
tail -n 10000 access.log | awk '{print $9}' | sort | uniq -c | sort -rn   # коды ответов
awk '$9 == 404 {print $7}' access.log | sort | uniq -c | sort -rn | head  # чего не хватает

Ловушки джокера

  • $remote_addr за прокси - это адрес прокси. Настоящий клиент - в X-Forwarded-For; либо логируй его, либо настрой realip.
  • Лог пишется после ответа, поэтому «висящий» запрос в логе не виден вообще, а время в строке - момент окончания, а не начала.
  • log_format живёт только в http. В server он даёт "log_format" directive is not allowed here ещё до старта.
  • access_log на уровне вытесняет унаследованный. Объявил свой в server - общий из http в этот сервер писать перестал. Несколько директив на одном уровне пишут во все назначения, off выключает логирование уровня.
  • JSON без escape=json не JSON. Кавычка в User-Agent превращается в \x22, и парсер спотыкается. А upstream-поля обязаны быть в кавычках: без них строка ломается на каждом запросе, не ушедшем на бэкенд ("urt":,).
  • buffer= и flush= задерживают запись. С flush=5s своя строка появится через пять секунд, а при жёстком падении процесса потеряется.
  • После logrotate нужен nginx -s reopen. Иначе nginx продолжает писать в переименованный файл, а новый не создаётся вовсе.

Комментарии

Пока нет комментариев. Будь первым!

Оставить комментарий

Комментарий появится после проверки. Email не публикуется. Войти, чтобы не вводить имя каждый раз.