# `idempotency-metrics` _(no submodules)_ ## Purpose Provides the `IdempotencyMetrics` class for collecting, aggregating, and reporting idempotency operation statistics. Supports both aggregate lifetime totals and rolling-window statistics for real-time dashboards. Optionally emits OpenTelemetry counters and histograms when a `Meter` is injected, enabling deep observability in OTel-instrumented deployments. ## Features - Aggregate counters: `totalRequests`, `cacheHits`, `cacheMisses`, `conflicts`, `mismatches` - Derived metrics: `hitRate`, `avgExecutionDurationMs`, `duplicateRequests` - Rolling window snapshot via `getWindowedSnapshot()` — configurable window (default: 5 min) - OTel counters: `idempotency.request.total`, `idempotency.store.operation.total`, `idempotency.lock.acquisition.total` - OTel histogram: `idempotency.execution.duration_ms` - Periodic reporting via configurable `MetricsReporter` callback - `reset()` for isolated test scenarios - Fluent `withMeter(meter)` for OTel wiring ## Usage: Basic Example ```ts import { IdempotencyMetrics } from "@suaveplan/idempotency/metrics"; const metrics = new IdempotencyMetrics(); metrics.recordHit(); metrics.recordMiss(); metrics.recordDuration(45); const snap = metrics.getSnapshot(); console.log(snap.hitRate); // 0.5 console.log(snap.avgExecutionDurationMs); // 45 ``` ## Usage: Advanced Example ```ts import { IdempotencyMetrics } from "@suaveplan/idempotency/metrics"; import { metrics as otelMetrics } from "@opentelemetry/api"; const meter = otelMetrics.getMeter("my-service"); const idempotencyMetrics = new IdempotencyMetrics({ reporter: (snap) => logger.info("idempotency snapshot", snap), reportIntervalMs: 30_000, windowMs: 60_000, // 1-minute rolling window }).withMeter(meter); idempotencyMetrics.startReporting(); // ... application runs ... idempotencyMetrics.stopReporting(); ``` ## API Reference ### `new IdempotencyMetrics(config?: IdempotencyMetricsConfig)` | Option | Type | Default | Description | |--------|------|---------|-------------| | `reporter` | `MetricsReporter` | — | Periodic snapshot callback | | `reportIntervalMs` | `number` | `60_000` | Reporting interval (ms) | | `windowMs` | `number` | `300_000` | Rolling window size (ms) | ### `withMeter(meter: Meter): this` Wires up OTel instruments. Chainable. ### `recordHit() / recordMiss() / recordConflict() / recordMismatch(): void` Increment the corresponding counter and push a timestamped event. ### `recordDuration(durationMs: number): void` Record execution latency; updates `avgExecutionDurationMs` and the OTel histogram. ### `recordStoreOperation(operation): void` Increments `idempotency.store.operation.total` with operation label. ### `recordLockAcquisition(result): void` Increments `idempotency.lock.acquisition.total` with result label. ### `getSnapshot(): IdempotencyMetricsSnapshot` Returns aggregate (lifetime) counters and derived metrics. ### `getWindowedSnapshot(): IdempotencyMetricsSnapshot` Returns metrics for the configured rolling window only. Prunes stale events. ### `startReporting() / stopReporting(): void` Start/stop the periodic reporter interval. ### `reset(): void` Clears all counters and events. ## Implementation Notes - Events are kept in a `TimestampedEvent[]` array; `pruneEvents` trims entries older than the rolling window on `getWindowedSnapshot`. - OTel instruments are lazily created; if `withMeter` is never called, no OTel dependency is exercised at runtime. - `stopReporting` is idempotent and safe to call multiple times. - `reset` does not stop the reporter timer; call `stopReporting` first if needed.