# `@suaveplan/drive-uri/otel` _(no submodules)_ ## Purpose OpenTelemetry instrumentation surface for `@suaveplan/drive-uri`. Exposes a meter named `@suaveplan/drive-uri` carrying the operation-level counters and duration histogram described in the package spec, plus a tracer of the same name for span emission. The `redactUri` helper strips query strings and fragments from URI attributes so peer hints, seeds, or other secret material never reach span backends. Counters and histograms are lazily created on first access via `getInstruments()` so the package has zero side effects at import time, and `setDriveUriMeterProvider` lets tests inject a stub provider for assertions. ## Features - Lazy instrument bag keyed by the active `MeterProvider`. - Counters: `drive_uri.reads_total`, `drive_uri.writes_total`, `drive_uri.deletes_total`, `drive_uri.errors_total`, `drive_uri.template_hydrations_total`. - Histogram: `drive_uri.op_duration_ms{op, scheme, outcome}`. - Per-op routing helper `recordOp` that increments the correct success or error counter and the duration histogram in one call. Writes increment `writes_total` even on rejection so operator dashboards see misuse rate. - `redactUri(uri)` strips everything from the first `?` or `#` onwards. ## Usage: Basic ```ts import { recordOp, recordTemplateHydration } from "@suaveplan/drive-uri/otel"; recordOp({ op: "read", scheme: "drive", outcome: "success", durationMs: 12 }); recordTemplateHydration("success"); ``` ## Usage: Advanced Test harness swapping in a stub `MeterProvider`: ```ts import { resetInstruments, setDriveUriMeterProvider, } from "@suaveplan/drive-uri/otel"; class StubProvider implements MeterProvider { public meter = new StubMeter(); public getMeter() { return this.meter; } } const provider = new StubProvider(); setDriveUriMeterProvider(provider); resetInstruments(); // ... run code under test, then inspect provider.meter ... setDriveUriMeterProvider(undefined); resetInstruments(); ``` ## API Reference - `setDriveUriMeterProvider(provider | undefined)` — override or revert. - `getInstruments(force = false)` — returns the cached bag or rebuilds. - `resetInstruments()` — clears the cache (used between provider swaps). - `recordOp({ op, scheme, outcome, durationMs, code? })` — one-shot per-operation observation. `op ∈ {open|read|write|stat|exists|remove|list}`. - `recordTemplateHydration(outcome)` — increments `drive_uri.template_hydrations_total{outcome}` by one. - `redactUri(uri): string` — strips `?...` and `#...` suffixes. - Types: `DriveUriOp`, `DriveUriOutcome`, `DriveUriInstruments`, `RecordOpInput`. ## Implementation Notes - `writes_total` carries the `outcome` attribute (`"success"` or `"error"`), letting dashboards split successful (currently impossible) writes from misuse rejections. - `errors_total` is keyed by `scheme` and `code` only — operators slice it by code to attribute failures to root causes (`DRIVE_URI.TEMPLATE_INVALID` vs. `DRIVE_URI.WRITE_UNSUPPORTED` etc.). - The drive-uri tracer is independent of the resolver's `@suaveplan/storage-uri` tracer — both spans fire on a single dispatch, giving operators a per-tier view of the operation. - `redactUri` is content-agnostic; it does NOT validate that the input is a syntactically correct URI. The plugin layer is responsible for rejecting malformed URIs before they reach the span attribute.