/** Product measurement with declared keys and bounded dimensions. No runtime or store dependency. */ export type MetricSpec = { kind: "counter" | "timing"; label: string; help?: string; unit?: string; perUser?: boolean; dimensions?: Record; }; export interface Measurement { key: string; day: string; count: number; sum: number; user?: string | number; dimensions: Record; } export interface MetricsSchema { metrics: Array<{ key: string; } & MetricSpec>; overlaps: Array<{ from: string; to: string; }>; } /** * Where measurements go. `declare` runs once per process before the first write and * carries the whole schema (kinds, labels, per-user flags, overlaps), so a store is * self-describing and a reader never needs the declaring code. `write` carries one sample. */ export interface MetricsStore { declare(schema: MetricsSchema): Promise; write(measurement: Measurement): Promise; } export interface MetricsOptions { store: MetricsStore; /** Unordered user overlap, not an ordered conversion funnel. */ overlaps?: ReadonlyArray; /** Failures are visible by default, but never reject a measurement call. */ onError?: (error: unknown, key: string) => void; now?: () => Date; } export interface SampleOptions { user?: string | number; dimensions?: Record; } export interface CounterHandle { bump(options?: SampleOptions & { n?: number; }): Promise; } export interface TimingHandle { record(value: number, options?: SampleOptions): Promise; } export type Metrics> = { [K in keyof Spec]: Spec[K]["kind"] extends "counter" ? CounterHandle : TimingHandle; } & { describe(): MetricsSchema; /** * Declare now instead of at the first sample: a server's boot, a Worker's cron. The * same once-per-process promise the samples await, so calling it is never a second write. */ declare(): Promise; }; export declare function defineMetrics>(input: Spec, opts: MetricsOptions>): Metrics; //# sourceMappingURL=index.d.ts.map