GrepBoardLog

Drop log files anywhere

Files, whole folders and .gz archives. Or press Ctrl+V to paste text.

Apache access and error logs, field by field

Drop an Apache access_log or error_log here to get status codes, error paths, top clients and, if the format has %D, response time percentiles. The log stays in your browser.

This page covers the common and combined formats from mod_log_config, how to log response time, how to read a 2.4 error log line, and one-liners for the server.

common and combined

mod_log_config documents these format strings. The third one is combined plus %D, the request duration in microseconds, appended at the end:

LogFormat "%h %l %u %t \"%r\" %>s %b" common
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-agent}i\"" combined
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-agent}i\" %D" combined_time
CustomLog logs/access_log combined_time

An access log line in combined_time:

198.51.100.7 - - [18/Oct/2026:10:02:31 +0000] "GET /report.php?id=8 HTTP/1.1" 500 612 "-" "Mozilla/5.0" 30001544
awk fieldDirectiveIn the exampleMeaning
$1%h198.51.100.7Remote host. The IP address, because HostnameLookups is Off by default; with lookups on, a host name.
$2%l-Remote logname from identd. A dash unless mod_ident is loaded and IdentityCheck is on.
$3%u-Authenticated user. Can be bogus when the status is 401.
$4 $5%t[18/Oct/2026:10:02:31 +0000]Time the request was received, with the offset from GMT.
$6 $7 $8\"%r\""GET /report.php?id=8 HTTP/1.1"First line of the request.
$9%>s500Final status. %s would log the status of the original request when it was internally redirected.
$10%b612Response size without headers. In CLF style: a dash instead of 0 when no bytes were sent.
$11\"%{Referer}i\""-"Referer request header (combined only).
$12 …\"%{User-agent}i\""Mozilla/5.0"User-Agent header (combined only). Contains spaces; split on the double quote to get it whole.
last%D30001544Time taken to serve the request, in microseconds. 30001544 µs is 30.0 seconds.

Response time: %D, %T and %{UNIT}T

DirectiveUnitNotes
%DmicrosecondsThe one to use for percentiles.
%TsecondsWhole seconds, so everything under one second logs as 0. Fine for spotting 30-second timeouts, useless for p99 of a fast API.
%{ms}TmillisecondsAlso %{us}T (same as %D) and %{s}T (same as %T). Available in 2.4.13 and later.
%I / %ObytesBytes received and sent including headers. Needs mod_logio.

Put the time at the end of the format, after the User-Agent, so every combined field keeps its position and $NF is always the duration. The board detects the number at the end and reads it as %D or %T.

It is the time taken to serve the request, so for a proxied or FastCGI request it includes the time the backend took. If %D is high on PHP or proxy paths, the next place to look is the error log at the same second.

The 2.4 error log

The error log layout is set by ErrorLogFormat. With the default, a line looks like this:

[Sun Oct 18 10:04:30.654321 2026] [core:error] [pid 4123:tid 140230300] [client 198.51.100.7:41900] AH00124: Request exceeded the limit of 10 internal redirects due to probable configuration error.
PartIn the exampleMeaning
time[Sun Oct 18 10:04:30.654321 2026]Date and time with microseconds.
module:level[core:error]Module that wrote the message and its severity.
process[pid 4123:tid 140230300]Process id and, with a threaded MPM, thread id.
client[client 198.51.100.7:41900]Client address and port, when the message is about a request.
messageAH00124: Request exceeded …Message, usually starting with an AH code that identifies it.

Counting by module:level and by AH code is the fastest way to see what changed: one new AH code appearing thousands of times is usually the incident.

Apache 2.2 error lines have no module or pid part ([time] [error] [client …] message); the board reads both.

What the board shows for Apache

  • Status codes, where errors happen, top paths, top client IPs, who is calling, bytes by path.
  • Latency distribution and slowest paths when %D or %T is present.
  • A per-minute timeline you can drag; every card and the raw lines follow the selection.
  • Scanner probes: requests for wp-login.php, .env, .git/ and similar.
  • For the error log: lines per module:level, AH codes, client addresses and a timeline.

Shell one-liners for Apache logs

Tested against a sample combined log with %D appended and a 2.4 error log. File names follow the RHEL-family default (access_log, error_log); Debian and Ubuntu use access.log and error.log.

  • Status code distribution.

    awk '{print $9}' access_log | sort | uniq -c | sort -rn
  • Clients with the most requests.

    cut -d' ' -f1 access_log | sort | uniq -c | sort -rn | head
  • Which paths get 4xx, and which code.

    awk '$9 ~ /^4/ {print $9, $7}' access_log | sort | uniq -c | sort -rn | head
  • Five slowest requests in milliseconds, from %D.

    awk '{printf "%.1f ms %s\n", $NF/1000, $7}' access_log | sort -rn | head -5
  • p95 response time from %D (nearest-rank).

    awk '{print $NF}' access_log | sort -n | awk '{a[NR]=$1} END {i=int(NR*0.95); if (i<NR*0.95) i++; printf "%.1f ms\n", a[i]/1000}'
  • Average time and request count per path.

    awk '{s[$7]+=$NF; n[$7]++} END {for (p in s) printf "%.1f ms %d %s\n", s[p]/n[p]/1000, n[p], p}' access_log | sort -rn
  • Requests per minute.

    cut -d[ -f2 access_log | cut -d: -f1-3 | uniq -c
  • Total response bytes (%b logs a dash for zero, so skip it).

    awk '$10 != "-" {s+=$10} END {printf "%.1f KiB\n", s/1024}' access_log
  • Error log: lines per module:level.

    grep -oE '^\[[^]]+\] \[[a-z_0-9]+:[a-z0-9]+\]' error_log | awk '{print $NF}' | sort | uniq -c | sort -rn
  • Error log: most frequent AH message codes.

    grep -oE 'AH[0-9]{5}' error_log | sort | uniq -c | sort -rn | head
  • Error log: which client addresses trigger errors.

    grep -oE '\[client [0-9a-f.:]+' error_log | awk '{print $2}' | sed -E 's/:[0-9]+$//' | sort | uniq -c | sort -rn | head

FAQ

What is the difference between %D and %T?

%D is the time to serve the request in microseconds; %T is the same time in whole seconds. Use %D, or %{ms}T on 2.4.13 and later, if you want percentiles.

Why does %b show a dash?

%b uses the Common Log Format convention: a dash instead of 0 when no body bytes were sent, for example on a 304. %B logs 0 instead.

What is the difference between %s and %>s?

For an internally redirected request, %s is the status of the original request and %>s is the final status. Access logs normally use %>s.

Why is the first field a host name instead of an IP?

HostnameLookups is on. It is off by default; with it on, httpd does a reverse DNS lookup per request, which is slow and makes the field harder to group.

Where are the Apache logs?

It depends on the build and distribution: /var/log/httpd/ on the RHEL family and /var/log/apache2/ on Debian and Ubuntu are common. The CustomLog and ErrorLog directives in the configuration are the authority.

Can it read the Apache 2.2 error log?

Yes. The older layout without the module and pid parts is detected too.

Does it work with virtual host formats like %v?

A format that adds fields in front of %h shifts every position. Use the Format tab to label the fields once and save the recipe.

🔒 Nothing leaves your browser.

Your logs are parsed and counted right here, on your machine.