Golden Signals in NGINX
This guide shows how to instrument any NGINX server to expose the 4 Golden Signals, Throughput (rate), Latency, Errors, and Traffic, using access logs and a lightweight log-based exporter.
Prerequisites
NGINX installed and configured.
Access to the
/var/log/nginx/access.log.
Docker or Docker Compose.
Prometheus or OpenTelemetry Collector available.
Grafana for visualization (optional but recommended).
Configure the NGINX log
Step 1: Update the nginx.conf
nginx.conf
Open your nginx.conf
and add the following log format:
log_format main '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" "$http_x_forwarded_for" '
'rt=$request_time '
'urt=$upstream_response_time '
'rlen=$request_length '
'conn=$connection conn_reqs=$connection_requests';
access_log /var/log/nginx/access.log main;
Important: This adds essential fields for observability: request time, status, method, path, response size, among others.
Step 2: Restart NGINX
sudo nginx -t && nginx -s reload
Start the NGINX log exporter
Option A: Docker Compose
services:
nginx_http_metrics:
image: leonardozwirtes/nginx_http_metrics:latest
container_name: nginx_http_metrics
network_mode: host
ports:
- "2112:2112"
environment:
LOG_PATH: /var/log/nginx/access.log # Or the correct path
volumes:
- /var/log/nginx:/var/log/nginx:ro
restart: unless-stopped
labels:
org.label-schema.group: "monitoring"
docker-compose up -d
Option B: Direct Docker
docker run -d \\
-p 2112:2112 \\
-v /var/log/nginx:/logs:ro \\
-e LOG_PATH=/logs/access.log \\
leonardozwirtes/nginx_http_metrics:latest
Configure Prometheus (alternative)
Add to your prometheus.yml:
scrape_configs:
- job_name: 'nginx_http_metrics'
static_configs:
- targets: ['<IP-OU-HOST-DO-EXPORTER>:2112']
Example using Docker Compose (if Prometheus is on the same network):
scrape_configs:
- job_name: 'nginx_http_metrics'
static_configs:
- targets: ['nginx_http_metrics:2112']
Important: Then restart Prometheus.
Integrate with the OpenTelemetry Collector (Better)
Important: If you're already using OpenTelemetry — or want a lighter and more flexible alternative to Prometheus — the Collector is the best option.
Basic example of configuration (otel-collector-config.yaml
):
otel-collector-config.yaml
):receivers:
prometheus:
config:
scrape_configs:
- job_name: 'nginx_http_metrics'
static_configs:
- targets: ['nginx_http_metrics:2112']
exporters:
prometheusremotewrite:
endpoint: <https://mimir.elvenobservability.com/api/v1/push>
service:
pipelines:
metrics:
receivers: [otlp]
exporters: [prometheusremotewrite]
To run the Collector:
otelcol-contrib --config otel-collector-config.yaml
Important: With the Collector, you can send metrics not only to Grafana, Tempo, Loki, or Prometheus — but also to any OTLP-compatible backend, with full control over routes, filters, and transformations.
Access the metrics endpoint
You can test the exporter with:
curl <http://localhost:2112/metrics>
Or access it in the browser:
<http://localhost:2112/metrics>
You will see metrics such as:
http_requests_total
http_duration_seconds_bucket
http_errors_total
http_traffic_bytes_total
Use the ready-made dashboard in Grafana
We created a dashboard ready to visualize all the Golden Signals of NGINX: Grafana Dashboard: NGINX Golden Signals
Included dashboards:
Requests per second
rate(http_requests_total[1m])
Error rate (4xx/5xx)
rate(http_errors_total[1m])
Latency P95
histogram_quantile(0.95, rate(http_duration_seconds_bucket[5m]))
Traffic per route
rate(http_traffic_bytes_total[1m])
Path normalization
To avoid label cardinality explosion, the following rules are applied:
/user/123
→/user/:id
/api/*
→/api
.php
→/:php
.env
→/:env
/admin/*
→/admin
Qualquer path com mais de 5 barras →
/:complex
Summary
Configure nginx logging
Add log_format
ao nginx.conf
Start the exporter
Via Docker ou Docker Compose
Collect the metrics
Via Prometheus ou Collector
Access metrics
View in grafana
Use the Golden Signals dashboard (link above)
Bonus: Coverage of the Golden Signals
Throughput
http_requests_total
Latency
http_duration_seconds
Errors
http_errors_total
Traffic
http_traffic_bytes_total
Last updated
Was this helpful?