first commit
This commit is contained in:
@@ -0,0 +1,106 @@
|
||||
# `idempotency-metrics`
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs -->
|
||||
## 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.
|
||||
Reference in New Issue
Block a user