Initial Commit

This commit is contained in:
2026-05-27 23:29:53 +01:00
commit fbc70f96e6
10000 changed files with 1102152 additions and 0 deletions

View File

@@ -0,0 +1,107 @@
# otel/instruments
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## Purpose
OpenTelemetry instrument bundle for the vault plugin: four counters and
one histogram covering the full CRUD surface. Every route handler reads
the cached bundle at the start of the call, records the metric on
success or failure, and forwards through to the next layer. Cached
binding ensures repeated handler calls do not redundantly call
`metrics.getMeter(...)` on every request.
## Features
- `vault.items.created_total{outcome}` — counter incremented on every
`POST /vault/items`. `outcome ∈ "success" | "failure"`.
- `vault.items.read_total{outcome}` — counter incremented on every
`GET /vault/items` or `GET /vault/items/:id`.
- `vault.items.updated_total{outcome}` — counter incremented on every
`PATCH /vault/items/:id`.
- `vault.items.deleted_total{outcome}` — counter incremented on every
`DELETE /vault/items/:id`.
- `vault.item.size_bytes` — histogram of item body byte sizes,
sampled on successful create + update. Unit `By` (bytes).
- `resetVaultPluginInstruments()` clears the cache so tests can install
a fresh `MeterProvider` between cases.
## Usage: Basic
```ts
import { getVaultPluginInstruments } from "@suaveplan/api-plugin-vault";
const instruments = getVaultPluginInstruments();
instruments.itemsCreatedTotal.add(1, { outcome: "success" });
instruments.itemSizeBytes.record(body.length);
```
## Usage: Advanced
```ts
import {
AggregationTemporality,
InMemoryMetricExporter,
MeterProvider,
PeriodicExportingMetricReader,
} from "@opentelemetry/sdk-metrics";
import { metrics } from "@opentelemetry/api";
import {
getVaultPluginInstruments,
resetVaultPluginInstruments,
} from "@suaveplan/api-plugin-vault";
const exporter = new InMemoryMetricExporter(
AggregationTemporality.CUMULATIVE
);
const reader = new PeriodicExportingMetricReader({
exporter,
exportIntervalMillis: 60_000,
});
const provider = new MeterProvider({ readers: [reader] });
metrics.setGlobalMeterProvider(provider);
resetVaultPluginInstruments();
const instruments = getVaultPluginInstruments();
instruments.itemsCreatedTotal.add(1, { outcome: "success" });
await provider.forceFlush();
const points = exporter.getMetrics();
```
## API Reference
### `VaultPluginInstruments`
Readonly record:
- `itemsCreatedTotal: Counter`
- `itemsReadTotal: Counter`
- `itemsUpdatedTotal: Counter`
- `itemsDeletedTotal: Counter`
- `itemSizeBytes: Histogram`
### `getVaultPluginInstruments(): VaultPluginInstruments`
Returns the cached bundle, creating it lazily against the current
global `MeterProvider`. Safe to call from hot paths — subsequent calls
return the cached reference.
### `resetVaultPluginInstruments(): void`
Drops the cached bundle. Used in test setup to re-bind against a
freshly installed provider.
## Implementation Notes
- The meter name is `@suaveplan/api-plugin-vault` — match this when
configuring an exporter filter to isolate vault-plugin telemetry.
- The histogram's `unit: "By"` (OTel canonical for bytes) is required
for downstream tooling to recognise it as a size distribution rather
than a duration. Operators visualising in Grafana SHOULD set the
panel unit accordingly.
- The `outcome` label is the only attribute emitted with the counters
— kept low-cardinality on purpose. Per-tenant or per-route
partitioning happens at the OTel-collector layer, not at the
instrument site.