Files
skills/docs/persistence/storage/storage-uri-plugin-bundle/src/otel/otel.md
2026-05-29 08:20:56 +01:00

3.3 KiB

OpenTelemetry wiring

(no submodules)

Purpose

otel.ts exposes the tracer, meter, and instrument bag that every read path in @suaveplan/storage-uri-plugin-bundle records against. It mirrors the convention used by @suaveplan/storage-uri/otel and @suaveplan/storage-plugin-cache/otel: lazy instrument acquisition, test-injectable MeterProvider, and a single recordOp entry point that emits the histogram, the success/error counter, and the per-op span in one call so the call site never forgets one of the three.

The module also carries the small helpers that the rest of the package relies on for span-attribute hygiene: sanitiseRelPathAttr strips query strings and truncates to 256 chars, and classifyRootKind maps a URL to the file | http | data | blob | other label used on every span and counter.

Features

  • bundle_uri.op_duration_ms{op, root_kind, outcome} histogram.
  • bundle_uri.reads_total{root_kind, outcome} counter.
  • bundle_uri.errors_total{root_kind, code} counter.
  • bundle_uri.range_fallback_total{root_kind} counter.
  • bundle_uri.cache_hits_total{root_kind} and bundle_uri.cache_misses_total{root_kind} counters.
  • Per-op span on the @suaveplan/storage-uri-plugin-bundle tracer with bundle.package, bundle.rel_path, bundle.root_kind, bundle.outcome attributes.
  • setBundleUriMeterProvider(provider) + resetInstruments() for deterministic test injection.

Usage: Basic

import { recordOp } from "@suaveplan/storage-uri-plugin-bundle";

recordOp({
    op: "get",
    rootKind: "http",
    outcome: "success",
    durationMs: 12,
    packageSlug: "my-pkg",
    relPath: "assets/x.wav",
});

Usage: Advanced

import {
    setBundleUriMeterProvider,
    resetInstruments,
} from "@suaveplan/storage-uri-plugin-bundle";
import { MeterProvider } from "@opentelemetry/sdk-metrics";

const provider = new MeterProvider({});
setBundleUriMeterProvider(provider);
resetInstruments();
// …run instrumented code, then drain `provider` to read observations.

API Reference

  • getInstruments(force?) — lazy-build the bag; force=true rebuilds.
  • setBundleUriMeterProvider(provider | undefined) — test injection.
  • resetInstruments() — drop the cached bag.
  • recordOp(input) — one-call emission of histogram + counter + span.
  • recordRangeFallback(rootKind) — increment fallback counter.
  • recordCacheHit(rootKind) / recordCacheMiss(rootKind) — cache-path counters.
  • sanitiseRelPathAttr(relPath) — strip query + truncate to 256 chars.
  • classifyRootKind(rootUrl) — URL → BundleUriRootKind.
  • BundleUriOp, BundleUriOutcome, BundleUriInstruments, RecordOpInput — supporting types.

Implementation Notes

The instrument bag is held in a module-private let so the same instruments persist across calls. resetInstruments is the test-only escape hatch that drops the cache so the next getInstruments rebinds against the freshly-installed MeterProvider. The 256-char clip is applied after the query strip — query-string lengths are not counted against the attribute size budget. classifyRootKind is a switch over URL.protocol (which always ends with :); the default case covers bundler-virtual schemes (virtual:, ~asset:, \0…) so coverage includes the "other" branch.