Collectors

Bewitch has 9 metric collectors. All implement the Collector interface with Name() and Collect() methods. Collectors run in parallel via goroutines on each tick. The daemon uses a GCD-based tick scheduler to fire each collector at its configured interval.

CPU🔗

Reads per-core CPU usage from /proc/stat. Computes delta percentages between samples. The first sample after startup is discarded (needs a baseline).

Memory🔗

Reads /proc/meminfo for total, free, available, buffers, cached, and swap. Computes used bytes and used percentage.

Disk🔗

Three data sources per mount: space usage (via statfs), I/O rates (via /proc/diskstats), and SMART health (via smartctl or direct device access).

Space🔗

I/O🔗

SMART Health🔗

Reads SMART data per physical device (not per partition). Multiple mounts from the same disk share one SMART read. SMART data is live-only — not stored in the database since it changes slowly.

[collectors.disk]
interval = "30s"
smart_interval = "5m"  # min 30s, "0" to disable
exclude_mounts = ["/boot/efi"]

Network🔗

Reads per-interface bytes from /proc/net/dev. Computes RX/TX bytes per second. Delta-based with first sample discarded.

ECC🔗

Reads ECC memory error counts from /sys/devices/system/edac/. Live-only data — not stored in DB. Useful for servers with ECC memory.

Temperature🔗

Reads hardware sensor temperatures from /sys/class/hwmon/. Caches sensor paths and refreshes every 60 seconds to avoid expensive glob operations.

Power🔗

Reads power consumption from Linux powercap/RAPL zones at /sys/class/powercap/. Delta-based, computes watts from energy counter differences. Caches zone paths (60s refresh).

GPU🔗

Monitors GPU utilization, frequency, power, and memory. Supports Intel iGPUs via intel_gpu_top (long-lived JSON subprocess) and NVIDIA GPUs via nvidia-smi (point-in-time CSV queries). Both backends auto-detect tool availability at startup; if neither is found, the collector produces empty samples.

Intel iGPU🔗

NVIDIA🔗

[collectors.gpu]
# interval = "5s"
# enabled = true  # Intel iGPU via intel_gpu_top, NVIDIA via nvidia-smi

Process🔗

Two-phase collection. Phase 1 cheaply scans all /proc/[pid]/stat files. Phase 2 enriches the top N processes (by CPU/memory) plus pinned processes with expensive data.

Phase 1 (all processes)🔗

Phase 2 (enriched processes)🔗

Process pinning🔗

Pinned processes always receive Phase 2 enrichment regardless of ranking. Useful for monitoring low-resource but critical services.

[collectors.process]
max_processes = 100
pinned = ["nginx*", "postgres", "redis-server"]

Pins can also be set interactively in the TUI with the * key. TUI pins persist in the daemon's preferences database across restarts.

Collector Backoff🔗

When a collector's Collect() returns an error, consecutive failures trigger exponential backoff. The collector skips 2^(n-1) intervals (capped at 64x) before retrying. On success, the failure count resets immediately. First error is always logged; subsequent errors include attempt count and backoff duration.

Parallel Collection🔗

Collectors due on each tick run concurrently, reducing total cycle time. The API cache is updated immediately after collection, then samples are written to the database asynchronously.