Move docs/ package mirror into document-navigator plugin
Relocate the ~6k-file docs tree from the repo root into plugins/document-navigator/docs/ so the plugin is self-contained and portable. docs/superpowers/ (specs and plans) stays at the repo root. Moved via cp+rm rather than git mv because directory rename() fails with EPERM on this WSL /mnt DrvFs mount; git rename-detection pairs the identical-content files at commit time. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,88 @@
|
||||
# `otel/instruments`
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs -->
|
||||
|
||||
## 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
|
||||
|
||||
```ts
|
||||
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`:
|
||||
|
||||
```ts
|
||||
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.
|
||||
Reference in New Issue
Block a user