Files
skills/docs/foundation/flow/job-scheduler/src/otel/job-scheduler-otel.md
2026-05-29 08:20:56 +01:00

3.0 KiB

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 Histograms and Counters — 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

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

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).