Read the fields in an Nginx access log

Interpret the combined format, distinguish literal placeholders from variables, and add timing fields that your log parser can reliably consume.

Best practices
Illustration of server operations and log analysis

First identify the active log_format; an access log does not have universal column positions. Nginx's predefined combined format includes the client address, a literal dash, authenticated user, timestamp, request, status, response-body bytes, referrer, and user agent.

Read a combined record

The built-in format has this structure. If you define a similar format yourself, give it a distinct name:

log_format site_combined '$remote_addr - $remote_user [$time_local] '
                         '"$request" $status $body_bytes_sent '
                         '"$http_referer" "$http_user_agent"';

Example:

192.168.1.1 - - [15/Jan/2024:10:30:45 +0800] "GET /api/users HTTP/1.1" 200 1234 "https://example.com/page" "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"
Value Meaning
192.168.1.1 $remote_addr, the effective client address seen by Nginx.
First - A literal placeholder in this format.
Second - $remote_user; no authenticated username is available.
Bracketed timestamp $time_local, including its numeric timezone offset.
Quoted request Method, request target, and protocol; the target may include a query string.
200 $status, the recorded response status.
1234 $body_bytes_sent, excluding response headers.
Quoted referrer $http_referer, supplied by the client when present.
Quoted user agent $http_user_agent, also supplied by the client.

Spaces inside quoted fields make naive whitespace splitting unreliable for general parsing. Missing values and escaped characters need handling too.

Add fields for performance analysis

Define a new format inside http, then reference its name in the desired logging context:

log_format performance '$remote_addr [$time_iso8601] "$request" '
                       '$status $body_bytes_sent '
                       'request_time=$request_time '
                       'upstream_time="$upstream_response_time"';
access_log /var/log/nginx/performance.log performance;

$request_time is overall request-processing time in seconds with millisecond resolution. $upstream_response_time describes upstream response timing and may contain multiple values after retries or internal redirects, or - when unavailable. Do not cast the whole field blindly to one number.

$request_length includes the request line, headers, and body. $http_x_forwarded_for is the received forwarding header, not an independently verified client address. Choose only fields needed for diagnosis; URLs and headers may contain sensitive values.

Send a known request, inspect the raw line, then validate the DataKit log collector parser and units. A parser cannot recover timings that Nginx never wrote.

FAQ

Why is remote_addr a proxy address?

That is normally the direct peer. Configure set_real_ip_from and the appropriate real-IP header only for genuinely trusted proxies. Do not trust arbitrary client-supplied forwarding headers.

Can timestamps use ISO 8601?

Yes: $time_iso8601 is suitable for that. $msec provides an epoch timestamp with millisecond resolution; it is a timestamp, not request duration.

Why are some requests missing?

Inspect access_log off, conditional logging, the selected location, buffering and flush behavior, and the actual destination. A request may be logged in the location where processing ends after an internal redirect.

Reference: Nginx access-log formats.

Get a tailored plan

Contact us

Join the community

Scan with WeChat
to join the community

Try Guance

Start online and pay only for what you use.

Get started

Choose a Guance plan

Code hosting