Reusable monitoring toolkit for Wippy applications. Provides a stats collector and HTTP endpoint that any app can include as a dependency.
Add to your _index.yaml:
- name: dep.monitor
kind: ns.dependency
component: butschster/monitor
version: "*"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:collectorLong-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: trueRequesting 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()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:statsResponse:
{
"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
}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
| 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 |