Advertisement
Open Source Projects by Phil Schwartz

Crafting a python debugger plugin for regex highlighting in log files

Log files are the silent storytellers of every server, and anyone who has stared at gigabytes of Apache access records knows how easily meaningful patterns hide between the noise. Whether the goal is tracking suspicious login attempts flagged by the Australian Cyber Security Centre, auditing a Sydney-based web farm, or simply chasing a misbehaving cron job in Brisbane, the ability to isolate a regex match inside an active debug session turns hours of scrolling into moments of insight.

Existing tools cover parts of the workflow well. Kodos, a Python regular expression debugger, shines when a developer wants to experiment with a single line of input. DenyHosts analyses SSH traffic for brute-force patterns. Neither, however, bridges the gap between a live debugging session and a multi-gigabyte log file. A debugger plugin that recognises patterns on the fly and paints them in colour while the program steps forward offers the missing middle ground for engineers who already trust pdb or debugpy.

That middle ground is the focus here. Drawing from the spirit of open-source utilities like Scratchy, an Apache log analyser, the plugin described below hooks into the standard debugger, watches a chosen log source, applies user-defined patterns, and renders matches directly inside the terminal. The result feels native to a Python session and travels cleanly between local scripts and remote servers, even across the timezone spread that takes a deployment from Perth to AEST in a single afternoon.

Hooking into the python debugger framework

The standard library ships pdb, a tiny yet capable debugger that respects every breakpoint a developer already knows. The cleanest entry point is to subclass Pdb and overwrite parts of the command flow so each new line arriving from the watched file is intercepted before execution resumes. Running python -m myplugin script.py loads the plugin, registers itself through settrace, and quietly waits.

For projects already relying on debugpy inside VS Code or similar editors, the same idea translates through the Protocol API. A thin client accepts the file path, registers a handler for breakpoint hits, and forwards raw lines to the matcher. Members of the Melbourne Python community often highlight this dual approach because it keeps the plugin portable across teams that mix cloud-based IDEs with terminal workflows.

Internal state lives in a small dataclass: active patterns, the latest buffer, and a colour palette. Because pdb already serialises commands line by line, every step in the debug loop becomes an opportunity to feed fresh content into the matcher.

Designing the regex engine for log patterns

Python's built-in re module handles the heavy lifting. Each pattern supplied by the user gets compiled once, stored in a list, and reused for every incoming line. Named groups such as (?P<ip>...) or (?P<timestamp>...) make highlighted output far easier to scan, because the plugin can paint each group in its own colour rather than flattening matches into a single block.

When patterns grow complex, pre-compiling with re.compile and switching to finditer keeps memory pressure predictable. Servers hosting Australian government workloads often undergo Essential Eight assessments that demand detailed audit trails under strict resource caps. A regex engine that streams rather than slurps holds the line even when logs reach millions of entries per day.

Developers in Brisbane maintaining large mail clusters have observed that combining several short patterns outperforms one long alternation, both in clarity and in speed. The plugin encourages that style by accepting a YAML file of patterns, each entry pointing to its own highlight colour.

Streaming log files without blocking the debugger

Blocking the debugger with a slow read would defeat the purpose, so the plugin treats the log file as a generator. A background thread calls readline on a polling interval, pushes new content into a queue.Queue, and the debugger thread drains that queue during idle moments. Watchdog-style behaviour emerges naturally without forcing the developer to write a custom event loop.

On Linux, inotify is the natural choice, yet keeping dependencies small and pure Python broadens adoption across macOS workstations and the occasional Windows box that still shows up in Australian development shops. The default poll interval is 250 milliseconds, configurable through an environment variable, and the streamer falls back gracefully when the file rotates.

Rotation is common where the Notifiable Data Breaches scheme encourages frequent identifier changes. The streamer tracks the inode and reopens the file as soon as it changes, so the debugger never silently halts after a rewrite.

Painting matches with ANSI escape codes

Highlighting is delivered through standard ANSI escape sequences. The plugin ships a small palette: red for failed authentication, amber for slow queries, green for healthy 200 responses, and a softer tone for matched substrings inside otherwise uninteresting lines. Most modern terminals, from the default Terminal.app on macOS to Windows Terminal, interpret these codes consistently, so rendering stays predictable for a developer in Sydney connecting through a regional NBN link.

For terminals that strip colour, a NO_COLOR style flag forces plain output. That fallback matters where logs are piped into mail clients or stored as evidence, and Australian defence-adjacent teams regularly require reproducible text output from any tool that touches log data.

The render step also collapses runs of identical matches into a single visual marker. Long bursts of the same warning become a discreet >>> 142 matches <<< rather than a wall of colour, restoring readability when a noisy pattern dominates a file.

Filtering noise from real-world Australian server logs

Australian server logs carry signatures international tools sometimes miss. IP ranges reserved for Telstra, Optus, and the various state-government networks appear frequently, and timestamps arrive in AEST or AEDT rather than UTC. The plugin lets users register a normalisation hook that converts local timestamps into a sortable form before matching, eliminating a common source of false negatives when correlating across services.

Logs from the Bureau of Meteorology, public research portals at the Australian National University, and even hobbyist radio repeaters in regional Victoria all share a tendency to embed human-readable notes. Patterns that target those notes can lift them out cleanly while leaving structured fields untouched. A small library of Australian-specific patterns, from ACSC published indicators to the prefixes used by NBNCo diagnostics, gives the plugin a local flavour without forcing it on anyone.

Validating with pytest and a pinch of fuzzing

Once the highlight engine works, confidence comes from tests. A tests/ directory exercises every pattern, every colour scheme, and every rotation edge case. pytest runs the suite in under a second, and a separate hypothesis-powered pass generates malformed log lines to confirm the matcher never raises on trash input.

Community feedback refines the design further. Presenting the work at PyCon AU gatherings in Melbourne or Sydney surfaces real workloads the initial draft did not anticipate, from statewide education platforms to local fintech sandboxes. Each round of conversation sharpens the defaults and trims rough edges from the documentation.

Packaging, licensing, and open-source etiquette

The plugin follows a modern pyproject.toml layout, lists its runtime dependencies cleanly, and ships under a permissive licence that mirrors the approach used by DenyHosts and Scratchy. Documentation lives alongside the code, installation is one pip install away, and the source repository welcomes pull requests.

Distribution through PyPI combined with release notes on the project page keeps discoverability high. Australian contributors appreciate a clear statement about supported Python versions, because enterprise sites still run a mix of older runtimes alongside newer deployments. Honesty about that matrix, paired with a friendly contributing guide, tends to attract the maintainers a small open-source project needs to survive.