v0.7.1 · updated · GitHub

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.

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