# Extending PearData ## Add a chart / context 1. Define the chart in `shared/metrics.js` (`STATIC_CHART_DEFS`, or `registerChart()` for instances). 2. Emit samples from `server/services/collector.js` (or a new collector module). 3. Store + REST/RPC pick it up automatically via `getAllChartDefs()` / `CHART_BY_ID`. 4. Ensure the chart lands in the Charts wall TOC via `shared/taxonomy.js` (`sectionForChart` matchers). Prefer a real section over **Other**. 5. Document dimensions in [DATA-MODEL.md](./DATA-MODEL.md). 6. The desktop Charts tab picks it up automatically (no per-chart HTML). Overview spotlight is optional. Coverage is asserted by `test/taxonomy-coverage.test.js`. ## Add an RPC method ### `shared/protocol.js` ```js export const MethodRoles = Object.freeze({ // ... listContainers: Roles.viewer, restartCollector: Roles.admin, }) ``` ### `shared/schema.js` Validate args. ### `server/services/…` + `server/handlers/monitor.js` Register with `session.respond(...)`. Use `{ hot: true }` for high-frequency paths. ### Client ```js await manager.request(Methods.listContainers, {}) ``` ### Docs + tests Update [PROTOCOL.md](./PROTOCOL.md) and add a brittle test. ## Add a REST route Edit `server/rest/routes.js` — keep stable `/api/v3/...` path naming. ## Add a job Register in `server/services/jobs.js` `JOB_HANDLERS`. ```js retrainAnomaly: async (args) => getAnomalyEngine().retrain(getStore(), args) ``` Operators run via `runJob` (`retrainAnomaly` is registered). ## Add a collector plugin (pattern) ``` server/services/collectors/ docker.js # PEARDATA_DOCKER=1 — cgroup + Docker socket names (installer auto-enables) peardock.js # bridge (planned) ``` Have `pipeline.js` start each enabled collector; all emit `samples` batches into the same store. ### Docker collector (shipped spike) 1. Set `PEARDATA_DOCKER=1` on the agent (or re-run the installer when Docker is present). 2. Ensure `peardata` can read the socket (`usermod -aG docker peardata` + unit `SupplementaryGroups=… docker`). 3. Charts: `docker.containers`, `docker.cpu.`, `docker.mem.` (stable ids); **titles/families** use human names (`dozzle · CPU`). 4. Discovery: cgroup v2 `docker-*.scope` / `libpod-*.scope`; names via `loadContainerNameMap` (unix HTTP API → `docker ps` → filesystem) + Compose labels (`shared/container-names.js`). 5. Cgroups collector reuses the same name map so `cgroup.*` cards are not bare hashes. 6. UI: [user-guide/containers.md](../user-guide/containers.md). ### Process top-N collector 1. Default **on** for Linux (`PEARDATA_PROCESSES=0` to disable charts). Optional `PEARDATA_PROCESSES_TOP=8`. 2. Charts: `processes.top_cpu` / `top_rss` / `top_io` / `top_threads` (dimensions = process comm names). 3. Desktop **Processes** tab + RPC `listProcesses` / `GET /api/v3/processes` — per-PID live table (not just top-N charts). 4. Linux `/proc` only; safe no-op on other platforms. ### Nginx stub_status plugin 1. Set `PEARDATA_NGINX=1` and `PEARDATA_NGINX_URL=…`. 2. Charts: `nginx.connections`, `nginx.requests`. 3. Base class: `server/services/collectors/plugin.js` (`CollectorPlugin`). ### Redis INFO plugin 1. Set `PEARDATA_REDIS=1` and optional `PEARDATA_REDIS_URL`. 2. Charts: `redis.memory`, `redis.clients`, `redis.stats`. ### Postgres plugin 1. Set `PEARDATA_POSTGRES=1` (+ host/port). 2. Charts: `postgres.up` (TCP probe); optional `postgres.stats` via `PEARDATA_POSTGRES_STATS_URL`. ### Export / Prometheus push - Job `exportSnapshot` / RPC `exportSnapshot` / REST `GET /api/v3/export` - Job `prometheusPush` → `PEARDATA_PUSHGATEWAY_URL` - Optional file write: `PEARDATA_EXPORT_DIR` ### Webhook notifications 1. Set `PEARDATA_WEBHOOK_URL=https://…` and optional `PEARDATA_WEBHOOK_SECRET`. 2. When a secret is set, requests include: - `X-PearData-Timestamp` - `X-PearData-Signature: sha256=` 3. Verify with `verifyWebhookSignature` from `server/services/notify.js`. 4. Desktop: toggle “Desktop notifications” in the Anomalies panel. ### z-score / retrain 1. `PEARDATA_ANOMALY_MODE=zscore|hybrid` for rolling z-score fires. 2. Job `retrainAnomaly` (operator) refits warn/crit from store history (`mean ± z·stdev`). 3. Helpers live in `server/services/zscore.js`. ### REST HyperDHT tunnel (holesail-style) 1. `PEARDATA_REST_TUNNEL=1` (+ optional `PEARDATA_REST_TUNNEL_SEED`). 2. Agent announces a HyperDHT key that proxies TCP → local REST. 3. Inspect: `GET /api/v3/tunnel` or `getServerInfo.restTunnel`. ### PearDock bridge 1. Set `PEARDATA_PEARDOCK=1` and `PEARDATA_PEARDOCK_PEERS=,…`. 2. Bridge dials peers, reads `getAllMetrics`, remaps `docker.*` → `peardock.*`. 3. Prefer public APIs / your own modules when integrating with PearDock (both are AGPL-3). ## Parent peer (fleet aggregator) Shipped opt-in spike: 1. Set `PEARDATA_PARENT=1` and `PEARDATA_PARENT_PEERS=,…`. 2. Parent dials children over HyperDHT (`PearDataConnection`), polls health + metrics. 3. Emits `fleet.cpu`, `fleet.ram`, `fleet.children` into the local store. 4. REST: `GET /api/v3/nodes` (multi), `/api/v3/fleet`, `/api/v3/stream_path`. 5. RPC: `getFleetHealth`, `listChildPeers`. ## PearDock / PearVirt hooks - Prefer **RPC adapters** over scraping: call dock/virt methods, map to PearData contexts. - PearData is AGPL-3.0-only — see [LICENSE](../LICENSE). Depend on public APIs when integrating sibling projects. ## Desktop chrome Keep ``, titlebar drag regions, and `pear.gui.resizable`. See [DESKTOP.md](./DESKTOP.md). ## Rebrand (fork) ```bash npm run rename -- my-monitor MyMonitor ``` Review invite prefix / env prefix, then `npm test`.