Skip to content

Overview — Project 1: logwise

If you’ve read The Rust Mindset, you have the one idea the whole language hangs from: a single owner per value, and “shared XOR mutable” for references. Now we make it concrete by building something real. Over three days you’ll write logwise — a command-line tool that reads a log file, filters it by severity and text, and prints a tidy summary — and every Rust concept arrives at the exact moment the build reaches for it.

Point it at a log file and it parses each line, applies the filters you asked for, and prints a per-level histogram plus the totals:

$ logwise samples/app.log --level warn --verbose
2026-06-26T09:00:05Z WARN cache miss rate is 38 percent
2026-06-26T09:00:12Z ERROR failed to open /var/data/blob: permission denied
2026-06-26T09:00:12Z WARN retrying blob read attempt 1 of 3
2026-06-26T09:00:13Z ERROR failed to open /var/data/blob: permission denied
2026-06-26T09:00:13Z WARN retrying blob read attempt 2 of 3
2026-06-26T09:00:30Z ERROR connection reset by peer on socket 7
total lines : 16
parsed : 15
malformed : 1
matched : 6
by level:
TRACE : 1
DEBUG : 2
INFO : 6
WARN : 3
ERROR : 3

It’s small enough to finish in three sittings, but it’s shaped like a real tool: argument parsing, fallible I/O, a typed data model, lenient and strict modes, and a test suite that proves it works.

Each day teaches the concept its slice of the build needs, then builds that slice with real code from the rust/logwise/ crate — not toy snippets.

DayYou learnYou build
Day 1cargo new, project layout, clap arg parsing, ownership/borrowing, structs & enums, matchargs + read the file + a Level enum and LogLine struct
Day 2Result, ?, Option, a thiserror error enum, robust I/O, splitting into modulesa parser that survives bad input + level/pattern filtering
Day 3iterators & closures (filter/map/fold), unit + integration tests, release builds, cargo installthe aggregation step, a full test suite, and a real installed CLI

By the end you’ll have a binary you can cargo install and actually use — and, more importantly, a working feel for the parts of Rust that stall people after the Book.

The companion crate lives at rust/logwise/. Its modules mirror the pipeline data flows through:

rust/logwise/
├─ Cargo.toml ← deps: clap (derive), thiserror
├─ samples/app.log ← sample data you analyze
├─ src/
│ ├─ main.rs ← wires the pipeline, decides the exit code
│ ├─ cli.rs ← clap argument struct (Day 1)
│ ├─ parser.rs ← Level enum + LogLine struct + parse_line (Day 1–2)
│ ├─ analyze.rs ← Filter + Summary + iterator aggregation (Day 3)
│ └─ error.rs ← LogError / ParseError via thiserror (Day 2)
└─ tests/cli.rs ← end-to-end test that runs the binary (Day 3)

You only need a Rust toolchain (rustup gives you cargo). From the crate directory:

Terminal window
cd rust/logwise
cargo run -- samples/app.log # summarize everything
cargo run -- samples/app.log --level error # only ERROR and above
cargo run -- samples/app.log -p blob -i -v # case-insensitive "blob", show matches
cargo test # run the whole suite
cargo install --path . # install the `logwise` binary

Hold the playbook’s recurring question on every page: what does building this force you to understand — and what is Rust’s compiler protecting you from? logwise is the smallest honest answer. Reading a file forces you to decide who owns those bytes; a log line that might be garbage forces you to model absence and failure as types; aggregating millions of lines forces you to reach for iterators that don’t allocate. At each step the compiler is keeping the “one owner” and “shared XOR mutable” rules true so you can’t leak memory, race a thread, or silently ignore an error.

When logwise compiles and its tests pass, move on to Project 2 — kvlite, a key-value store — where those same rules buy you fearless concurrency.

Ready? Start with Day 1 · Setup and Ownership →