Usage
From “show everything” to “show only what matters”. All examples are copy-paste with testdata/sample.log — replace with your source (see Log Sources).
No filter — aggregate report
caddy-analyze testdata/sample.log
Renders period, RPS, 2xx/3xx/4xx/5xx bars, bytes, P50/P95/P99, human/bot, top paths/IPs/UAs/methods/hosts, countries/cities/ASNs (if GeoIP), and operational counts.
Entry filters → listing mode
When any entry-level filter is active and format is table without -o, the tool switches to a color-coded listing (not aggregate). Force the report with -f json/csv/html or -o.
| Filter | Example |
|---|---|
| Time | --from 1h --from 2026-08-31T00:00:00Z --to 2026-08-31T01:00:00Z |
| Status | -s 404,500 --5xx --4xx |
| Network | --ip 198.51.100.0/24 --exclude-ip 10.0.0.0/8 |
| Geo | --country IT,US --exclude-country CN --asn 12345 |
| HTTP | -m POST -p /api/* --host example.com --grep "admin" |
| Perf | --slow 500ms --max-latency 100ms --min-size 1mb |
| Bot | --no-bots --bots-only |
| Operational | --level error,warn --ops-only |
caddy-analyze --5xx testdata/sample.log
caddy-analyze --country IT -t 25 testdata/sample.log
caddy-analyze --grep "wp-" --no-bots testdata/sample.log
Output formats
caddy-analyze -f table testdata/sample.log # default
caddy-analyze -f json -o report.json --detect testdata/sample.log
caddy-analyze -f csv -o report.csv testdata/sample.log
caddy-analyze -f html -o report.html --detect testdata/sample.log && open report.html
caddy-analyze --defang -f json testdata/sample.log # 203.0.113.1 → 203[.]0[.]113[.]1
--defang rewrites IPs/URLs for safe sharing (also hxxp).
Remote exporters
Remote formats send one aggregated report per emitted report. Elasticsearch and OpenSearch use the Bulk API; Loki receives the same report as one log line. In --follow and --interval, every window is flushed synchronously.
caddy-analyze -f elasticsearch --remote-url http://localhost:9200 --remote-index caddy-analysis testdata/sample.log
caddy-analyze -f opensearch --remote-url https://search.example/_bulk --remote-token "$TOKEN" testdata/sample.log
caddy-analyze -f loki --remote-url http://localhost:3100 testdata/sample.log
Use --remote-user/--remote-password for Basic authentication, or --remote-token for Bearer authentication. Retry and timeout behavior is controlled by --remote-retries, --remote-backoff, and --remote-timeout.
Custom patterns
Load one or more validated JSON rule files without recompiling the binary:
caddy-analyze --detect --custom-patterns rules.json --custom-patterns local.json testdata/sample.log
[{"type":"internal_admin","pattern":"/internal/admin","description":"Internal admin probe","confidence":8,"source":"uri","mitre":"T1595.002"}]
source can be uri, header, user_agent, or all. Invalid JSON, regexes, types, or confidence values fail before log processing.
Top — ranked inspector
caddy-analyze top ip testdata/sample.log
caddy-analyze top path -t 20 --5xx testdata/sample.log
caddy-analyze top country --country IT testdata/sample.log
caddy-analyze top city testdata/sample.log
caddy-analyze top asn testdata/sample.log
caddy-analyze top -b bandwidth -f csv -o top.csv testdata/sample.log
Dimensions: path, ip, ua, status, method, host, bandwidth, country, city, asn. Country/asn need GeoIP; city uses a City MMDB, which is downloaded automatically unless --no-auto-download is set.
Diff — compare two logs
caddy-analyze diff testdata/sample.log testdata/large.log
caddy-analyze diff old.log new.log -f json -o diff.json
Shows RPS delta, 5xx spike, latency regression, new error paths (top 10).
Baselines and regression checks
caddy-analyze baseline save --output baseline.json testdata/sample.log
caddy-analyze --against baseline.json --threshold 20 testdata/sample.log
The baseline is a versioned JSON snapshot. A comparison prints the metric deltas and exits non-zero when an error, latency, operational-error, or new-error-path regression exceeds the threshold. This makes it suitable for CI/CD gates. The default threshold is 20 percent.
Container deployment
A hardened local demo is available in docker-compose.yml. The Helm chart is under deploy/helm/caddy-analyzer; it runs non-root with a read-only filesystem and does not mount the Docker socket by default. Enable the socket only when the security implications are understood.
docker compose up --build
helm lint deploy/helm/caddy-analyzer
helm template caddy-analyzer deploy/helm/caddy-analyzer
Live — follow / interval / watch
caddy-analyze --follow /var/log/caddy/access.log # stream
caddy-analyze --interval 10s /var/log/caddy/access.log # report every 10s
caddy-analyze --watch /var/log/caddy/access.log # 8-tab TUI (see TUI & Reports)
caddy-analyze tail docker://caddy --detect # tail with inline detect
Detection
caddy-analyze --detect testdata/sample.log -f table
caddy-analyze --detect -f html -o sec.html testdata/sample.log
26 categories, dual-pass (raw + unescaped), MITRE-tagged. See Categories and Detection details.