Files
skills/docs/api-stack/api/api-rate-limit/src/instruments/instruments.md
2026-05-29 08:20:56 +01:00

2.8 KiB

instruments

(no submodules)

Purpose

Owns the rate-limit OTel instrument registry. Today the package emits exactly one counter — api.rate_limit.exceeded_total{plugin, route, key_kind} — which the design doc §12.4 lists as the canonical rate-limit denial signal. The factory wraps the OTel global meter-provider lookup so production gets real export when an SDK is installed and tests get a no-op when one is not.

Features

  • RATE_LIMIT_COUNTER_NAMES frozen tuple — drives both factory construction AND the conformance test that asserts each name is present on the returned bundle.
  • createRateLimitInstruments({ meterProvider? }) — explicit override precedence beats the global, so the middleware tests can assert exact .add call counts against an injected fake provider.
  • Returned object is Object.freeze-d so accidental mutation surfaces immediately rather than silently breaking downstream label invariants.

Usage: Basic

import { createRateLimitInstruments } from "@suaveplan/api-rate-limit/instruments";

const instruments = createRateLimitInstruments();
instruments.counters["api.rate_limit.exceeded_total"].add(1, {
    plugin: "billing",
    route: "POST /invoices",
    key_kind: "principal",
});

Usage: Advanced

Wire a captured meter-provider to assert exactly-once denial increments under a deterministic clock:

import type { MeterProvider } from "@opentelemetry/api";
import { createRateLimitInstruments } from "@suaveplan/api-rate-limit/instruments";

declare const fakeProvider: MeterProvider; // captures every .add() call
const instruments = createRateLimitInstruments({ meterProvider: fakeProvider });
// drive the middleware against the fake clock, then assert
// fakeProvider's recorded .add() invocations match the denial transitions

API Reference

  • const RATE_LIMIT_COUNTER_NAMES: readonly ["api.rate_limit.exceeded_total"]
  • type RateLimitCounterName = (typeof RATE_LIMIT_COUNTER_NAMES)[number]
  • interface RateLimitInstruments { counters: Readonly<Record<RateLimitCounterName, Counter>> }
  • interface RateLimitInstrumentsConfig { meterProvider?: MeterProvider }
  • function createRateLimitInstruments(config?: RateLimitInstrumentsConfig): RateLimitInstruments

Implementation Notes

The package deliberately does NOT install an SDK — that's an operator concern. When no SDK is registered, the OTel no-op meter-provider returns no-op counters whose .add() is a function-call no-op, so this module is hot-path safe even with default config. The host's own HostInstruments already declares the same counter name; both emit, both reach the same exporter — OTel aggregates correctly because the meter name is the only difference and the SDK merges series by name + label-set.