Skip to main content
Zeal is structured as a pipeline: a query string and a log file go in, filtered log entries come out. Each stage is a small, focused module.

Project structure

FilePurpose
src/lexer.zigStreaming tokenizer (zero-copy)
src/parser.zigRecursive-descent parser → AST
src/ast.zigAST node types
src/log_reader.zigFile reader + line iterator
src/log_parser.zigFormat auto-detection (JSON / logfmt / syslog / plain)
src/evaluator.zigWHERE expression evaluator
src/temporal.zigTemporal correlation + GROUP BY
src/cli.zigCLI argument parser
src/formatter.zigOutput formatting (text / JSON / raw)
src/main.zigCLI entry point
src/root.zigLibrary root (re-exports)

The pipeline

1

Parse CLI args (cli.zig)

cli.zig parses flags (--format, --follow, -f, etc.) and extracts the raw query string.
2

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.
3

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.
4

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.
5

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.
6

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.
7

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.
8

Format output (formatter.zig)

formatter.zig renders the matching entries to stdout in the requested format: human-readable text with colours (default), NDJSON, or raw original lines.

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.

Build docs developers (and LLMs) love