Diagnosing "It's Slow": A Log-Based Troubleshooting Walkthrough
Logging & Log Analysis
Chapter 6 · Diagnosing "It's Slow": A Log-Based Troubleshooting Walkthrough
Every chapter so far has built one piece: severity levels, log locations, access/error log fields, response-time logging, cross-log correlation. This chapter puts all of it to work on one realistic ticket, start to finish — the "Apache running slow" scenario this course has referenced since Chapter 1.
The Ticket
"Customers are reporting the checkout page is taking 10+ seconds to load. Started sometime this morning. Nothing else seems affected."
Before anything else: is response time even being logged? Checking the site's Apache config confirms %D was added to the LogFormat months ago — Chapter 4's own prerequisite is already satisfied, so the access log can actually answer a "how slow" question.
Filter the access log for the affected path and scan the response-time field:
Two real findings already: the slow requests are genuinely confirmed (not just a user's impression), and they're not constant — they cluster into short windows, roughly an hour apart, then return to normal.
Checking the error log for the same timestamps — 09:02 through 09:15 — turns up nothing dramatic, but one recurring line stands out precisely because it's routine and repeating in that exact window:
The application layer is confirming the slowness lives somewhere around the database, but not yet why.
Checking system-level activity for the same window via journalctl --since "09:00" --until "09:20" turns up the actual trigger:
Lining the three sources up by timestamp tells a complete, consistent story:
- A cron job named
nightly_backup.shis starting at 09:00, 10:00, and presumably every hour on the hour — despite its name suggesting it should run once, overnight - It drives CPU load sharply upward, visible in the kernel/system log
- Database queries slow down under that load, visible as the Apache
warn-level slow-query notice - The checkout page's own response time spikes to match, visible directly in the access log's
%Dfield
No single log source proved this on its own — the access log proved that it was slow, the error log hinted at where, and the system log finally explained why. Correlated by timestamp, the three together point at one specific, fixable cause: a backup script with a misconfigured hourly schedule, not a nightly one.
Hands-On Exercises
Explain why Step 1 of this walkthrough checks whether %D is configured before doing anything else, referencing what this course covered in Chapter 4.
📄 View solutionExplain what each of the three log sources (access log, error log, system/journal log) individually proved in this walkthrough, and why the full picture needed all three rather than any one alone.
📄 View solutionExplain why this chapter warns against treating the Step 3 slow-query warning as a complete diagnosis on its own, even though it was a real, accurate finding.
📄 View solutionChapter 6 Quick Reference
- Confirm response time is actually logged (Chapter 4) before trying to diagnose "slow" from the access log at all
- The access log's
%D/$request_timefield confirms and quantifies the symptom — proof, not just a user's impression - The error log often hints at where the slowness lives, without fully explaining why
- System-level logs (
journalctl, kernel messages) frequently reveal the actual trigger — resource exhaustion, a misbehaving scheduled job, and similar - Correlate all sources by timestamp before concluding a diagnosis is complete — a single confirmed finding can still be an incomplete answer
- Next chapter: Diagnosing "It's Returning the Wrong Thing" — A Second Troubleshooting Walkthrough