Traffic history. Each node records, once a minute, how many requests each pool served and how many server errors it returned, and keeps a day of it. The Statistics page draws it; the Services page carries a sparkline per service with errors over the requests. Drawn as hand-written SVG — there is no build step and no external script may load.
Alerts when a service loses its servers, from the health checks HAProxy is already running: all servers failing is down, some failing is degraded, both naming the servers and their last check result, and recovery is reported too. Only the node holding the virtual IP says anything about services — every node runs the same checks, and a passive node's view is not the one that matters.
Recovery messages were never delivered, which this uncovered. They are informational and the severity floor defaults to warning, so "X is healthy again", "the node is reachable again" and "the virtual IP is held by one node again" were all dropped: you were told what broke and never that it came back. A recovery now goes out whatever the floor says, provided the alert it closes was actually sent.
The Statistics page no longer blinks. It emptied the whole page and rebuilt it every five seconds, taking the table sorting and any text selection with it. Cards whose figures have not moved are now left alone entirely; one that has changed is rewritten in place.
Also: duplicate-address detection (1.77.0) — the watchdog asks the network who else claims this node's addresses, because two machines using one address is invisible from every layer above it; and the UI no longer points at menus that were renamed, with a check that fails the build if it starts doing so again.
Packages are attached below; the container image is at ghcr.io/avandeputte/haproxy-manager:1.78.1.