Мониторинг HTTP status codes

В чем проблема?

Nginx в своей стандартной комплектации (не Plus) предоставляет мало данных, как я понял. Точнее, наверное, prometheus-nginx-exporter собирает мало метрик. Нужные мне http status codes дефолтный экспортер не собирает, перепробовал многое (заново собирать nginx из исходников ради добавления в него модулей не хотелось) и остановился на другом экспортере, который берет данные из логов доступа (access.log).
Вообще, мне сбор данных из логов кажется тупорылой затеей (если говорить об эффективности и т.д.) но я просто заебался искать подходящее решение - это временное решение, потому что я пока не так сильно шарю.


prometheus-nginxlog-exporter

Repo: https://github.com/martin-helmich/prometheus-nginxlog-exporter

Установка

Есть deb-пакет: https://github.com/martin-helmich/prometheus-nginxlog-exporter/releases

Конфигурация

После установки конфиг /etc/prometheus-nginxlog-exporter.hcl лучше переместить в /etc/prometheus/prometheus-nginxlog-exporter/ (эту папку создать нужно):

mkdir /etc/prometheus/prometheus-nginxlog-exporter/
mv /etc/prometheus-nginxlog-exporter.hcl /etc/prometheus/prometheus-nginxlog-exporter/

Дефолтный конфиг prometheus-nginxlog-exporter.hcl выглядит так:

listen {
  port = 9114
}
 
namespace "nginx" {
  source = {
    files = [
      "/var/log/nginx/access.log"
    ]
  }
 
  format = "$remote_addr - $remote_user [$time_local] \"$request\" $status $body_bytes_sent \"$http_referer\" \"$http_user_agent\" \"$http_x_forwarded_for\""
 
  labels {
    app = "default"
  }
}

Можно сверху задать порт, в секции files указать нужный лог-файл и ниже указать формат данных, который используется в лог-файле, чтобы экспортер мог нормально парсить оттуда метрики.

Погнали в /etc/nginx/nginx.conf, там нужно подправить пару вещей.

log_format status_only "$status";
 
access_log /var/log/nginx/access.log;
access_log /var/log/nginx/http_status_codes.log status_only;
error_log /var/log/nginx/error.log;

Указываю нужный мне формат логов и его название произвольное (здесь status_only), чтобы ссылаться на него ниже. Не собираюсь трогать access.log, поэтому укажу новый путь для нужных мне логов; там, по сути, будут только коды (мне пока больше и не нужно).

Нужно исправить и prometheus-nginxlog-exporter.hcl . Конечный конфиг у меня выглядит так:

listen {
  port = 9114
}
 
namespace "nginx" {
  source = {
    files = [
      "/var/log/nginx/http_status_codes.log"
    ]
  }
 
  format = "$status"
 
  labels {
    app = "default"
  }
}

После изменений нужно подтянуть перезапустить сервисы:

sudo systemctl daemon-reload
 
sudo systemctl restart prometheus-nginxlog-exporter.service
sudo systemctl status prometheus-nginxlog-exporter.service
 
sudo systemctl reload nginx.service
sudo systemctl status nginx.service

Может понадобиться указать в prometheus-nginxlog-exporter.service юзера для доступа к access логам. Проверить, у кого есть доступ к логам можно так:

ls -l /var/log/nginx/

Вот prometheus-nginxlog-exporter.service, где указан юзер, от которого будет запускаться экспортер:

sudo vim /etc/systemd/system/multi-user.target.wants/prometheus-nginxlog-exporter.service
[Unit]
Description=NGINX metrics exporter for Prometheus
After=network-online.target
 
[Service]
User=www-data
ExecStart=/usr/sbin/prometheus-nginxlog-exporter -config-file /etc/prometheus/prometheus-nginxlog-exporter/prometheus-nginxlog-exporter.hcl
Restart=always
ProtectSystem=full
CapabilityBoundingSet=
 
[Install]
WantedBy=multi-user.target

У меня юзер указан www-data ибо на данный момент логи nginx создаются от этого пользователя, но в целом, лог http_status_codes.log, который нам нужен доступен всем для чтения, поэтому юзера можно и не указывать. Когда как.


Тест

Результат можно увидеть сначала в лог-файле:

sudo tail -f /var/log/nginx/http_status_codes.log
 
# output
200
200
404
...
# и т.д.

И на самом порту:

curl http://127.0.0.1:9114/metrics
 
# И там будет среди прочей инфы и комментов нужные нам метрики
nginx_http_response_count_total{app="default",method="",status="200"} 45
nginx_http_response_count_total{app="default",method="",status="404"} 1
# и т.п.
 
# показывается просто код и его кол-во (nginx_http_response_count_total{status="200"} можно в grafana указать и будет визуал)

PromQL

sum(nginx_http_response_count_total{status=~"2.."})

Этот материал использовался в Module 22

monitoringnginx