iwantcoding.com
🔥 Daily 👥 Rooms 🏆 Top Log in Sign up

Bootcamp

A 60-minute regex bootcamp: build a small log analyser that parses production-style logs and answers "how many 5xx in the last hour?" — applying the patterns you actually need.

A 60-minute regex bootcamp

EXAMPLE
# ===== Objectives =====
# 1. Compile patterns at module scope
# 2. Use named groups for readability
# 3. Use verbose mode for long patterns
# 4. Handle multi-line records
# 5. Detect + avoid ReDoS
# 6. Build a tiny CLI that summarises errors

# ===== 0-5 min: pick a log sample =====
# Apache combined or nginx access log; or a JSON-lines app log.
# Sample line:
# 203.0.113.5 - - [11/Jun/2026:10:32:14 +1000] "GET /api/users HTTP/1.1" 200 1532 "-" "curl/8.6"

# ===== 5-15 min: build the parser =====
import re

LOG = re.compile(r'''
    ^
    (?P<ip>\d{1,3}(?:\.\d{1,3}){3})\s+
    \S+\s+\S+\s+
    \[(?P<ts>[^\]]+)\]\s+
    \"(?P<method>[A-Z]+)\s+(?P<path>[^ ]+)\s+HTTP/[\d.]+\"\s+
    (?P<status>\d{3})\s+
    (?P<bytes>\d+|-)\s+
    \"(?P<referer>[^\"]*)\"\s+
    \"(?P<ua>[^\"]*)\"
    $
''', re.VERBOSE)

def parse(line: str):
    m = LOG.match(line)
    if not m: return None
    d = m.groupdict()
    d['status'] = int(d['status'])
    d['bytes']  = 0 if d['bytes'] == '-' else int(d['bytes'])
    return d

# ===== 15-25 min: count 5xx by path =====
from collections import Counter

c = Counter()
with open('access.log') as f:
    for line in f:
        rec = parse(line)
        if rec and rec['status'] >= 500:
            c[rec['path']] += 1

for path, n in c.most_common(10):
    print(f'{n:>6}  {path}')

# ===== 25-35 min: filter by time window =====
from datetime import datetime, timedelta, timezone

def parse_ts(ts: str) -> datetime:
    # 11/Jun/2026:10:32:14 +1000
    return datetime.strptime(ts, '%d/%b/%Y:%H:%M:%S %z')

cutoff = datetime.now(tz=timezone.utc) - timedelta(hours=1)
recent_5xx = 0
with open('access.log') as f:
    for line in f:
        rec = parse(line)
        if rec and rec['status'] >= 500 and parse_ts(rec['ts']) >= cutoff:
            recent_5xx += 1
print(f'5xx in last hour: {recent_5xx}')

# ===== 35-45 min: multi-line stack traces =====
# App logs often span multiple lines. Combine until the next 'leading line'
# pattern, then parse the leader.

LEADER = re.compile(r'^\[(?P<ts>\d{4}-\d{2}-\d{2}[ T]\d{2}:\d{2}:\d{2})\]\s+(?P<level>INFO|WARN|ERROR|FATAL)\s+')

def iter_events(lines):
    buf = []
    for line in lines:
        if LEADER.match(line) and buf:
            yield ''.join(buf); buf = []
        buf.append(line)
    if buf: yield ''.join(buf)

for event in iter_events(open('app.log')):
    head = LEADER.match(event)
    if head and head.group('level') in ('ERROR', 'FATAL'):
        print(event[:200])

# ===== 45-55 min: avoid ReDoS =====
# Pattern shapes to refuse on untrusted input:
# - (a+)+$
# - (\w+\s+)+$
# - (.*a){10}
#
# If you must run untrusted regex, use a linear-time engine:
# - Go's regexp (RE2)
# - Python re2 (google/re2) package
# - .NET 7+ has NonBacktracking mode

# Safe-regex check
# pip install safe-regex
# import safe_regex
# safe_regex.is_safe(r'^(a+)+$')      -> False

# ===== 55-60 min: package =====
# Wrap the parser into a CLI tool:
# python summarise.py access.log --since 1h --top 5
# Use argparse / click; tests with the sample log lines above.

# ===== Bonus =====
# - Generate a Prometheus exporter from the same parser
# - Write a small Grafana dashboard for 5xx by path
# - Tail -f mode: continuously parse new lines

# ===== Decision rules =====
# Use regex for:    line-oriented text, log parsing, extraction, validation
# Avoid regex for:  HTML, XML, JSON, YAML, CSV with quoting, code parsing
# Compile ONCE; use everywhere
# Verbose mode for any pattern > ~40 chars
# Named groups for any output you display

# ===== Pitfalls =====
# - Recompiling inside a hot loop
# - re.match vs re.search (match is anchored at start)
# - greedy quantifiers eating across newlines (use re.DOTALL deliberately)
# - leading anchors omitted -> partial matches accepted
# - timezones in timestamps ignored

Why it matters

A small log analyser is the project that exercises every important regex pattern — compile-once, named groups, verbose mode, multi-line records, time-window filtering — at a scale that fits a Saturday. Build it, host the dashboard, and you have proof you can use regex on real production data.

Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.

Example

Example
// 30-day RegEx bootcamp in the lesson body.
Try it Yourself »

Discussion

Loading…