#3703·glances

ENHANCEMENT: allow excluding containers from stats collection entirely, not just from display

Author: gregbert42Created Aug 30, 2026Updated Sep 5, 2026
Labelsenhancementplugin/containers

Context

The containers plugin opens a persistent stats stream and a background thread for every container, unconditionally, and only afterwards discards the ones the user filtered out with show= / hide=.

One fetcher is constructed per container in DockerExtension.update() (glances/plugins/containers/engines/docker.py:311-317), straight from the unfiltered list built at line 298 / 309:

python
# Start new thread for new container
for container in containers:
    if container.id not in self.stats_fetchers:
        ...
        self.stats_fetchers[container.id] = DockerStatsFetcher(container)

and each fetcher immediately opens a streaming GET /containers/{id}/stats (docker.py:53-55):

python
# Threaded Streamer
stats_iterable = container.stats(decode=True)
self._streamer = ThreadedIterableStreamer(stats_iterable, initial_stream_value={})

The user's filter is applied only once those stats are already collected, in ContainersPlugin.update() (glances/plugins/containers/__init__.py:254-270):

python
def is_key_in_container_and_hidden(container):
    return (key := container.get('key')) in container and self.is_hide(nativestr(container.get(key)))
...
_, containers = watcher.update(all_tag=self._all_tag())   # stats already streaming
...
    for container in get_containers_from_updated_watcher(watcher)
    if not is_key_in_container_and_hidden(container)

So a user who has explicitly told Glances to watch a subset still pays the full cost — one stream, one thread, and the daemon-side stats collection — for every container on the host.

Measured here (Glances 4.5.6, Docker 29.7.2, Arch Linux, 44 running containers): 69 open connections to /var/run/docker.sock, all owned by the single Glances process. Stable across a full docker.service restart (re-measured at 69 afterwards).

This is the same axis as #3559 (containers plugin cost at ~60 containers). That issue reduced the per-update inspect cost; this one is about not doing the work at all for containers the user does not want.

Verified against develop and develop-v5: docker.py and containers/__init__.py are byte-identical on the two branches (cmp clean), so one patch covers both.

Proposal

Add a new opt-in config key to [containers] — name up for discussion, e.g.:

ini
[containers]
# Containers to not monitor at all (comma-separated names or regexes).
# Unlike hide=, these are never polled: no stats stream, no thread.
no_stats=transmission_wireguard,some-other-container

matched before the fetcher is constructed in DockerExtension.update(), so no stream is ever opened for them.

Deliberately not proposing a change to hide= semantics. hide= /show= are documented as display filters, and hidden containers are still returned by /api/4/containers. Making them skip collection would silently drop them from the REST API and break existing dashboards. A separate key keeps that contract intact and makes the intent explicit at the call site.

Scope

In scope: the fetcher-creation path in glances/plugins/containers/engines/docker.py (DockerExtension.update()), the new config key and its accessor on ContainersPlugin, the default conf/glances.conf comment block, plus unit tests.

Out of scope:

  • hide= / show= behaviour — unchanged.
  • The containers plugin model, the TUI, and the WebUI. A container excluded via the new key simply never appears in the stats list, exactly as if it were not running.
  • engines/lxd.py.
  • engines/podman.py has the same shape (PodmanContainerStatsFetcher created per container at podman.py:358), so the same change applies there — but I've left it out of scope rather than assume you want it in the same patch. Happy to include it if you'd prefer parity.

Non-regression requirements

  1. With the new key unset (the default), behaviour and open-connection count are identical to today.
  2. hide= and show= keep filtering display only, and hidden containers keep appearing in /api/4/containers.
  3. A container matched by the new key opens no stats stream and starts no thread; its fetcher is torn down if the key is added and the config reloaded.
  4. Adding or removing a container from the key does not leak fetcher threads — the existing absent_containers teardown path (docker.py:320-328) must still run for excluded containers.

Corroborating case

The reason I went looking: haugene/transmission-wireguard moves eth0 out of the container's Docker-managed netns as its VPN kill-switch, so dockerd cannot resolve the interface for stats and logs an error line per stats sample:

bash
dockerd: level=error msg="collecting stats for container /transmission_wireguard: \
failed to retrieve the statistics for eth0 in netns /var/run/docker/netns/...: Link not found"

With Glances streaming, that is ~1 line/second — 375,816 lines in 4 days here. Docker has no daemon-side switch for it (docker/distribution#3216, closed with no fix), and hide=transmission_wireguard does not help for the reason above: the stream keeps running. I've reported the interface naming upstream to the image (haugene/docker-transmission-wireguard#19) and silenced the message locally with a systemd LogFilterPatterns= drop-in, so this is not a request to fix Docker's logging — it's just a concrete case where "stop polling this container" is the only thing that actually addresses the cause, and there is currently no way to express it.