Monitoring & metrics
What to watch on a running daemon: the health probes, the metrics endpoint and its probe states, the opt-in Prometheus surface, and the event stream as the live signal.
Last updated
Three surfaces, and they answer different questions. /health says the process is up. /v1/metrics says what it is doing. The event stream says what just happened.
Health probes
| Path | Auth | Answers |
|---|---|---|
/health | none | The process is serving. |
/health/live | none | Liveness, for an orchestrator. |
/health/ready | none | Readiness. |
All three sit outside the auth layer, which is what makes them usable as a monitor probe.
Do not probe for a file. runtime.json lives in the data directory and is only removed by an orderly stop, so a crashed or wedged daemon leaves it exactly where it was. A probe watching that file reports healthy forever, including for a process that is frozen. Ask /health instead.
The metrics endpoint
GET /v1/metrics, behind the bearer token, answers with the resource picture:
- how many browsers are running, against the configured concurrency
- the configured memory budget and what is used
- host memory, CPU and GPU figures
- a per-profile breakdown
It is served from a background sampler, so the request path probes nothing and the numbers are at most one sampling interval old. The cadence is [observability] sample_interval_ms, 3000 by default.
Probe states
Every measured value is paired with one of three states:
| State | Meaning |
|---|---|
measured | This is a reading. |
unsupported | This platform cannot report it. |
unavailable | It should be readable and was not, right now. |
This is why "zero" and "we could not read this" never look alike. A monitor that treats a missing GPU reading as 0 percent draws a flat green line for a machine it has stopped measuring, which is the worst possible failure for a dashboard.
Prometheus
Off by default. [observability] enable_prometheus turns it on and prometheus_bind places it, on loopback by default.
It is unauthenticated plaintext, on a separate listener, not behind the API's token. The daemon warns loudly if you bind it publicly. Firewall it, or scrape it over a private network.
The live signal
Polling metrics tells you about the machine. The event stream tells you about the work: profiles starting, crashing and being refused, proxy checks, exit-guard verdicts, runs starting and finishing.
Three of those are worth an alert on any install:
profile_crashed, with its reasonpreflight_failed, which means a profile is configured in a way that cannot startexit_guard_changedmoving tosevered, which means a browser lost its address mid-session
Logs
RUST_LOG controls verbosity, and log_json switches to machine-readable lines, which is what you want wherever something other than a person reads them.
Crash reporting is off by default and needs both a switch and a destination. On an anti-detect product, telemetry nobody asked for is the kind of surprise that costs the customer relationship rather than just producing a report.
Watching disk
Three things grow: profile directories, activity stills, and video files.
| What | Bounded by |
|---|---|
| Activity stills | [runs] shots_max_gb and shots_max_age_days. |
| Artifacts | [mcp] artifact_quota and artifact_ttl_secs. |
| Videos | Nothing automatic. GET /v1/videos/storage says what they cost. |
| Profiles | Nothing automatic. A browser directory grows the way any browser's does. |
Next
- Events: the frames to build an alert on.
- Configuration: the settings named here.
- Troubleshooting: what the numbers mean when they go wrong.
Run it on your own machine
Seven days to try it with your own agents on your own sites. Starting the trial needs a card.