# telemetry _(no submodules)_ ## Purpose OTel self-telemetry for `@suaveplan/campaigns`. Exposes a small set of counters and histograms that are emitted from every meaningful operation in the package — campaign creation, lifecycle transitions, send dispatches, batch planning, and failures. The instruments resolve against the globally registered `MeterProvider` via `@opentelemetry/api`; when no provider is registered, the OTel API returns no-op meters, so importing this module is always safe in production code that has not opted into telemetry. Centralising the meter and record helpers in one module keeps the instrumentation surface explicit and prevents feature modules from drifting into ad-hoc, untagged metrics. ## Features - Five counters: `campaigns_created_total`, `campaigns_transitions_total`, `campaigns_sends_total`, `campaigns_batches_planned_total`, `campaigns_failures_total`. - Two histograms: `campaigns_batch_plan_size` (recipient count per plan) and `campaigns_send_duration_ms` (estimated total send-window duration in ms). - Record helpers (`recordCampaignCreated`, `recordTransition`, `recordSend`, `recordBatchesPlanned`, `recordFailure`, `recordBatchPlanSize`, `recordSendDuration`) so call sites stay readable. - Lazy meter resolution via `metrics.getMeter("@suaveplan/campaigns")` so the module has zero side effects beyond the OTel API itself. - Per-instrument descriptions and units (`ms`, `{contact}`) so dashboards can label axes correctly. ## Usage: Basic ```ts import { recordCampaignCreated, recordSend } from "@suaveplan/campaigns"; recordCampaignCreated("broadcast", "email"); recordSend("email"); ``` ## Usage: Advanced Pair the histogram with the planner output for percentile dashboards: ```ts import { BatchPlanner, recordBatchPlanSize, recordSendDuration, } from "@suaveplan/campaigns"; const planner = new BatchPlanner(); const contacts = await audience.resolve(campaign.audienceConfig); const batches = planner.planBatches(contacts, { batchSize: 250 }); // planBatches() already records both metrics; helpers are exported so // callers can mirror the recording from custom dispatch loops too. recordBatchPlanSize(contacts.length); recordSendDuration(planner.calculateTotalDuration(contacts.length)); ``` ## API Reference - `campaignsCreatedCounter`, `campaignTransitionsCounter`, `campaignSendsCounter`, `batchesPlannedCounter`, `campaignFailuresCounter` — OTel `Counter` instances. - `batchPlanSizeHistogram`, `sendDurationHistogram` — OTel `Histogram` instances. - `recordCampaignCreated(type, channel)`, `recordTransition(from, to, event)`, `recordSend(channel)`, `recordBatchesPlanned(count)`, `recordFailure(channel)`, `recordBatchPlanSize(count)`, `recordSendDuration(ms)` — record helpers. ## Implementation Notes The meter is acquired once at module load time. Because `getMeter` is idempotent and the OTel API guarantees safe no-op behaviour when no provider is registered, the helpers can be called unconditionally from hot paths. Counters carry low-cardinality labels (`type`, `channel`, `from`, `to`, `event`) — never per-tenant or per-campaign identifiers, which would explode metric series. Add such labels via downstream OTel views if needed.