Project structure
| File | Purpose |
|---|---|
src/lexer.zig | Streaming tokenizer (zero-copy) |
src/parser.zig | Recursive-descent parser → AST |
src/ast.zig | AST node types |
src/log_reader.zig | File reader + line iterator |
src/log_parser.zig | Format auto-detection (JSON / logfmt / syslog / plain) |
src/evaluator.zig | WHERE expression evaluator |
src/temporal.zig | Temporal correlation + GROUP BY |
src/cli.zig | CLI argument parser |
src/formatter.zig | Output formatting (text / JSON / raw) |
src/main.zig | CLI entry point |
src/root.zig | Library root (re-exports) |
The pipeline
Parse CLI args (cli.zig)
cli.zig parses flags (--format, --follow, -f, etc.) and extracts the raw query string.Lex the query (lexer.zig)
lexer.zig tokenizes the query string using a streaming, zero-copy tokenizer. No heap allocations — tokens are slices into the original query.Parse to AST (parser.zig)
parser.zig applies a recursive-descent parse over the token stream and builds an AST representing the FROM, WHERE, GROUP BY, and SHOW clauses.Read the log file (log_reader.zig)
log_reader.zig opens the file and exposes a line iterator. Lines are yielded one at a time, keeping memory usage low regardless of file size.Parse log entries (log_parser.zig)
log_parser.zig inspects the first line to auto-detect the format (JSON, logfmt, syslog, or plain text) and then parses each subsequent line into a set of key–value fields.Evaluate WHERE (evaluator.zig)
evaluator.zig walks the WHERE sub-tree of the AST and tests each parsed entry against the filter expression. Entries that do not match are discarded.Temporal correlation (temporal.zig)
If the query includes a
WITHIN ... OF clause, temporal.zig uses binary search over the sorted timestamp index to find correlated events in O(n log m) time.Key design principles
- Zero-copy parsing: fields are slices into the original file buffer. Zeal avoids allocating new strings for field names and values.
- Streaming: lines are processed one at a time. Memory usage stays constant regardless of how large the log file is.
- Single binary: there are no runtime dependencies. The release build produces a ~5 MB static binary that runs anywhere.
