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,77 @@
# `otel/instruments`
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## Purpose
Provides the lazily-cached bundle of OpenTelemetry instruments emitted by `@suaveplan/api-plugin-database`. Every counter and histogram is created against the global `MeterProvider` resolved by `@opentelemetry/api` at first call; tests install an in-memory provider through the package's setup file and then call `resetDatabaseInstruments()` to force a rebind. Centralising the instruments in one module avoids the surface drift that comes from each call site calling `metrics.getMeter(...)` independently.
The bundle covers the four cross-cutting observability concerns the plugin owns: pool checkouts, pool checkins, current saturation, and query duration. Migration metrics are not duplicated here — `@suaveplan/api-migrations` ships its own `migrations.applied_total` counter through `getMigrationInstruments()`, so the plugin simply lets that package emit when it triggers the runner.
## Features
- Four instruments: two counters (`db.pool.checkouts_total`, `db.pool.checkins_total`), one up-down-counter (`db.pool.saturation`), one histogram (`db.query.duration_ms`).
- Lazy creation so the bundle binds to whichever `MeterProvider` is global at first call.
- `resetDatabaseInstruments()` clears the cache for test reuse.
- Stable meter name `@suaveplan/api-plugin-database` so consumers can query by scope.
## Usage: Basic
```ts
import { getDatabaseInstruments } from "@suaveplan/api-plugin-database/otel/instruments";
const instruments = getDatabaseInstruments();
instruments.poolCheckoutsTotal.add(1);
```
## Usage: Advanced
```ts
import {
getDatabaseInstruments,
resetDatabaseInstruments,
} from "@suaveplan/api-plugin-database";
function instrumentedAcquire(pool, signal) {
const instruments = getDatabaseInstruments();
const start = performance.now();
return pool.acquire(signal).then(
(adapter) => {
instruments.poolCheckoutsTotal.add(1);
instruments.poolSaturation.add(1);
instruments.queryDurationMs.record(performance.now() - start, {
outcome: "success",
});
return adapter;
},
(err) => {
instruments.queryDurationMs.record(performance.now() - start, {
outcome: "error",
});
throw err;
}
);
}
```
## API Reference
### `getDatabaseInstruments()`
Returns `DatabaseInstruments`. First call binds against the global `MeterProvider`; subsequent calls return the same cached object (referential equality).
### `resetDatabaseInstruments()`
Drops the cache so the next `getDatabaseInstruments()` rebuilds. Call in test setup after installing an in-memory provider.
### `interface DatabaseInstruments`
Bundle of: `poolCheckoutsTotal: Counter`, `poolCheckinsTotal: Counter`, `poolSaturation: UpDownCounter`, `queryDurationMs: Histogram`.
## Implementation Notes
- The histogram is intentionally labelled at the call site (`{ outcome }`) rather than baked into the instrument name; this keeps cardinality bounded and the OpenTelemetry shape aligned with the W3C semantic conventions.
- The bundle does NOT include a migration counter — `@suaveplan/api-migrations` ships its own. Mixing them here would emit duplicate signals against the same meter name.
- `metrics.setGlobalMeterProvider(provider)` BEFORE the first call is mandatory in tests; the bundle is captured at first call and reused.