Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Lx9FNLG2CqeBbVGGd9bFsP
3.4 KiB
Developer notes
Building the UI into the binary
make build runs make web first: npm run build in web/, then web/dist is copied to
internal/webui/dist, which //go:embed packs into the binary. internal/webui/dist is git-ignored
(only .gitkeep is tracked), so a build never dirties the tree. A plain go build without make web
embeds a one-line "UI not built" page from internal/webui/placeholder/.
nmon serves the UI at /. Unknown paths fall back to index.html for the client-side router, except
/api/, /docs, /openapi*, /metrics and /schemas, which belong to the API. Files under /assets/
are content-hashed and sent immutable; index.html is no-cache; text assets are served gzipped.
OpenAPI compatibility
scripts/openapi-check.sh compares the current spec (nmon openapi, else openapi.json) with
openapi.json at the latest m*/v* tag and fails on a removed route or method, a removed response
field, a changed field type, a new required parameter or request field, or a removed enum value. A tag
without openapi.json passes with a note. OPENAPI_NEW=file.json compares that file instead and
OPENAPI_BASE_TAG=m3 picks the base. The comparison is internal/openapidiff.
nmon-devtools (separate dev binary)
Developer helpers in their own executable, make devtools -> nmon-devtools; the shipped nmon does not contain them and never links the simulator. They need a running nmon serve --insecure-http.
backfill writes synthetic history straight into the hot store so graphs have 30 days of data without waiting 30 days:
nmon-devtools backfill --hot-url http://127.0.0.1:PORT --device SLUG --iface ULID [--iface ULID...] \
[--days 31] [--step 60s] [--pattern diurnal|flat] [--mean-mbps N]
Per interface it writes ifHCInOctets, ifHCOutOctets (monotonic, diurnal rate with noise and bursts) and
ifOperStatus, ending one step before the first live sample. When live samples exist the history is shifted
so its last value joins the live counter with no reset (this needs a live counter larger than the history,
about 3e13 bytes for 31 days at 100 Mbit/s; otherwise a warning says the join will look like a reset).
The hot URL is in the serve log (metric stores up hot=...). Samples older than hot retention are dropped
by the store.
seed-demo builds a small simulated network and back-fills it, for the gate and for screenshots:
nmon serve --data-dir D --insecure-http --poll-interval 10s ...
nmon-devtools seed-demo --api http://127.0.0.1:8443 --hot-url http://127.0.0.1:PORT \
[--env-out env] [--counters-rec testdata/snmprec/counters.snmprec]
It starts the simulated SNMP agents in-process on [::1], each on its own port (passed to the API as snmp.port), adds the devices through the API (a 48-port switch, access switches, routers, a firewall, a UPS, the counters fixture, a v1 device with 32-bit counters, and one whose agent is stopped after seeding so it reads as down), waits for live polls, back-fills 31 days, writes NMON_DEVICE, NMON_DEVICE_48, NMON_DEVICE_32BIT and NMON_DEVICE_DOWN to --env-out, and keeps the agents answering until interrupted. The simulated 64-bit counters start at 1e14 so history fits below them.
Gates
make gate-m3 runs everything above end to end and writes live screenshots to docs/screenshots/M3/.
It needs Playwright's chromium: cd web && npx playwright install chromium.