brogz
Measure wire bytes and timing for identity, gzip, and brotli responses
across a site's static assets. One static binary — no Node, no curl in your
PATH.
br+gz— the two encodings we compare.
┌─────────────────────────────────────────┬──────────┬─────────┬───────┬─────────┬───────┬──────────┐
│ path │ raw │ gzip │ gz CE │ br │ br CE │ br vs gz │
╞═════════════════════════════════════════╪══════════╪═════════╪═══════╪═════════╪═══════╪══════════╡
│ /index.html │ 38.59KB │ 9.89KB │ gzip │ 7.85KB │ br │ -20.6% │
│ /assets/index-yrrrWp82.js │ 17.19KB │ 6.75KB │ gzip │ 5.88KB │ br │ -12.9% │
│ /assets/vendor-DCLJsiZC.js │ 185.20KB │ 57.48KB │ gzip │ 49.58KB │ br │ -13.7% │
│ Σ TOTAL │ 306.95KB │ 96.27KB │ │ 82.96KB │ │ -13.8% │
└─────────────────────────────────────────┴──────────┴─────────┴───────┴─────────┴───────┴──────────┘
Install
# Homebrew (macOS, Linux)
# crates.io (anywhere with a Rust toolchain)
# or grab a prebuilt binary from the latest GitHub Release:
# https://github.com/Segodnya/brogz/releases
Prebuilt targets: x86_64/aarch64-unknown-linux-gnu, x86_64/aarch64-apple-darwin,
x86_64-pc-windows-msvc.
The Homebrew tap lives at Segodnya/homebrew-brogz and is bumped automatically on every new release.
Usage
brogz <URL> [OPTIONS]
Arguments:
<URL> Base URL, e.g. https://app.example
Options:
-r, --runs <N> Probes per URL × encoding [default: 10]
-c, --concurrency <N> Max parallel requests [default: 3 * runs]
-k, --insecure Skip TLS verification
-o, --out <FILE> Write JSON report to file (in addition to stdout table)
-p, --path <PATH> Skip discovery; measure these paths instead (repeatable)
--no-color Disable colored output
-h, --help, -V, --version
Common invocations:
# Auto-discover assets from /index.html, default 10 probes per URL × encoding.
# More probes for tighter medians; default concurrency follows runs.
# Save the JSON report alongside the stdout table.
# Skip discovery entirely — measure exactly these paths.
# Dev environments behind an internal CA.
What it measures
For every URL × encoding pair, brogz sends --runs parallel HTTP requests
with the matching Accept-Encoding header, records the wire byte count and
total wall-clock time, and reports:
| field | meaning |
|---|---|
bytes |
first probe's body length on the wire (not decompressed) |
contentEncoding |
Content-Encoding header from the final response |
medianMs |
median of per-probe wall-clock time (Math.round-compatible) |
Size and Content-Encoding mismatches across probes log a warn! to stderr.
Status mismatches or non-200 responses abort the URL with a clear error.
Output
A unicode table (with optional colors) to stdout. The full report — including
per-probe medians and totals — is written to JSON when --out is set:
The JSON shape is pinned by a unit test so historical reports can be diffed
with jq -S across versions without spurious churn.
Library usage
The crate exposes everything the CLI uses, behind a feature-gated split so library consumers do not pull in clap / comfy-table / crossterm:
[]
= { = "0.1", = false }
= { = "1", = ["rt-multi-thread", "macros"] }
= "2"
use Config;
use Url;
async
The lower-level building blocks are also public: discover_urls,
measure_url, measure_encoding, probe, build_client, median.
Exit codes
| code | meaning |
|---|---|
| 0 | success |
| 1 | runtime error (transport, non-200, inconsistent status) |
| 2 | invalid CLI arguments |
License
Dual-licensed under either of
- Apache License, Version 2.0 (LICENSE-APACHE)
- MIT license (LICENSE-MIT)
at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual-licensed as above, without any additional terms or conditions.