Log Parser
True\LogParser reads Apache combined-format access logs — plain or .gz compressed — and turns each line into a structured object. It implements Iterator so you can foreach straight over the file without holding the whole thing in memory.
Iterating a log file
use True\LogParser;
$log = new LogParser('/var/log/apache2/access.log');
foreach ($log as $entry) {
echo "{$entry->ip} {$entry->datetime} {$entry->type} {$entry->page} {$entry->code}\n";
}
Rotated logs work the same way — pass a .gz path and the parser decompresses it on the fly:
$log = new LogParser('/var/log/apache2/access.log.2024-04-01.gz');
foreach ($log as $entry) { /* ... */ }
Entry shape
Each entry is an object with these properties:
| Property | Description |
|---|---|
ip | Client IP address. |
datetime | Access time in Y-m-d H:i:s format. |
type | HTTP method (GET, POST, …). |
page | Requested path / resource. |
code | HTTP status code. |
size | Response size in bytes. |
referer | Referer URL. |
client | User-Agent string. |
Common patterns
Top IPs by hit count
$counts = [];
foreach (new LogParser('/var/log/apache2/access.log') as $entry) {
$counts[$entry->ip] = ($counts[$entry->ip] ?? 0) + 1;
}
arsort($counts);
print_r(array_slice($counts, 0, 10, true));
404s with referers
foreach (new LogParser('/var/log/apache2/access.log') as $entry) {
if ($entry->code === '404') {
echo "{$entry->page} <- {$entry->referer}\n";
}
}
Re-parse without recreating
The class also exposes parse($logFile) if you want to load a different file onto the same instance:
$log->parse('/var/log/apache2/access.log.1.gz');