5.9 KiB
OpenSpec Change: network-observability-consolidation
- Change ID: network-observability-consolidation
- Affects:
@suaveplan/network-plugin-monitor✅ (shipped — extended)@suaveplan/network-observability(upstream — folded in OR migrated as new plugin)
- Category: universal
- Status: PROPOSED (decision required at execution time)
- Date: 2026-05-11
- Parent:
network-transport-family(2026-05-11) — Wave 6 - Migration source:
../suaveplan/packages/universal/network-observability+../suaveplan/enterprise/network-observability.md
Summary
Resolve the duplication between upstream @suaveplan/network-observability (application-monitoring observability layer for the mesh) and shipped @suaveplan/network-plugin-monitor ✅ (peer-quality + RTT/loss scorers + alert thresholds + OTel wiring across 12 modules). Both target the same problem space — network-tier telemetry.
This proposal does not write code. It captures the decision and the resulting work.
Decision required: fold vs. plugin
Option A — Fold into network-plugin-monitor (recommended)
The shipped plugin already covers peer-quality scoring, RTT/loss, alert thresholds, and OTel. Upstream network-observability adds application-monitoring abstractions (probably topology metrics, event aggregation, dashboard primitives) — fold those into the shipped plugin as additional feature modules.
Pro: single canonical telemetry surface. Pro: no new package. Pro: consumers don't choose between two overlapping options.
Con: network-plugin-monitor grows. Mitigation: keep feature modules in their own subdirs, each ≤300 LOC.
Option B — Ship as separate @suaveplan/network-plugin-observability
Two plugins compose: monitor handles peer-quality, observability handles application-monitoring abstractions.
Pro: smaller plugins. Pro: tree-shake observability when not needed.
Con: consumers must wire both. Con: feature-creep boundary becomes blurry.
Recommendation: A. This proposal proceeds under A unless audit reveals upstream network-observability contains a fundamentally different abstraction (e.g. event-aggregation pipeline that doesn't fit the monitor plugin's per-peer model).
Current-state audit (perform at execution time)
Upstream coverage: 100%. Investigate what network-observability actually contains beyond what network-plugin-monitor ships:
ls ../suaveplan/packages/universal/network-observability/src/
diff <(grep -rh "^export" ../suaveplan/packages/universal/network-observability/src/) \
<(grep -rh "^export" packages/network/network-plugin-monitor/src/)
Outcome of audit determines fold-or-split.
Parity Checklist (FINAL — audit complete 2026-05-12)
Decision: Option A — fold into @suaveplan/network-plugin-monitor.
Audit revealed upstream network-observability contains exactly three feature modules — all of them are output / export adapters for an external metric collector, not a fundamentally different application-monitoring abstraction:
| Capability | Upstream | Existing (monitor) |
Verdict |
|---|---|---|---|
| Per-peer quality scoring | 🚫 not present | ✅ | already covered |
| RTT / loss collectors | 🚫 not present | ✅ (MetricCollector, NetworkMonitor) |
already covered |
| Alert thresholds | 🚫 not present | ✅ (AlertEngine) |
already covered |
| OTel wiring (internal) | 🚫 not present | ✅ (@opentelemetry/api instruments across 12 modules) |
already covered |
| Prometheus exposition (text format) | ✅ via prom-client |
🚫 | ⬆️ folded as prometheus/ (rewritten universal-tier, hand-rolled emitter; no prom-client dep) |
| Grafana dashboard JSON generator + presets | ✅ | 🚫 | ⬆️ folded as grafana/ (pure data builder, injectable Rng) |
| OTel SDK exporter bridge | ✅ via external SDK | 🚫 (uses @opentelemetry/api directly per genesis convention) |
❌ NOT folded — redundant; genesis monitor already emits via @opentelemetry/api so external SDKs pick up metrics natively |
| Application-monitoring abstractions | 🚫 not present in upstream src | n/a | n/a |
| Event-aggregation pipeline | 🚫 not present in upstream src | n/a | n/a |
| Topology metrics | 🚫 not present in upstream src | (handled by network-plugin-topology ✅) |
n/a |
Why fold and not split: the upstream "package" is 1159 LOC total, only ~600 LOC of which is portable (prom-client and external @opentelemetry/sdk are deliberately not universal-tier and would taint a sibling). After portability filtering, only the Prometheus text emitter (~150 LOC) and Grafana JSON builder (~370 LOC) survive — too small for a sibling plugin, and they consume the existing monitor's MetricCollector.scrape() output directly. Folding makes a single canonical telemetry surface.
Why the OTel SDK exporter is dropped, not folded: the upstream otel-exporter.ts (293 LOC) is an adapter that wraps prom-client metrics into @opentelemetry/sdk-metrics observable instruments. Genesis's network-plugin-monitor already declares its instruments through @opentelemetry/api's MeterProvider — any externally-registered OTel SDK (@suaveplan/opentelemetry's NoopSdk/SdkFactory, or a user's NodeSDK) picks them up natively. The bridge is structurally redundant.
Acceptance gate
- Audit performed; Option A or B chosen with documented rationale.
- Bare
@suaveplan/network-observabilityrow removed fromSTATUS.md(becomes either folded-into-monitor or shipped asnetwork-plugin-observability). bunx turbo lint typecheck test --filter='@suaveplan/network-plugin-monitor'(or new plugin) green.bunx turbo test:coverage100/100/100/100 on the resulting package(s).STATUS.mdupdated; supersession table extended.
Out of scope
- Cross-process observability federation (separate
network-plugin-observability-otlpif needed). - Custom dashboard rendering (UI tier).