mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-11 23:00:03 +00:00
feat(engine,producer,cli): capture failing dB/frame index on drawElement verify fallback
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.
This commit is contained in:
@@ -201,14 +201,34 @@ export interface CaptureSession {
|
||||
* forceScreenshot. Discriminant-based guard (not instanceof) so it survives
|
||||
* duplicated module instances across package boundaries.
|
||||
*/
|
||||
/**
|
||||
* Structured detail carried alongside the human-readable message — lets
|
||||
* telemetry report the actual failing dB / frame index instead of the
|
||||
* orchestrator having to regex them back out of formatted text. All optional:
|
||||
* a blank-frame trip has no PSNR score, so `failedDb`/`verifyThresholdDb`
|
||||
* are omitted for that throw site.
|
||||
*/
|
||||
export interface DrawElementVerificationDetails {
|
||||
frameIndex?: number;
|
||||
failedDb?: number;
|
||||
verifyThresholdDb?: number;
|
||||
}
|
||||
|
||||
export class DrawElementVerificationError extends Error {
|
||||
constructor(message: string) {
|
||||
readonly frameIndex?: number;
|
||||
readonly failedDb?: number;
|
||||
readonly verifyThresholdDb?: number;
|
||||
|
||||
constructor(message: string, details?: DrawElementVerificationDetails) {
|
||||
super(message);
|
||||
this.name = "DrawElementVerificationError";
|
||||
// Discriminant property, assigned dynamically: isDrawElementVerificationError
|
||||
// reads it structurally so detection survives duplicated module instances
|
||||
// across package boundaries (where instanceof fails).
|
||||
(this as unknown as { deVerificationFailure: boolean }).deVerificationFailure = true;
|
||||
this.frameIndex = details?.frameIndex;
|
||||
this.failedDb = details?.failedDb;
|
||||
this.verifyThresholdDb = details?.verifyThresholdDb;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -222,6 +242,31 @@ export function isDrawElementVerificationError(err: unknown): boolean {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the structured details off a (possibly cause-wrapped) verification
|
||||
* error — same chain-walk as isDrawElementVerificationError, structural
|
||||
* (not instanceof) for the same duplicated-module-instance reason. Returns
|
||||
* undefined when the error isn't a verification failure at all.
|
||||
*/
|
||||
export function getDrawElementVerificationDetails(
|
||||
err: unknown,
|
||||
): DrawElementVerificationDetails | undefined {
|
||||
let e: unknown = err;
|
||||
for (let depth = 0; depth < 5 && typeof e === "object" && e !== null; depth++) {
|
||||
const rec = e as { deVerificationFailure?: boolean } & Partial<DrawElementVerificationDetails>;
|
||||
if (rec.deVerificationFailure === true) {
|
||||
const details: DrawElementVerificationDetails = {};
|
||||
if (typeof rec.frameIndex === "number") details.frameIndex = rec.frameIndex;
|
||||
if (typeof rec.failedDb === "number") details.failedDb = rec.failedDb;
|
||||
if (typeof rec.verifyThresholdDb === "number")
|
||||
details.verifyThresholdDb = rec.verifyThresholdDb;
|
||||
return details;
|
||||
}
|
||||
e = (e as { cause?: unknown }).cause;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/** Wait for inline CSS background images introduced by the latest seek. */
|
||||
export async function decodeDynamicCssBackgroundImages(page: Page): Promise<void> {
|
||||
await page.evaluate(async () => {
|
||||
|
||||
Reference in New Issue
Block a user