Container Metrics Exporter
Build a Prometheus exporter in Go that collects resource usage for every container running on a machine (CPU, memory, network and disk I/O) and exposes it as labeled time series that Prometheus can scrape and Grafana can chart. It reads statistics from the container runtime's API: the Docker Engine API over its Unix socket with net/http, or containerd's gRPC API. Labels include the container name, image and chosen container labels, while keeping the number of series under control. The exporter handles containers starting and stopping, never blocks a scrape on a slow runtime, and reports its own health. You'll learn container resource accounting (cgroups), the Prometheus client library and metric types, talking to runtime APIs over HTTP and gRPC, and testing collectors.
- Estimate
- ~14h
- Steps
- 7
- Completed by
- 0
- Proposed by
- codeseed.app
net/http · gRPC
Project roadmap
- 01
Design the exporter
~2hWrite DESIGN.md: the metrics (container CPU seconds as a counter, memory usage and limit as gauges, network bytes received and sent and disk bytes read and written as counters), their names following Prometheus conventions, the labels (container name, id, image, and an allow-list of container labels, avoiding unbounded values), how often stats are collected (in the background, caching the latest values so scrapes are fast), and the runtime backends (Docker via HTTP, containerd via gRPC). Done when: DESIGN.md lists every metric, label and component.
- 02
Read stats from Docker
~2.5hCreate an http.Client that talks to /var/run/docker.sock through a custom DialContext, list running containers (/containers/json), and fetch each container's stats (/containers/{id}/stats?stream=false) in parallel with a limit and a timeout. Decode the JSON, and compute CPU seconds and memory usage correctly for cgroup v1 and v2. Done when: the tool prints current stats for every running container on your machine.
- 03
Expose Prometheus metrics
~2.5hUsing the prometheus/client_golang library, implement a custom Collector that reports the cached stats on each scrape (so a slow runtime never blocks a scrape), with the chosen labels. Serve /metrics with promhttp, and add the exporter's own metrics: collection duration, errors and number of containers. Done when: curl localhost:9417/metrics shows correct metrics, and promtool check metrics accepts them.
- 04
Handle containers coming and going
~1.5hRefresh the container list on every collection cycle (or watch Docker's events stream), stop reporting containers that disappeared so their series end, and handle containers that stop between listing and fetching stats. Mark stale data when the runtime doesn't answer. Done when: starting and stopping containers updates the metrics correctly, with no stale series left.
- 05
Add a containerd backend with gRPC
~2hAdd a second backend using containerd's Go client (which talks gRPC to containerd's socket) to list containers and read their metrics, behind the same interface as the Docker backend, chosen by a flag. Done when: the exporter reports the same metrics from containerd on a machine running it (for example inside a kind or k3s node).
- 06
Deploy and chart it
~1.5hWrite a Dockerfile (running as a non-root user with read-only access to the socket) and a Docker Compose file with the exporter, Prometheus configured to scrape it, and Grafana with a dashboard showing CPU and memory per container. Done when: the dashboard shows live per-container charts.
- 07
Test it
~2hPut each backend behind an interface and write tests with fake backends returning prepared stats: CPU calculations for both cgroup versions, label handling, containers disappearing, and a slow backend not blocking scrapes. Use testutil.CollectAndCompare to check exact metric output, and test the Docker client against an httptest server on a Unix socket. Done when: go test ./... passes.
Ready to build this?
Get a GitHub repo and start building. Your AI reviewer checks each step as you go.
Tech stack