Skip to content

Fix logs viewer going empty (aiodocker log-connection leak) - #105

Merged
kavehtoyser merged 1 commit into
developfrom
fix-log-connection-leak
Sep 11, 2026
Merged

kavehtoyser merged 1 commit into
developfrom
fix-log-connection-leak

Conversation

@kavehtoyser

Copy link
Copy Markdown
Collaborator

Symptom

The dashboard logs page renders empty for a running service (200 response, empty body), while docker logs <container> on the host shows plenty of lines. Seen on the Docker-29 GCP hosts; a manager restart temporarily fixes it.

Root cause

service_logs and manager_logs_stream read logs through a single aiodocker client cached for the manager's entire lifetime (_get_aio_client() → class-level _AIO_CLIENT). Every follow=true stream the browser abandons (closing the logs page) leaves its connection unreleased — the Unclosed connector warnings — so over time the client's aiohttp connection pool exhausts and new log requests hang, which surfaces as an empty logs page.

Verified: the service_logs generator returns instantly in a fresh process/client but hangs in the day-old running manager; direct uvicorn hit times out; a restart restores it.

Fix

Use a fresh aiodocker.Docker() per log request, closed in finally (runs even when the async generator is cancelled on client disconnect), and drop the cached singleton. The connection is always released, so nothing accumulates.

Log requests are infrequent, so a client per request is negligible overhead; and a per-request client also avoids the stale-loop pitfalls of a long-lived cached one.

Notes

🤖 Generated with Claude Code

service_logs and manager_logs_stream read container logs through a single
aiodocker client cached for the manager's whole lifetime (_get_aio_client /
_AIO_CLIENT). Each follow=true stream that the browser abandoned (closing the
logs page) left its connection unreleased ("Unclosed connector"); over time the
client's connection pool exhausted and every log request hung -> the dashboard
logs page rendered empty (200 with an empty body). A manager restart cleared it
temporarily. Reproduced on the Docker-29 GCP hosts, but the leak is
version-agnostic.

Use a fresh aiodocker client per log request and close it in `finally`, so the
connection is always released -- including when the async generator is cancelled
on client disconnect. Removes the degrading cached singleton entirely.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@kavehtoyser
kavehtoyser merged commit 3730777 into develop Sep 11, 2026
14 of 16 checks passed
@kavehtoyser
kavehtoyser deleted the fix-log-connection-leak branch September 11, 2026 09:11
This was referenced Sep 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant