# `@suaveplan/license` — otel/instruments _(no submodules)_ ## Purpose OpenTelemetry instrumentation for the license package. Registers a single `@opentelemetry/api` meter (`@suaveplan/license@0.1.0`) and attaches three instruments to it: a generation counter, a validation counter (attribute `license.valid: boolean`), and a validation-duration histogram (unit `ms`). When no SDK is wired the meter falls back to the Noop implementation, so importing this module has zero side effects in production unless the host application registers a real provider. ## Features - `license.generate_total` — counter incremented once per successful `generateLicense` call. - `license.validate_total` — counter incremented per validation call with attribute `license.valid: boolean` (and, on failure, `license.error` carrying the enum value). - `license.validate_duration_ms` — histogram of validation latency in milliseconds. - Five `ATTR_*` constants exported so call sites and tests reference attribute keys by name, not by stringly-typed literals. ## Usage: Basic ```ts import { ATTR_LICENSE_VALID, licenseValidateTotal, } from "@suaveplan/license/otel/instruments"; licenseValidateTotal.add(1, { [ATTR_LICENSE_VALID]: true }); ``` ## Usage: Advanced Wire an in-memory provider for tests and assert that the instruments emit: ```ts import { metrics } from "@opentelemetry/api"; import { AggregationTemporality, InMemoryMetricExporter, MeterProvider, PeriodicExportingMetricReader, } from "@opentelemetry/sdk-metrics"; const exporter = new InMemoryMetricExporter(AggregationTemporality.CUMULATIVE); const reader = new PeriodicExportingMetricReader({ exporter, exportIntervalMillis: 60_000 }); const provider = new MeterProvider({ readers: [reader] }); metrics.setGlobalMeterProvider(provider); // ...exercise the license package... await provider.forceFlush(); console.log(exporter.getMetrics()); ``` ## API Reference ### Instruments - `licenseGenerateTotal: Counter` - `licenseValidateTotal: Counter` - `licenseValidateDurationMs: Histogram` ### Attribute keys - `ATTR_LICENSE_VALID = "license.valid"` - `ATTR_LICENSE_ERROR = "license.error"` - `ATTR_LICENSE_TIER = "license.tier"` - `ATTR_LICENSE_PRODUCT_ID = "license.product_id"` - `ATTR_LICENSE_SIGNING_KEY_ID = "license.signing_key_id"` ## Implementation Notes The meter is fetched at module load via `metrics.getMeter(...)`. The `@opentelemetry/api` library guarantees that subsequent calls with the same name+version return the same meter instance, so importing `instruments.ts` from multiple call sites does not create duplicate counters. The Noop fallback means `licenseGenerateTotal.add(...)` is a zero-cost call when no SDK is wired — safe to leave the instrumentation on in every code path.