Practice: a log analyser

One messy log file and four questions about it — parsed, grouped and answered with the whole course at once.

24of 24
≈ 16Min read
4Parts

The brief

A web server has written eleven lines to a log. Three of them are not log lines: a comment, a blank line and something that got in by accident. That is what a real log looks like, and a parser that assumes otherwise falls over on its first day.

Your job is to turn the good lines into objects and answer four questions: when was it busiest, how often did it fail, which endpoint is slowest, and which is most used.

The format

A named-group regular expression is the right tool here, because this is a pattern: fixed fields separated by whitespace. Anything that does not match the whole line is not a log line, and the parser should say so by returning None rather than raising.

text
2026-09-22T08:14:03Z INFO GET /api/doors 200 42ms
└─ timestamp, ISO 8601, UTC
                     └─ level: INFO, WARN or ERROR
                          └─ method
                              └─ path
                                         └─ status
                                             └─ duration

What you will use

Every ranking has to break ties deterministically, or your answer changes between runs and no test can pin it down. Here: slowest first, and alphabetically when two are equally slow.

LessonHere
DataclassesA frozen Entry — one record per line, hashable and printable
The standard libraryre to parse, datetime to read the timestamp, Counter to tally
Iteratorsread() yields entries, so a 2 GB log costs the same as this one
Dictionariesdefaultdict(list) to collect the durations per path
ErrorsA bad line is not an exception — it is a line that is not a log line
Functionalmax with a key, sorted with a two-part key for the ties

The numbers to expect

Ten of the eleven lines parse. Three of them are errors. The busiest hour is 09, with five entries. /api/quote is by far the slowest endpoint at 1140 ms on average, and /api/doors is the most used, with four calls.

If your numbers differ, the parser is the first place to look — usually it accepted a line it should have rejected, or rejected one it should have taken.

Practice