Linux VPS

Web server access log formats: combined, custom and JSON logs

Read every field of the combined log format, add response time and upstream timing, switch to JSON logs, and use one-line commands to find top IPs, slow URLs and errors.

IntermediateLinux VPS3 min read

Every request a web server handles can be written to an access log. Understanding the access log format lets you spot attacks, find slow pages and prove what happened during an outage. This guide explains the standard format, how to add the fields that matter for tuning, and how to query logs from the shell.

Before you start

  • Root access to an Nginx or Apache server. Logs live in /var/log/nginx/, /var/log/apache2/ or /var/log/httpd/.
  • On cPanel, use cPanel → Metrics → Raw Access; see cPanel error and raw access logs.

The combined log format, field by field

203.0.113.7 - - [14/Nov/2026:10:12:01 +0000] "GET /blog/ HTTP/2.0" 200 18342 "https://google.com/" "Mozilla/5.0 ..."
FieldExampleMeaning
Client IP203.0.113.7Visitor (or proxy) address
Ident / user- -Unused / HTTP auth user
Time[14/Nov/2026:10:12:01 +0000]When the request finished
Request lineGET /blog/ HTTP/2.0Method, path, protocol
Status200HTTP status code
Bytes18342Response body size
Refererhttps://google.com/Page that linked here
User-AgentMozilla/5.0 …Browser or bot

Add timing fields

The default format has no timing, which is what you need most when a site is slow.

Nginx

log_format timed '$remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" rt=$request_time urt=$upstream_response_time cache=$upstream_cache_status host=$host';
access_log /var/log/nginx/access.log timed;
  • $request_time: total seconds from first byte read to last byte sent.
  • $upstream_response_time: time PHP-FPM or the backend took. If this is close to request_time, the app is slow, not the network.

Apache

LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %D %{Host}i" timed
CustomLog ${APACHE_LOG_DIR}/access.log timed

%D is the time in microseconds.

Write JSON logs

JSON is easier to ship to log tools and to query with jq:

log_format json escape=json '{"time":"$time_iso8601","ip":"$remote_addr","host":"$host","method":"$request_method","uri":"$request_uri","status":$status,"bytes":$body_bytes_sent,"rt":$request_time,"ua":"$http_user_agent"}';

Useful one-liners

  • Top 10 client IPs:
    awk '{print $1}' access.log | sort | uniq -c | sort -rn | head
  • Most requested URLs returning 404:
    awk '$9==404 {print $7}' access.log | sort | uniq -c | sort -rn | head
  • Requests slower than 2 seconds (with the timed format):
    grep -oP 'rt=\K[0-9.]+' access.log | awk '$1>2' | wc -l
  • Status code summary:
    awk '{print $9}' access.log | sort | uniq -c | sort -rn

Real client IPs behind a proxy

Behind Cloudflare or a load balancer every line shows the proxy IP. Use Nginx's real_ip module or Apache's mod_remoteip with the proxy's address ranges so the first field holds the visitor's IP.

Keep logs under control

Busy sites write gigabytes a day. Make sure logrotate compresses and removes old files (see logrotate guide), and consider disabling access logs for health checks and static assets with access_log off; in those locations.

FAQ: access log format

What is the difference between access and error logs?

Access logs record every request; error logs record problems such as missing files, PHP-FPM failures and config warnings.

Does logging slow the server?

Very little. Use buffer=32k flush=5s in Nginx on very busy sites.

Are IP addresses in logs personal data?

Under GDPR they can be. Keep logs only as long as you need them.

Next steps

Was this guide helpful?

Still stuck?

Ask MdmHost AI for a quick answer, or open a ticket and our team will take a look. We are here 24/7.