System Monitor
v0.1.0System monitor — stats collector and TUI dashboard for Wippy applications
Install
wippy add butschster/monitorSystem Monitor
Reusable monitoring toolkit for Wippy applications. Provides a stats collector and HTTP endpoint that any app can include as a dependency.
Installation
Add to your _index.yaml:
- name: dep.monitor
kind: ns.dependency
component: butschster/monitor
version: "*"
Add local replacement to wippy.lock (for development):
replacements:
- from: butschster/monitor
to: ../../monitor/src
Components
Stats Collector (monitor:collector)
Library that collects all system data in a single call:
local collector = require("collector")
local stats = collector.collect_stats()
-- stats.hostname — string
-- stats.pid — number
-- stats.cpu_count — number
-- stats.max_procs — number
-- stats.goroutines — number
-- stats.mem_stats — table (heap_alloc, heap_sys, stack_in_use, num_gc, ...)
-- stats.services — table[] (id, status, desired, retry_count, started_at)
-- stats.modules — table[] (name, description, class)
-- stats.total_entries — number
-- stats.entry_counts — table {[kind] = count}
-- stats.entry_details — table {[id] = {kind, meta}}
-- stats.collected_at — number (unix nanoseconds)
Import in your _index.yaml:
imports:
collector: monitor:collector
Stats Collector Process (monitor:collector.process)
Long-running process that responds to "collect" messages with a stats snapshot. Registers as "monitor.collector" in
the process registry for cross-node discovery.
# Add to your _index.yaml
- name: monitor.service
kind: process.service
process: monitor:collector.process
host: app:processes
lifecycle:
auto_start: true
Requesting stats from another process:
-- Look up the collector (works across cluster nodes)
local pid = process.registry.lookup("monitor.collector")
process.send(pid, "collect")
-- Response arrives in inbox as topic "monitor.stats"
local msg = inbox:receive()
local stats = msg:payload():data()
HTTP Stats Endpoint (monitor:stats)
Function that returns system stats as JSON. Mount on any HTTP router:
- name: debug.stats
kind: http.endpoint
method: GET
path: /debug/system
function: monitor:stats
Response:
{
"hostname": "myhost",
"pid": 1234,
"cpu_count": 4,
"goroutines": 23,
"memory": {
"alloc": 12419072,
"heap_alloc": 12419072,
"heap_sys": 25624576,
"heap_objects": 8421,
"stack_in_use": 524288,
"num_gc": 15
},
"services": [
{
"id": "app:http.server",
"status": "running",
"retry_count": 0
}
],
"total_entries": 12,
"entry_counts": {
"function.lua": 5,
"process.service": 3
},
"collected_at": 1707744000000000000
}
Cluster Monitoring
In cluster mode, each node runs a collector.process service. A monitor can discover all nodes and collect stats from
each:
┌─── Node A ──────────┐ ┌─── Node B ──────────┐
│ monitor:collector │ │ monitor:collector │
│ (process.service) │ │ (process.service) │
│ registered as │ │ registered as │
│ "monitor.collector" │ │ "monitor.collector" │
└──────────┬───────────┘ └──────────┬───────────┘
│ process.send(pid) │
└────────────┬────────────┘
│
┌───────▼───────┐
│ Monitor │
│ (any node) │
└───────────────┘
- Subscribe to cluster events for node discovery
- Look up
"monitor.collector"on each node via process registry - Send
"collect"to each — responses arrive via inbox - Aggregate and render
Registry Entries
| Entry | Kind | Purpose |
|-----------------------------|----------------|-------------------------------------|
| monitor:collector | library.lua | Importable stats collection library |
| monitor:collector.process | process.lua | Long-running collector process |
| monitor:stats | function.lua | HTTP endpoint returning JSON stats |