Initial Commit
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
# `instruments`
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs -->
|
||||
|
||||
## Purpose
|
||||
|
||||
Builds the OTel instrument bundle the header tenant resolver emits on every
|
||||
`resolve()` invocation. Centralising instrument creation keeps the resolver
|
||||
factory free of meter plumbing — the resolver simply records against the
|
||||
frozen counter returned here. The counter name (`api.tenant.resolves_total`)
|
||||
follows the API plugin system design doc §6 step 4 so a missing entry
|
||||
is a spec deviation a CI gate could detect.
|
||||
|
||||
The instrument is wired against the OTel global meter provider by default,
|
||||
which falls back to a no-op implementation when no SDK is installed. Tests
|
||||
need not configure a provider; production hosts register their SDK once at
|
||||
boot and the resolver picks it up automatically.
|
||||
|
||||
## Features
|
||||
|
||||
- One counter: `api.tenant.resolves_total` labelled
|
||||
`{ resolver: "header", outcome }`.
|
||||
- `outcome` attribute drawn from a closed five-value union
|
||||
(`resolved`, `absent`, `invalid`, `not_found_in_registry`,
|
||||
`untrusted_source`) so dashboards can break down resolver behaviour.
|
||||
- Optional `meterProvider` injection for tests that want a captive
|
||||
provider; defaults to the OTel global.
|
||||
|
||||
## Usage: Basic
|
||||
|
||||
```ts
|
||||
import { createHeaderResolverInstruments } from "@suaveplan/api-tenant-resolver-header/instruments";
|
||||
|
||||
const instruments = createHeaderResolverInstruments();
|
||||
instruments.resolvesTotal.add(1, { resolver: "header", outcome: "resolved" });
|
||||
```
|
||||
|
||||
## Usage: Advanced
|
||||
|
||||
```ts
|
||||
import { MeterProvider } from "@opentelemetry/sdk-metrics";
|
||||
import { createHeaderResolverInstruments } from "@suaveplan/api-tenant-resolver-header/instruments";
|
||||
|
||||
const provider = new MeterProvider();
|
||||
const instruments = createHeaderResolverInstruments({
|
||||
meterProvider: provider,
|
||||
});
|
||||
// hook instruments.meter into a Prometheus exporter to scrape
|
||||
// `api_tenant_resolves_total{resolver="header",outcome="invalid"}` etc.
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
- `interface HeaderResolverInstruments` — `{ meter, resolvesTotal }`.
|
||||
- `type HeaderResolveOutcome` — five-value union of outcome attribute
|
||||
values.
|
||||
- `function createHeaderResolverInstruments(config?: { meterProvider? })`
|
||||
— returns a frozen instrument bundle.
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
The bundle is frozen with `Object.freeze` so consumers cannot accidentally
|
||||
swap the counter instance at runtime. The counter is created lazily-per-
|
||||
resolver-instance rather than module-level so a host that wants different
|
||||
meter providers per host instance (multi-tenant test harness) can wire each
|
||||
resolver separately.
|
||||
|
||||
A counter — not a histogram — is the right primitive here because the
|
||||
quantity being observed is the count of resolver invocations broken down by
|
||||
outcome, not a duration. Resolver latency is dominated by the registry
|
||||
probe; hosts that need probe latency wire a histogram around their
|
||||
`TenantRegistryProbe` rather than expecting this package to time it.
|
||||
Reference in New Issue
Block a user