# otel _(no submodules)_ ## Purpose Owns the OpenTelemetry instrument bag for `@suaveplan/storage-uri`: meter, tracer, and the six counter + one histogram metrics emitted on every resolver operation. The module is intentionally side-effect-free at import time; instruments are created lazily on first access so tests can swap in an in-memory `MeterProvider` before any measurement is recorded. The same module also owns the URI redaction helper `redactUri(uri)` used by `StorageUriResolver.#run` to strip query strings and fragments from the `storage.uri` span attribute before emission — presigned-URL secrets must never leak into telemetry sinks. ## Features - Lazy instrument cache rebuilt automatically when the meter provider changes via `setStorageUriMeterProvider(provider)`. - Six counters: `reads_total`, `writes_total`, `deletes_total`, `errors_total`, `stream_fallback_total`, `buffered_write_total`. - One histogram: `op_duration_ms` with `{op, scheme, outcome}` attributes. - `redactUri(uri)` — drops `?query` and `#fragment` segments. ## Usage: Basic ```ts import { recordOp } from "@suaveplan/storage-uri/otel"; recordOp({ op: "read", scheme: "file", outcome: "success", durationMs: 12 }); ``` ## Usage: Advanced ```ts import { metrics } from "@opentelemetry/api"; import { setStorageUriMeterProvider, resetInstruments } from "@suaveplan/storage-uri/otel"; const provider = new MyInMemoryMeterProvider(); setStorageUriMeterProvider(provider); resetInstruments(); // ... run resolver ops ... const snapshot = provider.collect(); ``` ## API Reference - `setStorageUriMeterProvider(provider | undefined): void` - `getInstruments(force?: boolean): StorageUriInstruments` - `resetInstruments(): void` - `recordOp({ op, scheme, outcome, durationMs, code? }): void` - `recordStreamFallback(scheme: string): void` - `recordBufferedWrite(scheme: string): void` - `redactUri(uri: string): string` - Types: `StorageUriOp`, `StorageUriOutcome`, `RecordOpInput`, `StorageUriInstruments`. ## Implementation Notes `recordOp` routes the success counter by op category (`read`/`open`/`stat`/ `exists`/`list` → reads, `write` → writes, `remove` → deletes) so consumers need not subscribe to seven separate counters. Errors always increment `errors_total` with the resolved `STORAGE_URI.*` code on the `code` attribute. The instrument cache is intentionally module-local rather than class-bound — the resolver is constructed many times in tests, but the instrument bag is provider-scoped, not resolver-scoped.