# instruments _(no submodules)_ ## Purpose `getDeliveryTrackingInstruments` lazily constructs and caches the OTel `Counter` set used by every production code path in `@suaveplan/delivery-tracking`. Centralising the instrument names here keeps metric semantics consistent and makes the package observable via any `MeterProvider` configured by the host application. The instruments are bound to a `Meter` named `@suaveplan/delivery-tracking`. Tests install a real `InMemoryMetricExporter` + `MeterProvider` in `tests/setup/polyfills.ts` and assert counter totals using the exporter's snapshot — no mocking is involved, satisfying CLAUDE.md rule 2 ("no mocks"). ## Features - Lazy singleton; instruments are created on first call and reused. - `resetDeliveryTrackingInstruments()` clears the cache for test isolation. - Five counters with stable names: `delivery_tracking.tracked.total`, `delivery_tracking.deduped.total`, `delivery_tracking.webhook_parsed.total`, `delivery_tracking.token_issued.total`, `delivery_tracking.token_rejected.total`. - All counters carry attribute hints (event_type, channel, provider, kind) that callers should pass when incrementing. ## Usage: Basic ```ts import { getDeliveryTrackingInstruments } from "@suaveplan/delivery-tracking/otel"; const i = getDeliveryTrackingInstruments(); i.trackedCounter.add(1, { event_type: "sent" }); ``` ## Usage: Advanced ```ts import { metrics } from "@opentelemetry/api"; import { MeterProvider, PeriodicExportingMetricReader, InMemoryMetricExporter, AggregationTemporality, } from "@opentelemetry/sdk-metrics"; import { getDeliveryTrackingInstruments, resetDeliveryTrackingInstruments, } from "@suaveplan/delivery-tracking/otel"; const exporter = new InMemoryMetricExporter(AggregationTemporality.CUMULATIVE); metrics.setGlobalMeterProvider( new MeterProvider({ readers: [ new PeriodicExportingMetricReader({ exporter, exportIntervalMillis: 60_000, }), ], }) ); resetDeliveryTrackingInstruments(); const i = getDeliveryTrackingInstruments(); i.webhookParsedCounter.add(3, { provider: "sendgrid" }); ``` ## API Reference - `getDeliveryTrackingInstruments(): DeliveryTrackingInstruments` — returns the cached set; constructs on first call. - `resetDeliveryTrackingInstruments(): void` — clears the cache; intended for test setup. - `interface DeliveryTrackingInstruments` — `meter`, `trackedCounter`, `dedupedCounter`, `webhookParsedCounter`, `tokenIssuedCounter`, `tokenRejectedCounter`. ## Implementation Notes The lazy-init pattern is necessary because the global `MeterProvider` is usually set after module import. Constructing the counters at module top-level would bind them to the no-op default provider; constructing inside the accessor lets the test harness install its provider in `setupFiles` before any source module imports.