Files
suaveplan/openspec/archive/2026-05-12-enterprise-network-observability/proposal.md
2026-05-27 23:29:53 +01:00

5.8 KiB
Raw Blame History

OpenSpec Change: enterprise-network-observability

  • Change ID: enterprise-network-observability
  • Package: @suaveplan/network-observability
  • Category: universal/network
  • Target path: universal/network/network-observability
  • Status: SUPERSEDED-BY-GENESIS-WAVE
  • Date: 2026-04-24

Summary

Deliver @suaveplan/network-observability on the genesis branch from scratch at enterprise quality. The package provides network metrics collection and distributed tracing instrumentation: RTT measurements, bandwidth estimation, connection health scoring, packet loss tracking, span propagation across network hops, and structured event emission for network anomalies. Genesis adds structured errors via @suaveplan/error, Zod schemas for all metric types, deep OTel integration (this package is specifically about observability), AbortSignal on collection tasks, injectable Clock for measurement timestamps, and event-bus emission for threshold breaches.


Current-state audit (genesis)

The package does not exist on genesis yet — this is a fresh build.


Available workspace deps on genesis

Package Role
@suaveplan/error (workspace:^) Base class for NetworkObservabilityError; stable error codes
@suaveplan/types (workspace:^) LoggerLike, Clock, EventBusLike
@suaveplan/events (workspace:^) Event bus for threshold breach notifications
@suaveplan/logger (workspace:^) Structured logging
@suaveplan/timing (workspace:^) Stopwatch and throttle for measurement intervals
zod (catalog:forms) Zod schemas for all public metric types
@opentelemetry/api (catalog:observability) Deep OTel integration — this package enriches OTel spans
tslib (catalog:build) Runtime helpers

Dev deps: vitest, @vitest/coverage-istanbul, fast-check (all catalog:testing).


Public API surface

Core

function createNetworkMonitor(options?: NetworkMonitorOptions): NetworkMonitor

interface NetworkMonitor {
  start(signal?: AbortSignal): Promise<void>
  stop(): void
  snapshot(): NetworkSnapshot
  history(limit?: number): ReadonlyArray<NetworkSnapshot>
  on(event: NetworkEvent, handler: (data: NetworkSnapshot) => void): () => void
}

Metric types

interface NetworkSnapshot {
  readonly timestamp: number
  readonly rtt: RttMetrics
  readonly bandwidth: BandwidthMetrics
  readonly packetLoss: PacketLossMetrics
  readonly health: NetworkHealthScore
}

interface RttMetrics {
  readonly current: number
  readonly min: number
  readonly max: number
  readonly avg: number
  readonly p50: number
  readonly p95: number
  readonly p99: number
  readonly samples: number
}

interface BandwidthMetrics {
  readonly downloadBps: number
  readonly uploadBps?: number
  readonly estimatedAt: number
}

interface PacketLossMetrics {
  readonly rate: number  // 0–1
  readonly total: number
  readonly lost: number
}

interface NetworkHealthScore {
  readonly score: number  // 0–100
  readonly grade: 'excellent' | 'good' | 'fair' | 'poor' | 'critical'
  readonly factors: ReadonlyArray<HealthFactor>
}

interface HealthFactor {
  readonly name: string
  readonly weight: number
  readonly score: number
  readonly impact: 'positive' | 'negative' | 'neutral'
}

Span propagation

function injectTraceContext(headers: Record<string, string>): Record<string, string>
function extractTraceContext(headers: Record<string, string>): SpanContext | null
function withNetworkSpan<T>(name: string, fn: () => Promise<T>, attributes?: NetworkSpanAttributes): Promise<T>

interface NetworkSpanAttributes {
  url?: string
  method?: string
  statusCode?: number
  requestSize?: number
  responseSize?: number
}

Options

interface NetworkMonitorOptions {
  measureIntervalMs?: number
  historySize?: number
  rttTargetUrl?: string
  thresholds?: NetworkThresholds
  logger?: LoggerLike
  clock?: Clock
  eventBus?: EventBusLike
}

interface NetworkThresholds {
  maxRttMs?: number
  minBandwidthBps?: number
  maxPacketLossRate?: number
  minHealthScore?: number
}

type NetworkEvent = 'snapshot' | 'threshold-breach' | 'recovery'

Error codes

type NetworkObservabilityErrorCode =
  | 'NET_OBS_MEASUREMENT_FAILED'
  | 'NET_OBS_MONITOR_ALREADY_RUNNING'
  | 'NET_OBS_ABORT'

function registerNetworkObservabilityErrorCodes(): void

Genesis additions

  1. Structured NetworkObservabilityError with stable NET_OBS.* codes
  2. Zod schemas for all metric types and options
  3. Health scoring algorithm — weighted composite of RTT, packet loss, bandwidth; grades A–F
  4. W3C Trace Context propagation helpers (injectTraceContext, extractTraceContext)
  5. Threshold alerting — emits event-bus events when thresholds are breached or recovered
  6. Injectable Clock for deterministic timestamp tests
  7. OTel deep integration — this package is the entry point for network-layer OTel spans

File layout

universal/network/network-observability/
  package.json
  tsconfig.json
  vitest.config.ts
  src/
    index.ts
    error-codes.ts
    constants/
      index.ts
    types/
      common.ts
      common.md
    core/
      monitor/
        monitor.ts
        monitor.md
        monitor.types.ts
        monitor.test.ts
        index.ts
      health/
        health.ts
        health.md
        health.test.ts
        index.ts
    tracing/
      propagation.ts
      propagation.md
      propagation.test.ts
      index.ts
    metrics/
      rtt.ts
      rtt.md
      rtt.test.ts
      bandwidth.ts
      bandwidth.md
      bandwidth.test.ts
  tests/
    integration.test.ts
    property.test.ts

Impact

Workspace dep prerequisites: @suaveplan/error, @suaveplan/types, @suaveplan/events, @suaveplan/logger, @suaveplan/timing must be published.