first commit

This commit is contained in:
2026-05-29 08:20:56 +01:00
commit 949299f58d
6368 changed files with 527176 additions and 0 deletions

View File

@@ -0,0 +1,71 @@
# sampler
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## 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<SamplerEventMap>` 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.