Skip to content

Мониторинг 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/ (эту папку создать нужно):

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

Дефолтный конфиг prometheus-nginxlog-exporter.hcl выглядит так:
```json (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"
}
}

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

Погнали в **/etc/nginx/nginx.conf**, там нужно подправить пару вещей.
```nginx
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 . Конечный конфиг у меня выглядит так:
```json (hcl вообще-то, ну, он основан на json)
listen {
port = 9114
}

namespace "nginx" {
source = {
files = [
"/var/log/nginx/http_status_codes.log"
]
}

format = "$status"

labels {
app = "default"
}
}

Text Only
После изменений нужно подтянуть перезапустить сервисы:
```bash
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 логам. Проверить, у кого есть доступ к логам можно так:

Bash
ls -l /var/log/nginx/

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

Bash
sudo vim /etc/systemd/system/multi-user.target.wants/prometheus-nginxlog-exporter.service

Systemd
[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, который нам нужен доступен всем для чтения, поэтому юзера можно и не указывать. Когда как.


Тест

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

Bash
sudo tail -f /var/log/nginx/http_status_codes.log

# output
200
200
404
...
# и т.д.

И на самом порту:
Bash
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

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

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

monitoring #nginx