Skip to content

Commit 9fde586

Browse files
Add the docs!
1 parent 6ad867f commit 9fde586

11 files changed

Lines changed: 752 additions & 77 deletions

README.md

Lines changed: 19 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -10,37 +10,13 @@ Monitor your Caddy server in real time: per-host traffic, latency percentiles, s
1010

1111
## Features
1212

13-
### Caddy dashboard (always available)
14-
15-
- Per-host traffic table with RPS, per-host RPS sparklines, average response time, and in-flight requests
16-
- Latency percentiles (P50, P90, P95, P99) from Prometheus histogram buckets
17-
- Status code breakdown (2xx/s, 4xx/s, 5xx/s) per host
18-
- Sorting and live filtering by hostname
19-
- Live sparkline graphs (CPU, RPS, RSS)
20-
- JSON output mode for scripting (includes per-host metrics)
21-
22-
### FrankenPHP dashboard (when detected)
23-
24-
- Per-thread introspection (URI, HTTP method, duration, memory)
25-
- Worker queue depth and busy thread tracking
26-
- Full-screen graphs (CPU, RPS, RSS, queue depth, busy threads)
27-
- Graceful worker restart from the TUI
28-
- Detail panel with per-thread info and memory sparkline trend
29-
- Memory delta indicators (↑/↓) per thread between polls
30-
31-
### Cloud Ready with Prometheus Export & Daemon Mode
32-
33-
- `--expose=:9191` starts a `/metrics` endpoint exposing Caddy and FrankenPHP metrics in Prometheus format
34-
- `--daemon` runs headless (no TUI)
35-
- `/healthz` endpoint returns `200 OK` when data is fresh, `503` when stale or unavailable (useful for k8s liveness probes)
36-
- Exposes per-host RPS/latency/in-flight/status rates, thread state, per-thread memory, worker crashes/restarts/queue, request duration percentiles, and process CPU/RSS
37-
- Works alongside the TUI (`--expose` without `--daemon`) or standalone
38-
39-
### General
40-
41-
- Tab-based navigation between Caddy and FrankenPHP views
13+
- Per-host traffic table with RPS, latency percentiles (P50–P99), status codes, and sparklines
14+
- FrankenPHP thread introspection with memory tracking and worker management
15+
- Full-screen ASCII graphs (CPU, RPS, RSS, queue depth, busy threads)
16+
- Prometheus metrics export (`/metrics`) and health endpoint (`/healthz`)
17+
- Daemon mode for headless operation
18+
- JSON output mode for scripting
4219
- Auto-detection of FrankenPHP and Caddy processes
43-
- Stale data and connection loss detection
4420
- Cross-platform binaries, Homebrew tap, and Docker image
4521

4622
## Install
@@ -55,13 +31,13 @@ Or with Go:
5531
go install github.com/alexandre-daubois/ember/cmd/ember@latest
5632
```
5733

58-
Or with Docker (runs in daemon mode with Prometheus export on `:9191` by default):
34+
Or with Docker:
5935

6036
```bash
6137
docker run --rm --network host ghcr.io/alexandre-daubois/ember
6238
```
6339

64-
## Usage
40+
## Quick Start
6541

6642
Make sure Caddy is running with the admin API and metrics enabled:
6743

@@ -78,52 +54,20 @@ Then:
7854
ember
7955
```
8056

81-
Ember connects to the Caddy admin API and auto-detects FrankenPHP if present. In Caddy-only mode, the dashboard shows per-host HTTP metrics. When FrankenPHP is detected, a second tab provides thread-level introspection.
57+
Ember connects to the Caddy admin API and auto-detects FrankenPHP if present.
8258

83-
### Options
59+
## Documentation
8460

85-
```
86-
--addr string Caddy admin API address (default "http://localhost:2019")
87-
--interval dur Polling interval (default 1s)
88-
--slow-threshold ms Slow request threshold (default 500)
89-
--pid int FrankenPHP PID (auto-detected if not set)
90-
--json JSON output mode (streaming JSONL)
91-
--expose addr Expose Prometheus metrics (e.g. --expose=:9191)
92-
--daemon Headless mode (requires --expose)
93-
--metrics-prefix str Prefix for exported Prometheus metric names
94-
--no-color Disable colors
95-
```
61+
Full documentation is available in the [docs/](docs/index.md) directory:
9662

97-
### Keybindings
98-
99-
| Key | Action |
100-
|-----|--------|
101-
| `Tab` | Switch between Caddy / FrankenPHP tabs |
102-
| `1` / `2` | Jump to tab |
103-
| `` `` `j` `k` | Navigate list |
104-
| `Home` / `End` | Jump to first / last item |
105-
| `PgUp` / `PgDn` | Page navigation |
106-
| `Enter` | Detail panel |
107-
| `s` / `S` | Cycle sort field |
108-
| `p` | Pause / resume |
109-
| `r` | Restart workers (FrankenPHP) |
110-
| `/` | Filter |
111-
| `g` | Full-screen graphs |
112-
| `?` | Help overlay |
113-
| `q` | Quit |
114-
115-
### Shell Completions
116-
117-
```bash
118-
# Bash
119-
ember completion bash > /etc/bash_completion.d/ember
120-
121-
# Zsh
122-
ember completion zsh > "${fpath[1]}/_ember"
123-
124-
# Fish
125-
ember completion fish > ~/.config/fish/completions/ember.fish
126-
```
63+
- [Getting Started](docs/getting-started.md): Install and first run
64+
- [Caddy Configuration](docs/caddy-configuration.md): Caddyfile requirements
65+
- [Caddy Dashboard](docs/caddy-dashboard.md): Per-host traffic and latency
66+
- [FrankenPHP Dashboard](docs/frankenphp-dashboard.md): Thread introspection and workers
67+
- [CLI Reference](docs/cli-reference.md): Flags, keybindings, shell completions
68+
- [JSON Output](docs/json-output.md): Streaming JSONL for scripting
69+
- [Prometheus Export](docs/prometheus-export.md): Metrics, health checks, daemon mode
70+
- [Docker](docs/docker.md): Container usage
12771

12872
## License
12973

docs/caddy-configuration.md

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
# Caddy Configuration
2+
3+
Ember reads data from the Caddy admin API. This page explains what your Caddyfile needs for Ember to work.
4+
5+
## Admin API
6+
7+
Ember connects to the Caddy admin API (default: `localhost:2019`). Make sure it's enabled:
8+
9+
```
10+
{
11+
admin localhost:2019
12+
}
13+
```
14+
15+
> **Caution:** The admin API is unauthenticated by default. Do not expose it on a public interface. See [Caddy's admin API documentation](https://caddyserver.com/docs/caddyfile/options#admin) for authentication options.
16+
17+
## Metrics Directive
18+
19+
The `metrics` directive enables Prometheus-format metrics on the admin API. Without it, Ember cannot display HTTP traffic data.
20+
21+
```
22+
{
23+
admin localhost:2019
24+
metrics
25+
}
26+
```
27+
28+
This exposes the following Caddy metrics at the `/metrics` admin endpoint:
29+
30+
| Metric | Description |
31+
|--------|-------------|
32+
| `caddy_http_requests_total` | Total HTTP requests (with host, method, status labels) |
33+
| `caddy_http_request_duration_seconds` | Request duration histogram (with host labels and buckets) |
34+
| `caddy_http_requests_in_flight` | Currently in-flight requests |
35+
| `caddy_http_response_size_bytes` | Response body size |
36+
37+
Ember parses these metrics to compute per-host RPS, average latency, percentiles, status code rates, and more.
38+
39+
## FrankenPHP Detection
40+
41+
Ember automatically detects FrankenPHP by sending `GET /frankenphp/threads` to the admin API. If the endpoint responds with `200 OK`, the FrankenPHP tab is enabled.
42+
43+
If auto-detection does not work, you can specify the process ID manually:
44+
45+
```bash
46+
ember --pid 12345
47+
```
48+
49+
When no `--pid` is provided, Ember scans the process list for a FrankenPHP process. If none is found, it falls back to scanning for a Caddy process for CPU/RSS monitoring.
50+
51+
## Remote Caddy Instances
52+
53+
Use the `--addr` flag to point Ember to a remote Caddy admin API:
54+
55+
```bash
56+
ember --addr http://10.0.0.5:2019
57+
```
58+
59+
The admin API must be reachable from wherever Ember runs.
60+
61+
## Minimal Caddyfile
62+
63+
A complete working example:
64+
65+
```
66+
{
67+
admin localhost:2019
68+
metrics
69+
}
70+
71+
example.com {
72+
respond "Hello, world!" 200
73+
}
74+
```
75+
76+
## See Also
77+
78+
- [Getting Started](getting-started.md)
79+
- [Caddy Dashboard](caddy-dashboard.md)
80+
- [FrankenPHP Dashboard](frankenphp-dashboard.md)

docs/caddy-dashboard.md

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
# Caddy Dashboard
2+
3+
The Caddy tab is always available. It displays per-host HTTP traffic metrics collected from the Caddy Prometheus endpoint.
4+
5+
## Host Traffic Table
6+
7+
The main view shows a table with one row per host:
8+
9+
| Column | Description |
10+
|--------|-------------|
11+
| **Host** | Hostname from the Caddy configuration |
12+
| **RPS** | Requests per second |
13+
| **Sparkline** | Miniature RPS trend (last 8 samples) |
14+
| **Avg** | Average response time in milliseconds |
15+
| **P90** | 90th percentile latency |
16+
| **P95** | 95th percentile latency |
17+
| **P99** | 99th percentile latency |
18+
| **In-flight** | Currently in-progress requests |
19+
| **2xx/s** | Successful response rate |
20+
| **4xx/s** | Client error rate (displayed in yellow) |
21+
| **5xx/s** | Server error rate (displayed in red) |
22+
23+
> **Note:** If you see a host named `*`, it means Caddy metrics lack per-host labels. The `*` row aggregates all traffic. Make sure your Caddyfile routes include host matchers for per-host breakdown.
24+
25+
## Latency Percentiles
26+
27+
P50, P90, P95, and P99 are computed from Prometheus histogram buckets (`caddy_http_request_duration_seconds`). These percentiles appear per host in the traffic table and in the host detail panel.
28+
29+
> **Tip:** If percentile columns are empty, verify that the `metrics` directive is present in your Caddyfile global block. See [Caddy Configuration](caddy-configuration.md).
30+
31+
## Sorting
32+
33+
Press `s` to cycle the sort field forward, `S` to cycle backward. Available sort fields:
34+
35+
`host``rps``avg``p90``p95``p99``in-flight``2xx``4xx``5xx`
36+
37+
The current sort field is shown in the bottom status bar.
38+
39+
## Filtering
40+
41+
Press `/` to enter filter mode. Type a hostname pattern to filter the table. Press `Esc` to clear the filter and return to the full list.
42+
43+
## Host Detail Panel
44+
45+
Press `Enter` on a host to open the detail panel:
46+
47+
- **Traffic**: RPS, in-flight requests, total request count
48+
- **Latency**: P50, P90, P95, P99 (when available), average response time
49+
- **Status Codes**: Individual status codes with their rates
50+
- **HTTP Methods**: Request rates and percentage of total per method (GET, POST, etc.)
51+
- **Response Size**: Average response body size
52+
53+
Press `Esc` to close the detail panel.
54+
55+
## Graphs
56+
57+
Press `g` to toggle full-screen graphs showing:
58+
59+
- **CPU %**: Process CPU usage over time
60+
- **RPS**: Requests per second over time
61+
- **RSS**: Resident memory over time
62+
63+
Graphs display the last 300 samples. Press `g` or `Esc` to return to the table view.
64+
65+
## See Also
66+
67+
- [FrankenPHP Dashboard](frankenphp-dashboard.md)
68+
- [Caddy Configuration](caddy-configuration.md)
69+
- [CLI Reference](cli-reference.md)

docs/cli-reference.md

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
# CLI Reference
2+
3+
## Synopsis
4+
5+
```
6+
ember [flags]
7+
```
8+
9+
## Flags
10+
11+
| Flag | Type | Default | Description |
12+
|------|------|---------|-------------|
13+
| `--addr` | string | `http://localhost:2019` | Caddy admin API address |
14+
| `--interval` | duration | `1s` | Polling interval |
15+
| `--slow-threshold` | int | `500` | Slow request threshold in milliseconds. Requests above this are highlighted yellow; above 2x are red. |
16+
| `--pid` | int | `0` (auto) | FrankenPHP PID. Auto-detected if not set. |
17+
| `--json` | bool | `false` | JSON output mode (streaming JSONL). See [JSON Output](json-output.md). |
18+
| `--expose` | string | _(none)_ | Start Prometheus metrics endpoint on this address (e.g. `:9191`). See [Prometheus Export](prometheus-export.md). |
19+
| `--daemon` | bool | `false` | Headless mode: no TUI. Requires `--expose`. See [Prometheus Export](prometheus-export.md). |
20+
| `--metrics-prefix` | string | _(none)_ | Prefix for exported Prometheus metric names. See [Prometheus Export](prometheus-export.md). |
21+
| `--no-color` | bool | `false` | Disable colors |
22+
| `--version` | | | Print version and exit |
23+
24+
## Examples
25+
26+
```bash
27+
# Default: connect to localhost:2019
28+
ember
29+
30+
# Connect to a remote Caddy instance
31+
ember --addr http://prod:2019
32+
33+
# Pipe-friendly JSON output
34+
ember --json
35+
36+
# JSON output at a slower rate
37+
ember --json --interval 5s
38+
39+
# TUI with Prometheus metrics on port 9191
40+
ember --expose :9191
41+
42+
# Headless metrics exporter (no TUI)
43+
ember --expose :9191 --daemon
44+
45+
# Stricter slow-request highlighting
46+
ember --slow-threshold 200
47+
48+
# Prefixed Prometheus metrics
49+
ember --expose :9191 --metrics-prefix myapp
50+
51+
# Explicitly specify a FrankenPHP PID
52+
ember --pid 42
53+
```
54+
55+
## Keybindings
56+
57+
### Navigation
58+
59+
| Key | Action |
60+
|-----|--------|
61+
| `Up` / `Down` / `j` / `k` | Move cursor |
62+
| `Enter` | Open detail panel |
63+
| `Esc` | Close panel / clear filter / go back |
64+
| `Tab` | Switch tab |
65+
| `1` / `2` | Jump to tab |
66+
| `Home` / `End` | Jump to first / last item |
67+
| `PgUp` / `PgDn` | Page up / page down |
68+
69+
### Actions
70+
71+
| Key | Action | Context |
72+
|-----|--------|---------|
73+
| `s` / `S` | Cycle sort field forward / backward | List view |
74+
| `p` | Pause / resume polling | Any view |
75+
| `/` | Enter filter mode | List view |
76+
| `g` | Toggle full-screen graphs | Any view |
77+
| `r` | Restart workers | FrankenPHP tab only |
78+
| `?` | Toggle help overlay | Any view |
79+
| `q` | Quit | Any view |
80+
81+
## Shell Completions
82+
83+
### Bash
84+
85+
```bash
86+
ember completion bash > /etc/bash_completion.d/ember
87+
```
88+
89+
### Zsh
90+
91+
```bash
92+
ember completion zsh > "${fpath[1]}/_ember"
93+
```
94+
95+
### Fish
96+
97+
```bash
98+
ember completion fish > ~/.config/fish/completions/ember.fish
99+
```
100+
101+
## See Also
102+
103+
- [Getting Started](getting-started.md)
104+
- [JSON Output](json-output.md)
105+
- [Prometheus Export](prometheus-export.md)

0 commit comments

Comments
 (0)