ruby 20 lines · 6 steps

Parsing Apache logs with named captures

A regex with named groups turns each raw Apache access-log line into a clean, typed Ruby hash.

Explained by highlit
1class ApacheLogParser
2 LINE_PATTERN = /\A(?<ip>\S+)\s\S+\s\S+\s\[(?<time>[^\]]+)\]\s"(?<method>[A-Z]+)\s(?<path>\S+)\s(?<protocol>[^"]+)"\s(?<status>\d{3})\s(?<bytes>\d+|-)/
3 
4 TIME_FORMAT = "%d/%b/%Y:%H:%M:%S %z"
5 
6 def parse(line)
7 match = LINE_PATTERN.match(line)
8 return nil unless match
9 
10 {
11 ip: match[:ip],
12 timestamp: DateTime.strptime(match[:time], TIME_FORMAT),
13 method: match[:method],
14 path: match[:path],
15 protocol: match[:protocol],
16 status: match[:status].to_i,
17 bytes: match[:bytes] == "-" ? 0 : match[:bytes].to_i
18 }
19 end
20end
01 / 01
STEP 01

Walkthrough

Space play step click any line
Three takeaways
  1. 1Named capture groups make a complex regex self-documenting and let you pull fields by meaning instead of positional index.
  2. 2Returning nil on a failed match keeps parsing tolerant of malformed lines instead of crashing.
  3. 3Raw text fields should be coerced to real types at the boundary so downstream code works with integers and dates, not strings.

Related explainers

Share this explainer

Here's the card — post it anywhere.

Parsing Apache logs with named captures — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code