Monitoring
Live CPU, memory, disk and network for every server, app and database, with a short rolling history.
How it works
Each agent opens one telemetry stream to the control plane and pushes metrics for the whole host: the machine itself and every container on it. The control plane keeps a short rolling window in memory, roughly the last quarter of an hour, at a cost of about half a megabyte per server.
That is why charts are full the instant a page opens rather than drawing themselves from nothing, and why per-app monitoring has no switch to turn on: the data was already flowing.
Where to look
| Page | Shows |
|---|---|
| Monitoring in the sidebar | Every server: CPU, memory, disk, network |
| An app's Monitoring tab | That app's containers, plus disk I/O, with the resource limits that apply |
| A database's Monitoring tab | The same for the engine |
An app's and a database's Monitoring tab both name the server they run on in their header, with a Manage button beside it for instance admins: the same chart reads very differently depending on which machine it came from.
With more than one server, the Monitoring page opens on the fleet: one row per host with its CPU trend and its three percentages. Click a row to point the panels below at that host, or use the searchable picker at the top of the page to jump straight to one by name or address. With a single server both are skipped and the panels are the page.
The list sits under the selected host's own gauges and charts, not above them: the page answers "how is the one I picked" first.
The list is ordered worst first - by whichever of CPU, memory or disk is fullest - so the hosts worth a look are the ones you see without scrolling. Past six servers it scrolls rather than pushing the charts off the screen, and the selected host is scrolled back into view whenever you pick one.
A row says two more things when there is something to say: Agent outdated
when the host is behind the current agent, and an info marker when it is
sampling through docker stats instead of cgroups, which costs it noticeably
more CPU. Manage on each row opens that server's own page - its agent,
cleanup policy, team access and uninstall. It only appears for instance
admins, because those pages are theirs.
Reading the numbers
Every figure here is meant to match what the same machine reports in a
shell. Sizes are binary (KiB, MiB, GiB), the units df, free, htop
and docker use, so a disk they call 132G is 132 GiB here too.
A server
| Reading | What it means |
|---|---|
| CPU | Percentage of the whole machine. Time spent waiting on a disk counts as idle, exactly as htop shows it by default. |
| Memory | Total minus available, the same figure free prints in its used column. The tile's info marker splits it: processes is what programs hold, cache is what the kernel will hand back the moment something needs it. |
| Disk | The filesystem holding the agent's data directory, reported the way df reports it: same size, same used, same percentage. |
| Network | Only the machine's real network interfaces. Docker bridges and container veth devices carry the same bytes a second time, so they are left out. |
| Load | The kernel's 1, 5 and 15 minute averages, unchanged. |
Memory looks higher than in htop
Both are right, they answer different questions. Deplo and free count
cache that cannot be reclaimed as used; htop counts all of it as free.
The gap is usually a few percent, and the processes / cache split in the
tile's tooltip is exactly the difference.
What the arcs measure
CPU, memory and disk are drawn as arcs, and an arc only means something against a ceiling. Here the ceiling is the whole machine, and the caption under each number says what that machine has. The arc turns amber past 80%.
An app or a database
| Reading | What it means |
|---|---|
| CPU | The arc fills against the ceiling that really applies: the resource limit when one is set, otherwise the whole machine, and the caption names it (2.99 cores of 8 cores). The chart below keeps the raw convention docker stats and htop use, a percentage of one core, so three busy cores read as 300% there and the axis grows past 100% rather than flattening the line. |
| Memory | Measured against the machine's RAM. Set a resource limit and it reads against that limit instead, aggregated over the running containers. |
| Network | Counted once per network namespace. A sidecar sharing another container's network reads the same counters, so the table marks it network shared with <container> and the stack total counts it once. |
| Disk I/O | Bytes read and written to block devices by the stack's containers. |
| Status | Per container, in the breakdown table: the healthcheck verdict when the image defines one, otherwise the raw docker state (running, restarting, exited, paused, dead). |
| Restarts | How many times docker has restarted that container. It is what separates a container that is starting from one that has been dying for an hour, and it turns amber the moment it leaves zero. |
A container on the host network
network_mode: host puts a container on the machine's own network, where
the only counters that exist are the machine's. That container is marked
host network and contributes nothing to the app's network chart - its
traffic is on the server's chart instead.
Save metrics on server
One instance-wide switch, in the ⋯ menu at the top right of the
Monitoring page, on by default, changed by anyone holding
manage_monitoring.
Turning it off stops keeping history and clears what is stored. Live charts still work, because they read the stream directly. Turn it off if you would rather that window did not exist at all.
Alerts that come from metrics
The metric stream is also what raises the server and app health alerts, delivered through notifications. See the Servers category there for the full list: Server running hot, Server disk almost full, Server offline and back online, Server cannot run apps, and App keeps restarting.
Limits and gotchas
- History is in memory, not in the database. Restarting the control plane clears it. This is deliberate: metrics are for looking at now, and writing every sample to Postgres would cost far more than it is worth.
- The fleet page needs whole-team access. A member scoped to one folder sees an explicit "outside your access" state, because a fleet view has no meaningful per-folder version.
- A gap in a chart means no data arrived, usually a reconnect. It does not mean the value was zero.
view_metricsis its own capability, grantable per folder like the rest.
If it does not work
- A server shows dashes instead of numbers, or its fleet row reads No data: the stream is not connected. Check that server's health.
- A container's status is blank: that host's agent is too old to report one. An empty Status never means healthy.
- A running container shows no healthcheck verdict: its image defines no
healthcheck, so the status falls back to
running. Nothing is wrong. - An app shows nothing: it is stopped, or its containers are on a server whose agent is not reporting.
- Charts are empty right after a restart: the window is in memory and starts again from scratch.
- A number does not match a shell: check the unit first. Everything here is binary (GiB), and an app's CPU chart is a percentage of one core, not of the machine - its arc is the one drawn against the machine.
See Servers and agents for more.
See also
Did this page help you?