fix: surface webprobe performance evidence mode
This commit is contained in:
@@ -46,6 +46,7 @@ function buildFrontendPerformanceReport(rows, artifacts) {
|
||||
.map(finalizeProfileStackHotspot)
|
||||
.sort((left, right) => Number(right.selfTimeMs ?? 0) - Number(left.selfTimeMs ?? 0))
|
||||
.slice(0, 30);
|
||||
const attribution = frontendPerformanceAttributionStatus({ captures, profileHotspots, profileStacks, scriptHotspots, longTasks, loafs, gaps });
|
||||
return {
|
||||
summary: {
|
||||
rowCount: sourceRows.length,
|
||||
@@ -63,6 +64,12 @@ function buildFrontendPerformanceReport(rows, artifacts) {
|
||||
maxLongTaskMs: frontendPerformanceMaxNumber(longTasks, (item) => item.durationMs),
|
||||
maxLongAnimationFrameMs: frontendPerformanceMaxNumber(loafs, (item) => item.durationMs),
|
||||
maxEventLoopGapMs: frontendPerformanceMaxNumber(gaps, (item) => item.durationMs),
|
||||
cpuProfileStatus: attribution.cpuProfileStatus,
|
||||
attributionMode: attribution.attributionMode,
|
||||
noCpuProfile: attribution.noCpuProfile,
|
||||
loafOnly: attribution.loafOnly,
|
||||
cpuProfileHotspotEvidence: attribution.cpuProfileHotspotEvidence,
|
||||
evidenceNote: attribution.evidenceNote,
|
||||
captureArtifacts: performanceCaptureArtifacts(artifacts),
|
||||
valuesRedacted: true,
|
||||
},
|
||||
@@ -127,6 +134,21 @@ function buildFrontendPerformanceFindings(report) {
|
||||
topStacks: (report?.profileStacks || []).slice(0, 8),
|
||||
valuesRedacted: true,
|
||||
});
|
||||
if (summary.noCpuProfile === true && (severeLongTasks.length > 0 || severeLoafs.length > 0 || severeGaps.length > 0)) findings.push({
|
||||
id: "frontend-performance-loaf-only-no-cpu-profile",
|
||||
severity: "amber",
|
||||
summary: "frontend performance evidence is LoAF/LongTask/event-loop only because no completed CPU profile capture is present; do not cite CPU profile hotspots for this run",
|
||||
count: 1,
|
||||
attributionMode: summary.attributionMode || "loaf-only-no-cpu-profile",
|
||||
cpuProfileStatus: summary.cpuProfileStatus || "missing",
|
||||
captureCount: summary.captureCount ?? 0,
|
||||
longTaskCount: summary.longTaskCount ?? 0,
|
||||
longAnimationFrameCount: summary.longAnimationFrameCount ?? 0,
|
||||
eventLoopGapCount: summary.eventLoopGapCount ?? 0,
|
||||
topScripts: (report?.scriptHotspots || []).slice(0, 12),
|
||||
nextAction: "Run an explicit performanceCapture command and re-run observe analyze before making CPU-profile hotspot claims; existing LoAF scripts remain valid browser-side attribution.",
|
||||
valuesRedacted: true,
|
||||
});
|
||||
if ((report?.drainErrors || []).length > 0) findings.push({
|
||||
id: "frontend-performance-probe-drain-errors",
|
||||
severity: "amber",
|
||||
@@ -138,6 +160,43 @@ function buildFrontendPerformanceFindings(report) {
|
||||
return findings;
|
||||
}
|
||||
|
||||
function frontendPerformanceAttributionStatus(input) {
|
||||
const captureCount = Array.isArray(input?.captures) ? input.captures.length : 0;
|
||||
const profileHotspotCount = Array.isArray(input?.profileHotspots) ? input.profileHotspots.length : 0;
|
||||
const profileStackCount = Array.isArray(input?.profileStacks) ? input.profileStacks.length : 0;
|
||||
const scriptHotspotCount = Array.isArray(input?.scriptHotspots) ? input.scriptHotspots.length : 0;
|
||||
const eventCount =
|
||||
(Array.isArray(input?.longTasks) ? input.longTasks.length : 0) +
|
||||
(Array.isArray(input?.loafs) ? input.loafs.length : 0) +
|
||||
(Array.isArray(input?.gaps) ? input.gaps.length : 0);
|
||||
const hasCpuProfile = captureCount > 0;
|
||||
const hasCpuProfileHotspots = profileHotspotCount > 0 || profileStackCount > 0;
|
||||
if (hasCpuProfile) {
|
||||
return {
|
||||
cpuProfileStatus: hasCpuProfileHotspots ? "captured-with-hotspots" : "captured-no-hotspots",
|
||||
attributionMode: "cpu-profile-and-performance-observer",
|
||||
noCpuProfile: false,
|
||||
loafOnly: false,
|
||||
cpuProfileHotspotEvidence: hasCpuProfileHotspots,
|
||||
evidenceNote: hasCpuProfileHotspots
|
||||
? "completed performanceCapture artifacts produced CPU profile hotspot evidence"
|
||||
: "completed performanceCapture artifacts exist, but no CPU profile hotspots were extracted",
|
||||
valuesRedacted: true,
|
||||
};
|
||||
}
|
||||
return {
|
||||
cpuProfileStatus: "missing",
|
||||
attributionMode: eventCount > 0 || scriptHotspotCount > 0 ? "loaf-only-no-cpu-profile" : "no-frontend-performance-evidence",
|
||||
noCpuProfile: true,
|
||||
loafOnly: eventCount > 0 || scriptHotspotCount > 0,
|
||||
cpuProfileHotspotEvidence: false,
|
||||
evidenceNote: eventCount > 0 || scriptHotspotCount > 0
|
||||
? "LongTask/LoAF/event-loop evidence is present, but no completed performanceCapture CPU profile exists"
|
||||
: "no frontend performance events or completed performanceCapture CPU profile exist",
|
||||
valuesRedacted: true,
|
||||
};
|
||||
}
|
||||
|
||||
function compactPerformanceEventRow(row, perf) {
|
||||
return {
|
||||
ts: row.ts ?? null,
|
||||
|
||||
Reference in New Issue
Block a user