first commit

This commit is contained in:
2026-05-29 08:20:56 +01:00
commit 949299f58d
6368 changed files with 527176 additions and 0 deletions

View File

@@ -0,0 +1,93 @@
# `otel/instruments` — OpenTelemetry instruments for the rate-limit plugin
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## Purpose
Builds (and caches) the bundle of OpenTelemetry instruments the
rate-limit plugin emits on every check. Operators wiring an SDK at
boot get accurate counters and histograms without the plugin owning
the SDK lifecycle. Tests installing an `InMemoryMetricExporter` can
call `resetRateLimitInstruments()` to force a re-bind against the
freshly-installed provider, so assertions run against real meter
output rather than a snapshot taken before the provider was swapped
in.
The bundle covers the four signals operators actually alert on: total
checks (with outcome), denials (subset of checks), check duration, and
bypasses (with reason).
## Features
- Lazy, idempotent meter construction — first call binds against the
global provider; subsequent calls return the cached bundle.
- `resetRateLimitInstruments()` drops the cache so the next call
re-binds; required for test isolation across files.
- Counters and histograms carry stable units and descriptions so the
collector's metadata pipeline can render dashboards correctly.
- Compatible with `@opentelemetry/sdk-metrics` in-memory exporters,
Prometheus exporters, and OTLP exporters out of the box.
## Usage: Basic
```ts
import { getRateLimitInstruments } from "@suaveplan/api-plugin-rate-limit";
const instruments = getRateLimitInstruments();
instruments.checksTotal.add(1, { outcome: "allowed", routeId: "default" });
```
## Usage: Advanced
```ts
import {
InMemoryMetricExporter,
MeterProvider,
PeriodicExportingMetricReader,
} from "@opentelemetry/sdk-metrics";
import { metrics } from "@opentelemetry/api";
import {
getRateLimitInstruments,
resetRateLimitInstruments,
} from "@suaveplan/api-plugin-rate-limit";
const exporter = new InMemoryMetricExporter(/* … */);
const reader = new PeriodicExportingMetricReader({
exporter,
exportIntervalMillis: 1_000,
});
const provider = new MeterProvider({ readers: [reader] });
metrics.setGlobalMeterProvider(provider);
resetRateLimitInstruments();
const instruments = getRateLimitInstruments();
// every subsequent check() records into `exporter`.
```
## API Reference
- `interface RateLimitInstruments` — bundle of the four instruments:
`checksTotal: Counter`, `denialsTotal: Counter`,
`checkDurationMs: Histogram`, `bypassedTotal: Counter`.
- `function getRateLimitInstruments(): RateLimitInstruments` — lazy
accessor; returns the cached bundle bound to the current global
meter provider.
- `function resetRateLimitInstruments(): void` — drops the cache.
## Implementation Notes
- The meter name is `@suaveplan/api-plugin-rate-limit` so collectors
can route metrics from this plugin to a dedicated scope without
pattern-matching attribute values.
- `checksTotal` and `denialsTotal` are intentionally overlapping —
alerting on the rejection RATE is easier when the denominator
(`checksTotal`) and numerator (`denialsTotal`) live in the same
metric family.
- The `outcome` attribute on `checksTotal` is one of
`"allowed" | "denied" | "bypassed"`; the `routeId` attribute is the
rule's `id` (or `"default"`); the `tenantId` attribute is present
only when the request carried a resolved tenant.
- Counter additions and histogram records are intentionally
fire-and-forget — the OpenTelemetry API is non-blocking and any
collector backpressure is the SDK's concern, not the plugin's.