fix(web-sentinel): record analyze raw findings
This commit is contained in:
@@ -2545,7 +2545,7 @@ export function runNodeWebProbeObserveAnalyze(options: NodeWebProbeObserveOption
|
||||
},
|
||||
valuesRedacted: true,
|
||||
} : null);
|
||||
return withWebObserveAnalyzeRendered({
|
||||
const payload = {
|
||||
ok: analysisOk,
|
||||
status: analysisOk ? "analyzed" : "blocked",
|
||||
command: webObserveCommandLabel("analyze", options),
|
||||
@@ -2560,7 +2560,165 @@ export function runNodeWebProbeObserveAnalyze(options: NodeWebProbeObserveOption
|
||||
wrapper: buildWebObserveWrapperForObserveOptions("analyze", options, spec.workspace),
|
||||
result: analysis === null ? compactCommandResultWithStdoutTail(result) : compactCommandResult(result),
|
||||
valuesRedacted: true,
|
||||
});
|
||||
};
|
||||
return options.raw ? compactWebObserveAnalyzePayloadForRaw(payload, options.compactRaw) : withWebObserveAnalyzeRendered(payload);
|
||||
}
|
||||
|
||||
function compactWebObserveAnalyzePayloadForRaw(payload: Record<string, unknown>, compactRaw: boolean): Record<string, unknown> {
|
||||
if (!compactRaw) return payload;
|
||||
const analysis = payload.analysis && typeof payload.analysis === "object" && !Array.isArray(payload.analysis)
|
||||
? payload.analysis as Record<string, unknown>
|
||||
: {};
|
||||
return {
|
||||
ok: payload.ok,
|
||||
status: payload.status,
|
||||
command: payload.command,
|
||||
id: payload.id,
|
||||
node: payload.node,
|
||||
lane: payload.lane,
|
||||
workspace: payload.workspace,
|
||||
analysis: compactWebObserveAnalyzeAnalysisForRaw(analysis),
|
||||
failure: compactWebObserveAnalyzeFailureForRaw(payload.failure),
|
||||
result: payload.result,
|
||||
valuesRedacted: true,
|
||||
};
|
||||
}
|
||||
|
||||
function compactWebObserveAnalyzeAnalysisForRaw(analysis: Record<string, unknown>): Record<string, unknown> {
|
||||
const counts = recordValue(analysis.counts);
|
||||
const archiveSummary = recordValue(analysis.archiveSummary);
|
||||
const findings = arrayRecordsValue(analysis.findings).slice(0, 16).map(compactWebObserveAnalyzeFindingForRaw);
|
||||
const archiveRedFindings = arrayRecordsValue(analysis.archiveRedFindings ?? archiveSummary.redFindings).slice(0, 16).map(compactWebObserveAnalyzeFindingForRaw);
|
||||
return {
|
||||
ok: analysis.ok === true ? true : analysis.ok === false ? false : null,
|
||||
command: stringOrNullValue(analysis.command),
|
||||
stateDir: stringOrNullValue(analysis.stateDir),
|
||||
counts,
|
||||
analysisWindow: recordValue(analysis.analysisWindow),
|
||||
archiveSummary: {
|
||||
redFindingCount: numberOrNullValue(archiveSummary.redFindingCount),
|
||||
findingCount: numberOrNullValue(archiveSummary.findingCount),
|
||||
sampleCount: numberOrNullValue(recordValue(archiveSummary.sampleMetrics).sampleCount),
|
||||
pagePerformance: recordValue(archiveSummary.pagePerformance),
|
||||
runtimeAlerts: recordValue(archiveSummary.runtimeAlerts),
|
||||
valuesRedacted: true,
|
||||
},
|
||||
runtimeAlerts: compactWebObserveAnalyzeAlertSummaryForRaw(analysis.runtimeAlerts),
|
||||
pagePerformanceSlowApi: arrayRecordsValue(analysis.pagePerformanceSlowApi ?? analysis.archivePagePerformanceSlowApi).slice(0, 8).map((item) => ({
|
||||
path: stringOrNullValue(item.path ?? item.route),
|
||||
route: stringOrNullValue(item.route ?? item.path),
|
||||
sampleCount: numberOrNullValue(item.sampleCount),
|
||||
p95Ms: numberOrNullValue(item.p95Ms ?? item.p95),
|
||||
maxMs: numberOrNullValue(item.maxMs ?? item.max),
|
||||
budgetMs: numberOrNullValue(item.budgetMs),
|
||||
overBudgetCount: numberOrNullValue(item.overBudgetCount),
|
||||
overFiveSecondCount: numberOrNullValue(item.overFiveSecondCount),
|
||||
valuesRedacted: true,
|
||||
})),
|
||||
findings,
|
||||
archiveRedFindings,
|
||||
reportJsonPath: stringOrNullValue(analysis.reportJsonPath),
|
||||
reportJsonSha256: stringOrNullValue(analysis.reportJsonSha256),
|
||||
reportMdPath: stringOrNullValue(analysis.reportMdPath),
|
||||
reportMdSha256: stringOrNullValue(analysis.reportMdSha256),
|
||||
analyzer: compactWebObserveAnalyzeAnalyzerForRaw(analysis.analyzer),
|
||||
valuesRedacted: true,
|
||||
};
|
||||
}
|
||||
|
||||
function compactWebObserveAnalyzeFailureForRaw(value: unknown): Record<string, unknown> | null {
|
||||
const failure = recordValue(value);
|
||||
if (Object.keys(failure).length === 0) return null;
|
||||
return {
|
||||
reason: stringOrNullValue(failure.reason),
|
||||
exitCode: numberOrNullValue(failure.exitCode),
|
||||
timedOut: failure.timedOut === true,
|
||||
parsedJson: failure.parsedJson === true,
|
||||
recoveredFromArtifacts: failure.recoveredFromArtifacts === true,
|
||||
stdoutBytes: numberOrNullValue(failure.stdoutBytes),
|
||||
stderrBytes: numberOrNullValue(failure.stderrBytes),
|
||||
stdoutTail: stringOrNullValue(failure.stdoutTail)?.slice(-1200) ?? null,
|
||||
stderrTail: stringOrNullValue(failure.stderrTail)?.slice(-1200) ?? null,
|
||||
valuesRedacted: true,
|
||||
};
|
||||
}
|
||||
|
||||
function compactWebObserveAnalyzeAnalyzerForRaw(value: unknown): Record<string, unknown> {
|
||||
const analyzer = recordValue(value);
|
||||
return {
|
||||
exitCode: numberOrNullValue(analyzer.exitCode),
|
||||
recoveredFrom: stringOrNullValue(analyzer.recoveredFrom),
|
||||
stdoutBytes: numberOrNullValue(analyzer.stdoutBytes),
|
||||
stderrBytes: numberOrNullValue(analyzer.stderrBytes),
|
||||
reportJsonBytes: numberOrNullValue(analyzer.reportJsonBytes),
|
||||
reportMdBytes: numberOrNullValue(analyzer.reportMdBytes),
|
||||
transportExitCode: numberOrNullValue(analyzer.transportExitCode),
|
||||
transportTimedOut: analyzer.transportTimedOut === true,
|
||||
compactStdoutLimited: analyzer.compactStdoutLimited === true,
|
||||
valuesRedacted: true,
|
||||
};
|
||||
}
|
||||
|
||||
function compactWebObserveAnalyzeAlertSummaryForRaw(value: unknown): Record<string, unknown> {
|
||||
const source = recordValue(value);
|
||||
const summary = recordValue(source.summary);
|
||||
const out: Record<string, unknown> = {};
|
||||
for (const key of [
|
||||
"httpErrorCount",
|
||||
"requestFailedCount",
|
||||
"significantRequestFailedCount",
|
||||
"workbenchSessionListReadCount",
|
||||
"workbenchTraceEventsReadCount",
|
||||
"webPerformanceBeaconFailureCount",
|
||||
"workbenchEventSourceFailureCount",
|
||||
"consoleAlertCount",
|
||||
"significantConsoleAlertCount",
|
||||
]) {
|
||||
const value = summary[key] ?? source[key];
|
||||
if (value !== undefined && value !== null) out[key] = value;
|
||||
}
|
||||
out.valuesRedacted = true;
|
||||
return out;
|
||||
}
|
||||
|
||||
function compactWebObserveAnalyzeFindingForRaw(value: Record<string, unknown>): Record<string, unknown> {
|
||||
return {
|
||||
kind: stringOrNullValue(value.kind ?? value.id ?? value.code),
|
||||
id: stringOrNullValue(value.id ?? value.kind ?? value.code),
|
||||
code: stringOrNullValue(value.code ?? value.id ?? value.kind),
|
||||
severity: stringOrNullValue(value.severity ?? value.level),
|
||||
level: stringOrNullValue(value.level ?? value.severity),
|
||||
count: numberOrNullValue(value.count ?? value.sampleCount),
|
||||
sampleCount: numberOrNullValue(value.sampleCount ?? value.count),
|
||||
timingSourceOfTruth: stringOrNullValue(value.timingSourceOfTruth ?? value.expectedElapsedSource ?? value.evidenceKind),
|
||||
timingStatus: stringOrNullValue(value.timingStatus),
|
||||
timingAlert: value.timingAlert === true,
|
||||
summary: stringOrNullValue(value.summary ?? value.message)?.slice(0, 220) ?? null,
|
||||
message: stringOrNullValue(value.message ?? value.summary)?.slice(0, 220) ?? null,
|
||||
rootCause: stringOrNullValue(value.rootCause)?.slice(0, 140) ?? null,
|
||||
rootCauseStatus: stringOrNullValue(value.rootCauseStatus)?.slice(0, 90) ?? null,
|
||||
rootCauseConfidence: stringOrNullValue(value.rootCauseConfidence)?.slice(0, 40) ?? null,
|
||||
nextAction: stringOrNullValue(value.nextAction)?.slice(0, 240) ?? null,
|
||||
evidenceSummary: stringOrNullValue(value.evidenceSummary)?.slice(0, 220) ?? null,
|
||||
valuesRedacted: true,
|
||||
};
|
||||
}
|
||||
|
||||
function arrayRecordsValue(value: unknown): Record<string, unknown>[] {
|
||||
return Array.isArray(value) ? value.map(recordValue).filter((item) => Object.keys(item).length > 0) : [];
|
||||
}
|
||||
|
||||
function recordValue(value: unknown): Record<string, unknown> {
|
||||
return value !== null && typeof value === "object" && !Array.isArray(value) ? value as Record<string, unknown> : {};
|
||||
}
|
||||
|
||||
function stringOrNullValue(value: unknown): string | null {
|
||||
return typeof value === "string" && value.length > 0 ? value : null;
|
||||
}
|
||||
|
||||
function numberOrNullValue(value: unknown): number | null {
|
||||
const number = Number(value);
|
||||
return Number.isFinite(number) ? number : null;
|
||||
}
|
||||
|
||||
export function recoverWebObserveAnalyzeFromArtifacts(options: NodeWebProbeObserveOptions, spec: HwlabRuntimeLaneSpec, result: { exitCode: number; timedOut: boolean }): Record<string, unknown> | null {
|
||||
|
||||
Reference in New Issue
Block a user