Files
suaveplan/packages/api-stack/api/api-secrets-vault/src/otel/instruments.md
2026-05-27 23:29:53 +01:00

3.1 KiB

otel/instruments

(no submodules)

Purpose

OpenTelemetry instrument bundle for the vault-backed secrets adapter. Owns the three counters the package emits and a lazily- bound cache keyed on the global MeterProvider. The canonical api.secrets.reads_total{backend="vault"} counter is the metric operators correlate across every secrets adapter in the host scope — its label namespace lets a single dashboard ingest reads from env, Bun-native, vault, or future adapters without per-backend counter names.

Features

  • getSecretsVaultInstruments() — returns the cached bundle, binding to the global MeterProvider on first call.
  • resetSecretsVaultInstruments() — drops the cache so the next get rebinds against a freshly-installed MeterProvider. Used in test setup so each spec starts with a clean read.
  • readsTotal — counter for successful resolutions; the adapter always tags backend="vault".
  • writesTotal — counter for set / delete mutations on the fromVault bridge, partitioned by op ∈ "set" | "delete". (The bridge is the only place writes flow; the adapter is read-only.)
  • watcherEmitsTotal — counter for secret.changed events forwarded by the watcher.

Usage: Basic

import { getSecretsVaultInstruments }
    from "@suaveplan/api-secrets-vault/otel";

const ins = getSecretsVaultInstruments();
ins.readsTotal.add(1, { backend: "vault" });

Usage: Advanced

Reset + rebind in a test that installs its own MeterProvider:

import { metrics } from "@opentelemetry/api";
import { MeterProvider } from "@opentelemetry/sdk-metrics";
import {
    getSecretsVaultInstruments,
    resetSecretsVaultInstruments,
} from "@suaveplan/api-secrets-vault/otel";

const provider = new MeterProvider({ readers: [/* exporter */] });
metrics.setGlobalMeterProvider(provider);
resetSecretsVaultInstruments();

const ins = getSecretsVaultInstruments();
ins.readsTotal.add(1, { backend: "vault" });

API Reference

  • interface SecretsVaultInstruments
    • readonly readsTotal: Counter
    • readonly writesTotal: Counter
    • readonly watcherEmitsTotal: Counter
  • getSecretsVaultInstruments(): SecretsVaultInstruments
  • resetSecretsVaultInstruments(): void

Implementation Notes

The cache holds the bundle across calls so production paths pay the metrics.getMeter cost once per process. Each counter description is human-readable; api.secrets.reads_total is intentionally a generic name with a backend attribute rather than api.secrets.vault.reads_total so cross-adapter aggregations are single-counter operations on the metrics backend.

Calling resetSecretsVaultInstruments between tests is mandatory when a new MeterProvider is installed — otherwise the cached counters point at a stale provider and the new exporter sees zero emissions even though add(1) was called. The vitest setup at tests/setup/polyfills.ts installs its provider before any source import, so the first get already binds against it; tests then call reset only when they need to verify counter emission against a fresh exporter state.