first commit
This commit is contained in:
@@ -0,0 +1,76 @@
|
||||
# job-scheduler-otel
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs -->
|
||||
## 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).
|
||||
Reference in New Issue
Block a user