first commit
This commit is contained in:
@@ -0,0 +1,98 @@
|
||||
# crypto-vault — OpenTelemetry instruments
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs -->
|
||||
## Purpose
|
||||
|
||||
`instruments.ts` holds the full OTel instrument set emitted by
|
||||
`@suaveplan/crypto-vault` production paths. The module exposes a lazy
|
||||
singleton that defers `metrics.getMeter(...)` until first use, so loading
|
||||
the package does nothing observable when no exporter is wired up. Every
|
||||
instrument is safe-by-construction — no key bytes, salts, plaintext, or
|
||||
user-identifiable data appears in attributes.
|
||||
|
||||
## Features
|
||||
|
||||
- Lazy `getCryptoVaultInstruments()` accessor — first call materialises the
|
||||
instrument set against the global meter; subsequent calls hit the cached
|
||||
set.
|
||||
- `setCryptoVaultMeterProvider(provider)` lets tests register a deterministic
|
||||
in-memory `MeterProvider` and then assert against captured observations.
|
||||
- `resetCryptoVaultInstruments()` clears the cache so tests can re-run with a
|
||||
fresh provider without leaking state.
|
||||
- Counters and histograms covering Argon2id derivations, HKDF derivations,
|
||||
zeroization, SecureBuffer allocations / zeroizations, and the SRP-6a
|
||||
handshake.
|
||||
|
||||
## Usage: Basic Example
|
||||
|
||||
```ts
|
||||
import { getCryptoVaultInstruments } from "@suaveplan/crypto-vault/otel";
|
||||
|
||||
const i = getCryptoVaultInstruments();
|
||||
i.argon2idDurationMs.record(143.2);
|
||||
i.secureBufferAllocateTotal.add(1, { length: "32" });
|
||||
```
|
||||
|
||||
## Usage: Advanced Example
|
||||
|
||||
```ts
|
||||
import {
|
||||
getCryptoVaultInstruments,
|
||||
resetCryptoVaultInstruments,
|
||||
setCryptoVaultMeterProvider,
|
||||
} from "@suaveplan/crypto-vault/otel";
|
||||
|
||||
class CountingMeter {
|
||||
public readonly events: Array<[string, number]> = [];
|
||||
public createHistogram = (name: string) => ({
|
||||
record: (v: number) => this.events.push([`hist:${name}`, v]),
|
||||
});
|
||||
public createCounter = (name: string) => ({
|
||||
add: (v: number) => this.events.push([`ctr:${name}`, v]),
|
||||
});
|
||||
}
|
||||
const meter = new CountingMeter();
|
||||
setCryptoVaultMeterProvider({ getMeter: () => meter as unknown as never });
|
||||
|
||||
getCryptoVaultInstruments().secureBufferZeroizeTotal.add(1);
|
||||
console.log(meter.events); // [["ctr:crypto_vault.secure_buffer.zeroize.total", 1]]
|
||||
|
||||
setCryptoVaultMeterProvider(undefined);
|
||||
resetCryptoVaultInstruments();
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
### `getCryptoVaultInstruments(): CryptoVaultInstruments`
|
||||
|
||||
Returns the cached instrument set, building it on first call against the
|
||||
global OTel meter.
|
||||
|
||||
### `setCryptoVaultMeterProvider(provider?)`
|
||||
|
||||
Replace the meter provider used by subsequent
|
||||
`getCryptoVaultInstruments()` calls. Pass `undefined` to revert to the
|
||||
global default.
|
||||
|
||||
### `resetCryptoVaultInstruments(): void`
|
||||
|
||||
Clear the cache so the next `getCryptoVaultInstruments()` re-acquires the
|
||||
meter. Tests use this to defeat singleton leakage between suites.
|
||||
|
||||
### `CryptoVaultInstruments`
|
||||
|
||||
Bag of `Counter` and `Histogram` instances. Field names map to the metric
|
||||
names listed under "Features".
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
- The cache is intentionally module-level — production code should not need
|
||||
per-instance instrument sets. Tests that want isolation register a
|
||||
provider, run their assertions, then reset.
|
||||
- Metric names follow the OTel semantic-conventions style:
|
||||
`<package>.<feature>.<dimension>_<unit>`.
|
||||
- The package never adds key material, vault IDs, item IDs, salts, or email
|
||||
addresses to instrument attributes. The only attributes used are
|
||||
fixed-cardinality status / outcome strings.
|
||||
Reference in New Issue
Block a user