Skip to main content

NGINX

Collect request rate, active connections, upstream health, and error rate metrics from NGINX using nginx-prometheus-exporter (for NGINX open source) or the NGINX Plus API.

Pattern: nginx-prometheus-exporter → Prometheus scrape → xScaler remote_write


Dashboard

Dashboard


Prerequisites

  • NGINX with ngx_http_stub_status_module enabled (included in most builds)
  • Prometheus or Grafana Alloy
  • xScaler tenant credentials

Step 1 — Enable the stub status endpoint

Add the following location block to your NGINX config (e.g. /etc/nginx/conf.d/status.conf):

server {
listen 8080;
server_name localhost;

location /nginx_status {
stub_status;
allow 127.0.0.1;
deny all;
}
}

Reload NGINX:

nginx -s reload

Verify:

curl http://localhost:8080/nginx_status
# Active connections: 5
# server accepts handled requests
# 12 12 20

Step 2 — Run nginx-prometheus-exporter

docker run --rm -d \
--name nginx-exporter \
--network host \
-p 9113:9113 \
nginx/nginx-prometheus-exporter \
--nginx.scrape-uri=http://localhost:8080/nginx_status

Verify:

curl -s http://localhost:9113/metrics | grep nginx_up
# nginx_up 1

Step 3 — Scrape and forward to xScaler

Prometheus

scrape_configs:
- job_name: nginx
static_configs:
- targets: ['localhost:9113']
labels:
instance: web-01

remote_write:
- url: https://euw1-01.m.xscalerlabs.com/api/v1/push
authorization:
credentials: <token>
headers:
X-Scope-OrgID: <tenant-id>

Grafana Alloy

prometheus.scrape "nginx" {
targets = [{"__address__" = "localhost:9113"}]
forward_to = [prometheus.remote_write.xscaler.receiver]
}

prometheus.remote_write "xscaler" {
endpoint {
url = "https://euw1-01.m.xscalerlabs.com/api/v1/push"
authorization {
type = "Bearer"
credentials = "<token>"
}
headers = { "X-Scope-OrgID" = "<tenant-id>" }
}
}

OpenTelemetry Collector

Requires ngx_http_stub_status_module enabled in your NGINX build.

receivers:
nginx:
endpoint: http://localhost/status
collection_interval: 15s

processors:
memory_limiter:
check_interval: 1s
limit_mib: 256
batch:
timeout: 10s

exporters:
otlphttp/xscaler:
endpoint: https://euw1-01.m.xscalerlabs.com
headers:
Authorization: "Bearer <token>"
X-Scope-OrgID: "<tenant-id>"

service:
pipelines:
metrics:
receivers: [nginx]
processors: [memory_limiter, batch]
exporters: [otlphttp/xscaler]

Logs

Collect Nginx access log and error log. Add the following to your Alloy config:

local.file_match "nginx_logs" {
path_targets = [{
__address__ = "localhost",
__path__ = "/var/log/nginx/access.log",
instance = constants.hostname,
job = "integrations/nginx",
}]
}

loki.source.file "nginx_logs" {
targets = local.file_match.nginx_logs.targets
forward_to = [loki.write.xscaler.receiver]
}

loki.write "xscaler" {
endpoint {
url = "https://euw1-01.l.xscalerlabs.com/api/v1/logs/push"

http_client_config {
authorization {
type = "Bearer"
credentials = env("XSCALER_TOKEN")
}
}

headers = { "X-Scope-OrgID" = env("XSCALER_TENANT_ID") }
}
}

Key metrics

MetricDescription
nginx_upExporter reachability (1 = up)
nginx_connections_activeCurrently active connections
nginx_connections_accepted_totalTotal accepted connections
nginx_connections_handled_totalTotal handled connections
nginx_connections_readingConnections reading request
nginx_connections_writingConnections writing response
nginx_connections_waitingKeep-alive idle connections
nginx_http_requests_totalTotal HTTP requests processed

Useful PromQL queries

# Request rate/sec
rate(nginx_http_requests_total[5m])

# Active connections
nginx_connections_active

# Dropped connections rate (accepted - handled)
rate(nginx_connections_accepted_total[5m])
- rate(nginx_connections_handled_total[5m])

# Idle (keep-alive) connections
nginx_connections_waiting

# Connections in flight (reading + writing)
nginx_connections_reading + nginx_connections_writing

Troubleshooting

nginx_up 0

  • Confirm NGINX is running and the stub_status endpoint is accessible: curl http://localhost:8080/nginx_status
  • Check that --nginx.scrape-uri points to the correct host and port

stub_status returns 404

  • Verify ngx_http_stub_status_module is compiled in: nginx -V 2>&1 | grep stub_status
  • Confirm the config block is loaded and NGINX was reloaded after changes