import { type Counter, type Histogram, metrics } from "@opentelemetry/api"; /** * Bundle of OpenTelemetry instruments emitted by the vault plugin. * * - `itemsCreatedTotal{outcome}` — incremented on every `POST /vault/items`. * - `itemsReadTotal{outcome}` — incremented on every `GET /vault/items/:id` or * `GET /vault/items` listing. * - `itemsUpdatedTotal{outcome}` — incremented on every `PATCH /vault/items/:id`. * - `itemsDeletedTotal{outcome}` — incremented on every `DELETE /vault/items/:id`. * - `itemSizeBytes` — histogram of item body byte size, sampled on * successful create + update. * * `outcome ∈ "success" | "failure"`. */ export interface VaultPluginInstruments { readonly itemsCreatedTotal: Counter; readonly itemsReadTotal: Counter; readonly itemsUpdatedTotal: Counter; readonly itemsDeletedTotal: Counter; readonly itemSizeBytes: Histogram; } let cached: VaultPluginInstruments | undefined; /** * Lazily build (and cache) the vault-plugin instruments bundle against * the current global `MeterProvider`. Call `resetVaultPluginInstruments()` * in test setup to force a re-bind against a freshly-installed provider. */ export function getVaultPluginInstruments(): VaultPluginInstruments { if (cached !== undefined) return cached; const meter = metrics.getMeter("@suaveplan/api-plugin-vault"); cached = { itemsCreatedTotal: meter.createCounter("vault.items.created_total", { description: "Total vault-item create attempts, partitioned by outcome label", }), itemsReadTotal: meter.createCounter("vault.items.read_total", { description: "Total vault-item read attempts, partitioned by outcome label", }), itemsUpdatedTotal: meter.createCounter("vault.items.updated_total", { description: "Total vault-item update attempts, partitioned by outcome label", }), itemsDeletedTotal: meter.createCounter("vault.items.deleted_total", { description: "Total vault-item delete attempts, partitioned by outcome label", }), itemSizeBytes: meter.createHistogram("vault.item.size_bytes", { description: "Distribution of vault-item body sizes in bytes (create + update)", unit: "By", }), }; return cached; } /** * Drop the cached instrument bundle so the next * `getVaultPluginInstruments()` call binds against whichever * `MeterProvider` is globally registered at that moment. Tests call * this after installing a fresh provider. */ export function resetVaultPluginInstruments(): void { cached = undefined; }