# job-scheduler-otel _(no submodules)_ ## Purpose Wires `@opentelemetry/api` metrics for the scheduler. The module exposes a small set of recording helpers — `recordJobRun`, `recordJobDuration`, `incrementJobFailure`, `incrementCronExhausted`, `recordQueueDepth` — that the scheduler and execution modules call at fixed points. Lazy meter / instrument initialisation keeps cold-start cost near zero for callers that never produce metrics. ## Features - One meter (`@suaveplan/job-scheduler`) shared across all instruments. - Lazy-initialised `Histogram`s and `Counter`s — no instrument is created until first use. - Closed-enum `outcome` and `kind` label values (`success | error | timeout`, `cron | queued`) so cardinality is bounded. - Pure side-effect-free getters — the module can be imported in tree-shake audits without producing instruments. ## Usage: Basic Example ```ts import { recordJobRun } from "@suaveplan/job-scheduler"; const start = Date.now(); try { await runHandler(); recordJobRun(Date.now() - start, "success", "queued"); } catch (err) { recordJobRun(Date.now() - start, "error", "queued"); throw err; } ``` ## Usage: Advanced Example ```ts import { incrementCronExhausted, incrementJobFailure, recordJobDuration, recordJobRun, recordQueueDepth, } from "@suaveplan/job-scheduler"; function tick(queueDepth: number): void { recordQueueDepth(queueDepth); } function onCronExhausted(): void { incrementCronExhausted(); } function onJobFinished( durationMs: number, outcome: "success" | "error" | "timeout", kind: "cron" | "queued" ): void { recordJobRun(durationMs, outcome, kind); if (outcome !== "success") incrementJobFailure(kind); if (outcome === "timeout") { recordJobDuration(durationMs, "timeout", kind); } } ``` ## API Reference - `type JobOutcome = "success" | "error" | "timeout"` - `type JobKind = "cron" | "queued"` - `recordJobRun(durationMs, outcome, kind): void` — records duration histogram sample and increments runs counter. - `recordJobDuration(durationMs, outcome, kind): void` — duration-only sample, no counter bump. - `incrementJobFailure(kind): void` — bump failures counter by `kind`. - `incrementCronExhausted(): void` — bump exhausted-cron counter. - `recordQueueDepth(depth): void` — sample current heap depth. ## Implementation Notes All instruments are created exactly once per process via lazy module-scope caches. The OpenTelemetry `metrics` API guarantees stable instrument identity across `getMeter(name).createX` calls only when name + kind + description + unit match — caching here avoids that contract entirely. Label-value enums are closed by TypeScript at the boundary; passing a free-form string would compile-fail. The histograms accept `number` durations; callers compute deltas with the injected scheduler `Clock` (test runs use `FakeClock` so values are deterministic and stable across CI runs).