# monitor.parse-access-log
Parses one line of a web server access log in the NCSA Common Log Format or
the Combined Log Format, the defaults of Apache httpd and nginx (nginx's
`combined` is the same layout):
```
Common %h %l %u %t "%r" %>s %b
Combined %h %l %u %t "%r" %>s %b "%{Referer}i" "%{User-agent}i"
127.0.0.1 - frank [10/Oct/2000:13:55:36 -0700] "GET /apache_pb.gif HTTP/1.0" 200 2326 "http://www.example.com/start.html" "Mozilla/4.08 [en] (Win98; I ;Nav)"
```
Feed it `monitor.status-code-summary` for error rates, or `monitor.rollup`
for requests per minute.
## Decisions
- **Junk is null, not an error.** Real logs hold truncated lines, lines from
another format and binary noise; a log reader should skip them and count
them, not stop. So anything not in either format returns null: a bad month,
30 February, a status outside 100 to 599, stray text after the byte count.
- **"-" is null** in every field that uses it (ident, user, bytes, referer,
user agent). Apache's `%b` writes "-" rather than 0 when no body was sent
(a 304, say): treat a null `bytes` as 0 if you are summing.
- **The request line.** `"-"` (the client sent nothing before timing out) and
anything that is not `METHOD path HTTP/x` (a TLS handshake sent to a plain
HTTP port logs as `"\x16\x03\x01..."`) keep the line, with method, path and
protocol null: the status (typically 400 or 408) is still worth counting.
`METHOD path` with no protocol is an HTTP/0.9 request: protocol null.
- **Escapes are kept as logged.** Apache writes `"` as `\"`, `\` as `\\` and
non-printable bytes as `\xhh` inside quoted fields. The parser honours `\"`
when finding the end of a field but returns the text as it appears in the
log, so no information is lost and nothing is decoded twice.
- **Extra fields after the user agent are ignored**, since many sites append
response time or a request id to Combined. After a Common line's byte count
nothing may follow except the two quoted Combined fields.
- **Time** `[10/Oct/2000:13:55:36 -0700]` is checked field by field (English
month abbreviations, real calendar dates, leap years, a numeric offset) and
converted with `time.iso-to-unix`, so `at` is exact Unix seconds (UTC).
A leap second (`:60`) is not a Unix time and makes the line null.
- A trailing `\n` or `\r\n` is stripped, so lines straight from a file work.
## Sources
- Apache HTTP Server 2.4, mod_log_config: "Common Log Format" and "Combined
Log Format", the `%b` "-" for no bytes, the `%t` format and the escaping of
`%r`, `%i` and `%u`, https://httpd.apache.org/docs/2.4/mod/mod_log_config.html
- Apache HTTP Server 2.4, Log Files (the example lines and field-by-field
explanation), https://httpd.apache.org/docs/2.4/logs.html#accesslog