mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-03 04:38:33 +00:00
de_fallback_reason only told you the fallback happened (blank/psnr/oom/ capture_error), not the failing PSNR or frame index — that data existed as text inside the thrown error's message and was discarded on the way to telemetry. DrawElementVerificationError now carries structured frameIndex/failedDb/verifyThresholdDb; the orchestrator reads them via the new getDrawElementVerificationDetails helper instead of regexing message text, and both telemetry surfaces (the render_complete perfSummary path and the crash-survival RenderCaptureObservability mirror) emit de_fallback_failed_db / de_fallback_frame_index. Needed to distinguish "32dB vs the 32dB threshold, tune it" from "12dB real corruption, investigate" during the parallel-router soak — currently that distinction is invisible.
127 lines
4.9 KiB
TypeScript
127 lines
4.9 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import type { RenderObservabilitySummary } from "@hyperframes/producer";
|
|
import { renderObservabilityTelemetryPayload } from "./renderObservability.js";
|
|
|
|
function makeSummary(
|
|
capture: Partial<RenderObservabilitySummary["capture"]>,
|
|
): RenderObservabilitySummary {
|
|
return {
|
|
events: [],
|
|
eventCount: 0,
|
|
browserDiagnostics: {
|
|
total: 0,
|
|
errors: 0,
|
|
pageErrors: 0,
|
|
requestFailed: 0,
|
|
httpErrors: 0,
|
|
navigationStarts: 0,
|
|
navigationFailures: 0,
|
|
consoleErrors: 0,
|
|
consoleWarnings: 0,
|
|
},
|
|
capture: { forceScreenshot: false, captureMode: "beginframe", ...capture },
|
|
};
|
|
}
|
|
|
|
describe("renderObservabilityTelemetryPayload — render-reliability counters", () => {
|
|
it("maps the transient-retry and OOM counters through to the telemetry payload", () => {
|
|
const payload = renderObservabilityTelemetryPayload(
|
|
makeSummary({ transientRetries: 2, memoryExhaustionDetected: true }),
|
|
);
|
|
expect(payload.captureTransientRetries).toBe(2);
|
|
expect(payload.captureMemoryExhaustionDetected).toBe(true);
|
|
});
|
|
|
|
it("leaves the counters undefined when the render didn't retry or OOM", () => {
|
|
const payload = renderObservabilityTelemetryPayload(makeSummary({}));
|
|
expect(payload.captureTransientRetries).toBeUndefined();
|
|
expect(payload.captureMemoryExhaustionDetected).toBeUndefined();
|
|
});
|
|
});
|
|
|
|
describe("renderObservabilityTelemetryPayload — DE inversion/router cohort (failure-path visibility)", () => {
|
|
it("maps the router cohort and its pre-router worker count", () => {
|
|
const payload = renderObservabilityTelemetryPayload(
|
|
makeSummary({ deParallelRouter: "routed", dePreRouterWorkers: 2 }),
|
|
);
|
|
expect(payload.captureDeParallelRouter).toBe("routed");
|
|
expect(payload.captureDePreRouterWorkers).toBe(2);
|
|
expect(payload.captureDeWorkerInversion).toBeUndefined();
|
|
expect(payload.captureDePreInversionWorkers).toBeUndefined();
|
|
});
|
|
|
|
it("maps the inversion cohort and its pre-inversion worker count", () => {
|
|
const payload = renderObservabilityTelemetryPayload(
|
|
makeSummary({ deWorkerInversion: "inverted", dePreInversionWorkers: 4 }),
|
|
);
|
|
expect(payload.captureDeWorkerInversion).toBe("inverted");
|
|
expect(payload.captureDePreInversionWorkers).toBe(4);
|
|
expect(payload.captureDeParallelRouter).toBeUndefined();
|
|
});
|
|
|
|
it("carries deSelfVerifyFallback so a hard failure mid-verify is still visible", () => {
|
|
const payload = renderObservabilityTelemetryPayload(
|
|
makeSummary({ deParallelRouter: "routed", deSelfVerifyFallback: true }),
|
|
);
|
|
expect(payload.captureDeSelfVerifyFallback).toBe(true);
|
|
});
|
|
|
|
it("carries deFallbackReason so a render that fails AFTER an OOM-triggered fallback attempt is distinguishable from one that never attempted a fallback", () => {
|
|
const payload = renderObservabilityTelemetryPayload(
|
|
makeSummary({
|
|
deParallelRouter: "routed",
|
|
deSelfVerifyFallback: false,
|
|
deFallbackReason: "oom",
|
|
}),
|
|
);
|
|
expect(payload.captureDeFallbackReason).toBe("oom");
|
|
});
|
|
|
|
it("leaves deFallbackReason undefined when no fallback was ever attempted", () => {
|
|
const payload = renderObservabilityTelemetryPayload(makeSummary({}));
|
|
expect(payload.captureDeFallbackReason).toBeUndefined();
|
|
});
|
|
|
|
it("carries the failing dB and frame index for a psnr fallback, still visible on a hard failure", () => {
|
|
const payload = renderObservabilityTelemetryPayload(
|
|
makeSummary({
|
|
deParallelRouter: "routed",
|
|
deFallbackReason: "psnr",
|
|
deFallbackFailedDb: 28.4,
|
|
deFallbackFrameIndex: 649,
|
|
}),
|
|
);
|
|
expect(payload.captureDeFallbackFailedDb).toBe(28.4);
|
|
expect(payload.captureDeFallbackFrameIndex).toBe(649);
|
|
});
|
|
|
|
it("leaves failedDb undefined for a blank/oom/capture_error fallback (no PSNR score exists)", () => {
|
|
const payload = renderObservabilityTelemetryPayload(
|
|
makeSummary({ deFallbackReason: "oom", deFallbackFrameIndex: undefined }),
|
|
);
|
|
expect(payload.captureDeFallbackFailedDb).toBeUndefined();
|
|
expect(payload.captureDeFallbackFrameIndex).toBeUndefined();
|
|
});
|
|
});
|
|
|
|
describe("renderObservabilityTelemetryPayload — non-DE parallel-stream router", () => {
|
|
it("maps the router outcome", () => {
|
|
const payload = renderObservabilityTelemetryPayload(
|
|
makeSummary({ captureParallelStream: "beginframe" }),
|
|
);
|
|
expect(payload.captureParallelStream).toBe("beginframe");
|
|
});
|
|
|
|
it("maps the passive eligible_off cohort-sizing signal", () => {
|
|
const payload = renderObservabilityTelemetryPayload(
|
|
makeSummary({ captureParallelStream: "eligible_off" }),
|
|
);
|
|
expect(payload.captureParallelStream).toBe("eligible_off");
|
|
});
|
|
|
|
it("stays undefined when the router never fired", () => {
|
|
const payload = renderObservabilityTelemetryPayload(makeSummary({}));
|
|
expect(payload.captureParallelStream).toBeUndefined();
|
|
});
|
|
});
|