Logs are the first place to look for every 4xx, 5xx or slow request, and custom formats make them far more useful.
NGINX writes two logs.
The error log (error_log path level;) records problems: missing files, upstream failures, configuration warnings. Levels go from debug through info, notice, warn, error up to emerg; the default is error. Upstream errors show the exact cause, such as connect() failed (111: Connection refused) while connecting to upstream.
The access log records every request using a log_format. The predefined combined format contains client address, time, request line, status, body size, referer and user agent. Define your own with variables:
$request_time: total time NGINX spent on the request.$upstream_response_time,$upstream_addr,$upstream_status: what the backend did, essential for latency debugging.$request_id: a unique ID you can also forward to the backend as a header for tracing.
log_format name escape=json '{...}' produces JSON lines that log shippers parse without regexes.
access_log off; disables logging for noisy locations like health checks; access_log ... buffer=32k flush=5s; reduces disk writes on busy servers; a conditional if=$loggable parameter logs only some requests. In containers, the official image links these logs to stdout and stderr.
Example
http {
log_format json escape=json '{'
'"time":"$time_iso8601","ip":"$remote_addr",'
'"req":"$request","status":$status,"bytes":$body_bytes_sent,'
'"rt":$request_time,"urt":"$upstream_response_time",'
'"upstream":"$upstream_addr","id":"$request_id"}';
access_log /var/log/nginx/access.json json buffer=32k flush=5s;
error_log /var/log/nginx/error.log warn;
server {
listen 80;
location = /healthz { access_log off; return 200 "ok\n"; }
location / {
proxy_set_header X-Request-ID $request_id;
proxy_pass http://127.0.0.1:8000;
}
}
}Remember
- error_log for problems, access_log for every request
- Log $request_time and $upstream_response_time to find slowness
- escape=json gives machine-readable logs
Watch out for
- Debugging 502s from the access log alone; the error log says why the upstream failed.