# sampler _(no submodules)_ ## Purpose `Sampler` collects periodic snapshots of runtime metrics (memory usage by default, plus caller-supplied custom metrics). The timer source is injected through a `TimersLike` so tests can advance virtual time deterministically and so non-`setInterval` runtimes (Workers, Deno, embedded JS) can plug in their own scheduler. Sample storage is capped via FIFO eviction so long-running collectors don't leak memory. ## Features - Zod-validated options (`intervalMs > 0`, optional positive `maxSamples`, optional `captureMemory`). - Injectable `Clock`, `TimersLike`, and `MemoryProbe` — the defaults read `Date.now`, `setTimeout`/`clearTimeout`, and `process.memoryUsage`/`performance.memory` respectively. - `start()` / `stop()` are idempotent — double-`start` and double-`stop` are no-ops. - `takeSample(customMetrics?)` records a single sample on demand; same code path used by the scheduled tick. - `getSamples()` / `getSamplesInRange(start, end)` / `clear()` for retrieval and reset. - `events: EventBus` emits `sampler:start`, `sampler:stop`, `sampler:sample`. - Telemetry: `profiler_samples_total` counter incremented on every sample. ## Usage: Basic ```ts import { Sampler } from "@suaveplan/profiler"; const sampler = new Sampler({ intervalMs: 1000 }); sampler.start(); // ... sampler.stop(); console.log(sampler.getSamples()); ``` ## Usage: Advanced ```ts import { Sampler } from "@suaveplan/profiler"; import type { TimersLike } from "@suaveplan/types"; const queue: Array<{ cb: () => void; handle: number }> = []; let next = 1; const fakeTimers: TimersLike = { setTimer(cb) { const handle = next++; queue.push({ cb, handle }); return handle; }, clearTimer() {}, }; let clockT = 0; const sampler = new Sampler({ intervalMs: 10, timers: fakeTimers, clock: () => clockT, memoryProbe: () => 4096, }); sampler.start(); clockT = 10; queue.shift()?.cb(); ``` ## API Reference - `class Sampler` — `new Sampler(options: SamplerOptions)`. - `interface SamplerOptions extends SamplerConfig { clock?, timers?, memoryProbe? }`. - Methods: `start`, `stop`, `takeSample`, `getSamples`, `getSamplesInRange`, `isRunning`, `clear`. - Errors: throws `ProfilerError` with `PROFILER.INVALID_OPTIONS` when options fail Zod validation. ## Implementation Notes The scheduler uses a self-rescheduling `setTimer` rather than `setInterval` because `TimersLike` only models one-shot timers. Each tick checks `this.running` before taking a sample, which lets a stop() that runs between callback dispatch and execution avoid emitting a stale sample. FIFO eviction uses `splice(0, n)` so the oldest samples drop out when `maxSamples` is exceeded.