Integration · NGINX

NGINX monitoring: connections, requests, latency and errors

Combine stub_status metrics, access log latency and status codes and OpenTelemetry traces to see how NGINX and the upstreams behind it serve every request.
Obseria apps and capabilities: observability, APM, infrastructure and integrations
Obseria home dashboard with service health, open problems, SLO compliance and ingestion
Obseria trace explorer with span list and span attributes
Overview

Why monitor NGINX with Obseria

Golden signals at the edge

Request rate, error rate from status codes and latency from request_time give you an SLO-ready view of every virtual host.

Proxy versus upstream

upstream_response_time next to request_time shows whether time is spent in NGINX, on the network or in the backend service.

Requests you can follow

With the NGINX OpenTelemetry module, each proxied request becomes a span that continues into the upstream service trace.

Coverage

NGINX components Obseria monitors

  • stub_status. Accepted, handled and current connections by state, plus total requests, via the nginx receiver.
  • Access logs. Status codes, bytes sent, request_time and upstream_response_time parsed from access logs.
  • Error logs. Upstream timeouts, connection refusals and configuration errors from the NGINX error log.
  • Upstreams. Latency and errors per upstream from access log fields and from traces of the backend services.
  • Tracing. Spans for proxied requests from the ngx_otel_module with W3C trace context propagation.
  • Kubernetes ingress. NGINX-based ingress controllers that expose Prometheus metrics, scraped by the Obseria Agent.
At a glance

The NGINX signals that matter

Obseria collects these values automatically and shows them in ready-made dashboards and alerts.

Traffic volume

Shows how many requests your website receives over time, helping you spot peaks, campaigns and unusual drops.

  • nginx.requests

Connection reliability

Tells you whether every incoming visitor is actually served or whether connections are being dropped under load.

  • nginx.connections_accepted
  • nginx.connections_handled

Current activity

Reveals how many visitors are being served right now and how many connections are idle or waiting.

  • nginx.connections_current{state=active}
  • nginx.connections_current{state=reading}
  • nginx.connections_current{state=writing}
  • nginx.connections_current{state=waiting}

Response speed

Shows how long visitors wait for a page and how much of that time is spent in your backend applications.

  • $request_time
  • $upstream_response_time
Show all 9 metrics in detail
MetricUnitWhat it tells you
nginx.requests{requests}Total client requests; its rate is the request throughput.
nginx.connections_accepted{connections}Client connections accepted by NGINX.
nginx.connections_handled{connections}Handled connections; lower than accepted means resource limits were hit.
nginx.connections_current{state=active}{connections}Open client connections including idle keep-alive.
nginx.connections_current{state=reading}{connections}Connections where NGINX is reading the request header.
nginx.connections_current{state=writing}{connections}Connections where NGINX is writing the response; grows when upstreams are slow.
nginx.connections_current{state=waiting}{connections}Idle keep-alive connections waiting for the next request.
$request_timesAccess log variable: total time to serve a request, from first byte read to last byte sent.
$upstream_response_timesAccess log variable: time spent waiting for the upstream response.
Setup

Set up NGINX monitoring in minutes

  1. Step 1

    Enable stub_status

    Expose stub_status on a local-only location such as 127.0.0.1:8080/nginx_status and reload NGINX.

  2. Step 2

    Configure metrics and logs

    Add the nginx receiver and a filelog receiver for access logs to the OpenTelemetry Collector or Obseria Agent.

  3. Step 3

    Add tracing

    Load the NGINX OpenTelemetry module and point it at the local Collector, so proxied requests appear in traces.

Example configuration · YAML
receivers:
  nginx:
    endpoint: http://127.0.0.1:8080/nginx_status
    collection_interval: 10s
  filelog/nginx_access:
    include: [/var/log/nginx/access.log]
    start_at: end
exporters:
  otlphttp:
    endpoint: ${env:OBSERIA_OTLP_ENDPOINT}
    headers:
      Authorization: "Bearer ${env:OBSERIA_TOKEN}"
service:
  pipelines:
    metrics:
      receivers: [nginx]
      exporters: [otlphttp]
    logs:
      receivers: [filelog/nginx_access]
      exporters: [otlphttp]

Out of the box

Dashboards, alerts and SLOs that are ready the moment data arrives.

  • NGINX overview: requests, connections by state
  • Status code breakdown and 5xx rate per host
  • Request time versus upstream response time
  • Alert: 5xx rate above 1% for 5 minutes
  • Alert: handled connections lower than accepted
Guide

NGINX monitoring: what matters

Why NGINX monitoring matters

NGINX is the front door for many applications: web server, reverse proxy, load balancer and TLS terminator. Every user request passes through it, which makes it the best place to measure what users actually experience. It is also a frequent place where problems become visible first, as 502 and 504 responses, even when the cause lies in an upstream service. NGINX monitoring therefore has two jobs: watch NGINX itself, and use it as a vantage point on the services behind it.

Obseria collects NGINX metrics with the nginx receiver of the OpenTelemetry Collector, parses access and error logs with the filelog receiver, and receives spans from the NGINX OpenTelemetry module.

The NGINX metrics that matter

stub_status metrics

The open source stub_status module exposes a small but useful set of counters. nginx.requests gives request throughput. nginx.connections_accepted and nginx.connections_handled should grow at the same rate; if handled falls behind accepted, NGINX ran into a limit such as worker_connections. nginx.connections_current splits open connections into reading, writing and waiting. A growing number of writing connections usually means slow upstreams, because NGINX holds the connection while it waits for the response.

Enable it on a local-only listener:

server {
    listen 127.0.0.1:8080;
    location /nginx_status {
        stub_status;
        allow 127.0.0.1;
        deny all;
    }
}

Access log signals

Latency and errors come from the access log. Add $request_time and $upstream_response_time to your log format. The difference between both tells you whether time is spent in NGINX and the client connection or in the backend. Status codes give the error rate: 5xx for server-side failures, 499 for clients that gave up before a response arrived.

log_format timed '$remote_addr "$request" $status $body_bytes_sent '
                 'rt=$request_time urt=$upstream_response_time';
access_log /var/log/nginx/access.log timed;

Common problems and how to detect them

  • 502 Bad Gateway: the upstream refused the connection or closed it. Check the error log for "connect() failed" and the health of the upstream service.
  • 504 Gateway Timeout: the upstream did not answer within proxy_read_timeout. Upstream response time approaching the timeout is the early warning.
  • Connection limits: handled connections lag accepted connections, or the error log reports "worker_connections are not enough".
  • Rising 499s: clients cancel requests, often because of slow responses or aggressive client timeouts.
  • TLS and certificate issues: handshake errors in the error log; combine them with synthetic checks that test certificate expiry.

Best practices for NGINX monitoring

  1. Keep stub_status on a local listener and never expose it publicly.
  2. Use a structured or key-value access log format with timing fields, so logs parse reliably.
  3. Define SLOs on request success rate and latency per virtual host or route, measured at NGINX.
  4. Propagate W3C trace context from NGINX to upstreams so a slow request can be followed end to end.
  5. Drop health check and static asset log lines in the pipeline if you do not need them, to control log volume.

How Obseria helps with NGINX monitoring

Obseria combines NGINX metrics, parsed access and error logs and traces in Obseria Lake. TopoGraph places NGINX in front of the services it proxies, so a 5xx spike points straight to the affected upstream. Obseria Intelligence correlates error and latency changes with deployments, upstream health and host metrics and explains the likely root cause with a chain of evidence. Obseria Pipeline can drop noisy log lines and mask IP addresses or query strings before storage, and filtered logs cost only ingestion. Dashboards, alerts and SLOs are included, and synthetic checks from 50+ locations add the outside view of your endpoints.

Start with stub_status and the access log on one host, add tracing for the routes that matter most, and roll the same Collector configuration out to every NGINX instance. Within a day you have request rate, error rate and latency per route, ready to turn into SLOs.

NGINX monitoring FAQ

The OpenTelemetry nginx receiver reads stub_status: requests, accepted and handled connections and current connections by state. Latency and status codes come from access logs, and traces from the NGINX OpenTelemetry module.

No. stub_status, access logs and the OpenTelemetry module are all available for open source NGINX.

Add $request_time and $upstream_response_time to your access log format. Obseria parses them so you can chart percentiles per host, route and upstream.

Yes. The NGINX OpenTelemetry module creates spans for proxied requests and propagates W3C trace context to upstream services, which continue the trace.

Yes. Run the Obseria Agent as a DaemonSet to collect container logs and scrape metrics. NGINX-based ingress controllers that expose Prometheus metrics are scraped as well.

Start monitoring NGINX today

Connect NGINX in minutes with OpenTelemetry or the Obseria Agent. Free for 14 days.