The /targets page is owl's live view of where data is coming from
right now. Three sections, each rendered only when its source is
configured.
Targets that need credentials (bearer token, Basic auth, custom
headers) are configured via the optional auth block — see
Authentication for the full surface.
Scrape targets
HTTP endpoints owl pulls on a schedule. One row per target, with the last scrape time, duration, sample count and error if any. Includes:
- Targets declared in
config.ymlundertargets:. - Targets auto-discovered from container labels by the docker integration (see Docker integration).
- The bundled
owl-selftarget, which scrapes owl's own/metrics.
Internal collectors
In-process sources that write directly to storage, bypassing the HTTP scrape pipeline. The aggregate row shows the collector's last tick, duration and the number of samples it produced.
Three kinds today:
| Kind | Source | Enabled by |
|---|---|---|
host |
/proc and /sys parsers, emits node_* series |
host.enabled: true |
docker_metrics |
Docker daemon stats, emits container_* series |
docker.metrics.enabled: true |
docker_discovery |
Docker daemon container list, produces scrape targets | docker.discovery.enabled: true |
The docker_discovery row reports N of M containers opted in so
you can immediately distinguish "the label is missing or wrong" from
"the daemon is unreachable".
Containers
When docker.metrics.enabled is on, owl renders a per-container row
below the collectors table: name, compose service and project (when
labelled), image, last seen, and memory working set. This is the
detail behind the aggregate docker_metrics row — the actual things
owl is observing on the host.
/api/targets
The same data is available as JSON. The response carries up to three top-level keys; each is omitted when its source is not wired, so consumers that only care about scrape targets see the same shape as before the collectors were added.
{
"targets": [
{
"name": "traefik",
"url": "http://traefik:8082/metrics",
"labels": {"job": "traefik", "instance": "traefik"},
"interval": 15000000000,
"last_scrape": "2026-06-07T12:34:56Z",
"last_samples": 142,
"duration": 8000000
}
],
"collectors": [
{
"name": "host",
"kind": "host",
"interval": 5000000000,
"last_collection": "2026-06-07T12:34:58Z",
"duration": 3000000,
"last_samples": 57
},
{
"name": "docker",
"kind": "docker_metrics",
"interval": 10000000000,
"last_collection": "2026-06-07T12:34:55Z",
"duration": 12000000,
"last_samples": 64,
"extra": "8 containers seen"
},
{
"name": "docker-discovery",
"kind": "docker_discovery",
"interval": 30000000000,
"last_collection": "2026-06-07T12:34:30Z",
"duration": 4000000,
"last_samples": 2,
"extra": "2 of 8 containers opted in"
}
],
"containers": [
{
"name": "owl",
"image": "ghcr.io/neverbot/owl:latest",
"compose_service": "owl",
"compose_project": "owl-stack",
"memory_working_set_bytes": 13107200,
"last_seen": "2026-06-07T12:34:55Z"
}
]
}
Durations are nanoseconds (Go's encoding default). Timestamps are RFC 3339 in UTC.