gsw is a low-overhead Linux monitoring agent for processes, Docker containers,
and Go services. It is designed for small servers where a full Prometheus and
Grafana stack would consume too much memory.
It opens no listening ports. Metrics come from /proc, cgroup v2, and optional
loopback-only Go pprof endpoints. Samples are displayed in a terminal dashboard
and stored in a local SQLite database.
- Monitor multiple named services in one process.
- Track services by PID, process name, or stable Docker container name.
- Reattach automatically when a container is recreated.
- Read aggregate container CPU, memory, I/O, and task counts from cgroup v2.
- Track process CPU, RSS, virtual memory, threads, file descriptors, and I/O rates.
- Store per-service history in SQLite with WAL and retention limits.
- Sample Go goroutine counts from optional pprof endpoints.
- Detect sustained goroutine growth using a bounded in-memory trend window.
- Run interactively or as a headless systemd agent.
- Keep all CLI, diagnostics, configuration, and terminal output in English.
- Linux.
- SQLite runtime library.
- Docker CLI and access to
/var/run/docker.sockfor container targets. - cgroup v2 for aggregate container metrics. Process metrics remain available as a fallback when cgroup v2 cannot be read.
Install the SQLite runtime:
# Arch / CachyOS
sudo pacman -S sqlite
# Ubuntu / Debian
sudo apt install libsqlite3-0cargo build --release
sudo install -m 0755 target/release/gsw /usr/local/bin/gswMonitor several containers:
gsw watch \
--service api=container:orvix-api \
--service telephony=container:orvix-telephony \
--service cache=container:llavero \
--interval 5 \
--db server-metrics.dbLegacy single-target commands remain supported:
gsw watch --pid 12345
gsw watch --name api-server --label api
gsw watch --container api-server --label api
gsw watch -- ./server --port 8080CPU 100% means one full logical CPU, following top semantics. A multi-core
service can exceed 100%.
Copy the example and edit service names:
sudo install -d -m 0755 /etc/gsw /var/lib/gsw
sudo install -m 0644 config/gsw.example.toml /etc/gsw/config.toml
gsw watch --config /etc/gsw/config.tomlExample:
database = "/var/lib/gsw/metrics.db"
interval_seconds = 5
pprof_interval_seconds = 30
retention_hours = 168
max_samples = 150000
[[services]]
name = "api"
target = "container:orvix-api"
[[services]]
name = "telephony"
target = "container:orvix-telephony"Supported target formats are pid:123, name:server, and
container:container-name.
The agent command runs the same collector without redrawing a dashboard:
gsw agent --config /etc/gsw/config.tomlInstall the supplied systemd unit:
sudo install -m 0644 packaging/systemd/gsw.service /etc/systemd/system/gsw.service
sudo systemctl daemon-reload
sudo systemctl enable --now gsw
sudo systemctl status gswThe unit applies a 32 MiB memory high-water mark and a 96 MiB hard limit to keep the monitoring agent from becoming a resource problem itself.
/proc and cgroups cannot see goroutines. A Go service must expose pprof on a
private endpoint. Never attach pprof to a public application port.
For Docker, publish a dedicated diagnostics port on loopback only:
ports:
- "127.0.0.1:6060:6060"Then add the URL to the service configuration:
[[services]]
name = "api"
target = "container:orvix-api"
pprof_url = "http://127.0.0.1:6060"The pprof request has a 750 ms timeout and a 128 KiB response limit. It runs on
the slower pprof_interval_seconds schedule rather than every process sample.
Full heap and goroutine profiles are not continuously stored.
gsw summary --db /var/lib/gsw/metrics.db
gsw summary --service telephony --db /var/lib/gsw/metrics.dbRows are grouped by service and local hour. The report includes CPU averages and peaks, RSS averages and peaks, goroutine trends, and peak file descriptor usage.
The default configuration retains seven days of detailed samples and at most 150,000 rows per service. Count-based pruning is partitioned by service, so adding more services does not silently shorten another service's history.
SQLite runs in WAL mode. Do not manually delete the -wal or -shm files while
the agent is running.
See docs/ARCHITECTURE.md for module boundaries, collection flow, and storage decisions.
gsw does not serve HTTP or accept remote input. Docker socket access is highly
privileged; only trusted users should run container monitoring. Pprof endpoints
must remain on loopback or another private transport.