Reading Web Server Logs: Apache & Nginx
Logging & Log Analysis
Chapter 4 · Reading Web Server Logs: Apache & Nginx
Chapter 3 found the files. This chapter reads what's actually in them — the access log's field-by-field structure, what HTTP status codes really tell you, a genuinely easy-to-miss gap in the default format, and the error log that fills that gap in. Apache and Nginx are covered together throughout, since their conventional log formats are close enough to read with one shared mental model.
The Access Log: Common & Combined Format
Both Apache and Nginx default to a format descended from the same standard, Common Log Format (CLF), almost always extended in practice to Combined Log Format, which adds two more fields. A single line looks like this:
| Field | Example value | What it means |
|---|---|---|
| Remote host | 192.168.1.10 | The IP address the request came from |
| Identity | - | Almost always a literal dash — rarely used in practice |
| Authenticated user | - | A dash unless the request used HTTP basic authentication |
| Timestamp | [08/Aug/2026:14:32:07 +0100] | When the request was received, including timezone offset |
| Request line | "GET /login HTTP/1.1" | Method, path, and protocol version, together |
| Status code | 500 | The HTTP status code returned — covered in depth below |
| Response size | 1204 | Bytes sent in the response body |
| Referer | "https://example.com/dashboard" | The page the request was linked from, if any (Combined format only) |
| User-agent | "Mozilla/5.0..." | The requesting browser/client's own self-reported identity (Combined format only) |
HTTP Status Codes: Reading the Middle Field
| Range | Category | Common examples |
|---|---|---|
| 2xx | Success | 200 OK |
| 3xx | Redirection | 301/302 (moved, found) |
| 4xx | Client error — the request itself was the problem | 404 Not Found, 401 Unauthorized, 403 Forbidden |
| 5xx | Server error — the server failed to handle a valid request | 500 Internal Server Error, 502 Bad Gateway, 503 Service Unavailable, 504 Gateway Timeout |
That 4xx/5xx split matters for triage: a spike in 404s often means a broken link or a bot scanning for pages that don't exist — rarely a real system problem. A spike in 5xx codes means the server itself is failing to do its job, and is exactly the kind of signal Chapters 6 and 7 build a full diagnostic process around.
The Gap Almost Everyone Assumes Isn't There: Response Time
| Server | Directive to add response time |
|---|---|
| Apache | %D (microseconds) or %T (seconds), added to a custom LogFormat |
| Nginx | $request_time, added to a custom log_format directive |
With %D added, the same request from earlier might look like this — the final field, 4523912, is microseconds, meaning this request took roughly 4.5 seconds:
The Error Log: Where the "Why" Often Lives
The access log tells you what request came in and what status went out. It rarely tells you why a request failed — that's the error log's job.
Both examples describe the same underlying situation — the web server couldn't reach a backend it depends on — from Apache's PHP module and Nginx's own upstream-proxy perspective respectively. Neither the Apache nor the Nginx access log line for this same request would show anything more specific than a 500 or 502; the error log is what actually names the cause.
Reading Both Logs Together
The real technique, used throughout Chapters 6 and 7, is straightforward once both formats are familiar: find the access log line for the problem request, note its exact timestamp, then search the error log for entries at that same moment. The access log confirms that something failed and roughly how; the error log — when the failure produced one — explains why.
Hands-On Exercises
A colleague says "I'll just check the access log to see how slow that request was." Explain why this chapter says that might not be possible, and what needs to be true first.
📄 View solutionAn access log shows a request returned a 404, and a separate request returned a 500. Explain which one is more likely to indicate a genuine server-side problem worth investigating, and why.
📄 View solutionExplain what actually connects a specific access log line to the relevant error log line for the same failed request, given that this chapter says there's no formal link between the two files.
📄 View solutionChapter 4 Quick Reference
- Combined Log Format — host, identity, user, timestamp, request line, status, size, referer, user-agent, in that order
- 2xx success, 3xx redirect, 4xx client error, 5xx server error — a 5xx spike is the one worth real investigation
- Response time is not included by default — Apache needs
%D/%T, Nginx needs$request_time, added explicitly to a custom log format - The error log explains why a request failed; the access log only confirms that it did
- Timestamps are the only link between an access log line and its corresponding error log entry — there's no other formal connection
- Next chapter: Reading Authentication & Login Logs