/** * SLO evaluation against a `LoadReport`. Keep the surface small and * declarative — the value is in being a one-liner in CI: * * const slo = { steps: { "shop/checkout": { p95Ms: 200, errorRate: 0.05 } } }; * assertSlo(report, slo); * * Design choices: * - Separate maps per scope (steps / scenarios / endpoints / totals) * instead of a single namespaced map, so each value type is checked * at compile time and missing-target typos surface as violations * rather than silent skips. * - Comparisons are inclusive: `p95Ms: 200` means actual <= 200 passes. * `errorRate: 0.05` means actual <= 0.05 passes. * `minThroughputPerSec: 5` means actual >= 5 passes. * - Missing scope target (e.g. step "shop/buy" not in report) is itself * a violation. The whole point of an SLO file is to express * expectations — a silently-missing target defeats that. */ import type { LoadReport } from "./types.js"; export interface StepSloThresholds { /** Max acceptable p50 in ms. */ p50Ms?: number; /** Max acceptable p95 in ms. */ p95Ms?: number; /** Max acceptable p99 in ms. */ p99Ms?: number; /** Max acceptable mean in ms. */ meanMs?: number; /** Max acceptable error rate (failures / invocations). 0–1. */ errorRate?: number; } export interface ScenarioSloThresholds { /** Max acceptable iteration error rate (iterationFailures / iterations). */ errorRate?: number; /** Min acceptable throughput in iterations per second. */ minThroughputPerSec?: number; } export interface EndpointSloThresholds { p50Ms?: number; p95Ms?: number; p99Ms?: number; meanMs?: number; /** Max acceptable error rate (errorCount / count). */ errorRate?: number; } export interface TotalsSloThresholds { /** Max acceptable iteration failures (count). */ maxIterationFailures?: number; /** Max acceptable network errors (count). */ maxNetworkErrors?: number; /** Max acceptable step failures (count). */ maxStepFailures?: number; } export interface SloDefinition { /** Key format: `"scenarioName/stepName"`. */ steps?: Record; /** Key format: scenario name. */ scenarios?: Record; /** Key format: endpoint key (e.g. `"/api/checkout"` after normalisation). */ endpoints?: Record; totals?: TotalsSloThresholds; } export type SloScope = "step" | "scenario" | "endpoint" | "totals"; export interface SloViolation { scope: SloScope; /** Target key inside the scope (e.g. `"shop/checkout"`, `"shop"`, `"/api"`). */ target: string; /** Threshold name (`p95Ms`, `errorRate`, etc.). */ metric: string; /** The threshold from the SLO definition. */ threshold: number; /** * The actual value from the report. `null` means the target was * missing entirely (and so the metric couldn't be evaluated). */ actual: number | null; /** Human-readable single-line message. */ message: string; } export interface SloResult { ok: boolean; violations: SloViolation[]; } export declare function evaluateSlo(report: LoadReport, slo: SloDefinition): SloResult; /** * Like `evaluateSlo` but throws an Error listing every violation when * any threshold is breached. The thrown error's `.violations` field * carries the structured list for programmatic handling. */ export declare function assertSlo(report: LoadReport, slo: SloDefinition): void; export declare function formatSloViolations(violations: ReadonlyArray): string; //# sourceMappingURL=slo.d.ts.map