feat(FN-4608): complete Step 3 — add reliability details and drill-downs

Fusion-Task-Id: FN-4608
Fusion-Task-Lineage: 6cabc509-38a1-4cb8-be6f-51c53d5753ff
This commit is contained in:
Fusion
2026-05-15 09:34:48 -07:00
committed by gsxdsm
parent fc5061afdd
commit 6f9c5af17f
2 changed files with 100 additions and 2 deletions

View File

@@ -32,6 +32,13 @@
gap: var(--space-lg);
}
.reliability-section-header {
display: flex;
align-items: center;
justify-content: space-between;
gap: var(--space-sm);
}
.reliability-table {
width: 100%;
border-collapse: collapse;
@@ -56,6 +63,23 @@
color: var(--text-muted);
}
.reliability-details {
margin-top: var(--space-sm);
}
.reliability-details summary {
color: var(--text-muted);
cursor: pointer;
}
.reliability-details-content {
margin-top: var(--space-sm);
display: flex;
flex-direction: column;
gap: var(--space-xs);
color: var(--text-muted);
}
.reliability-histogram {
list-style: none;
margin: var(--space-sm) 0 0;
@@ -92,4 +116,9 @@
.reliability-grid {
grid-template-columns: minmax(0, 1fr);
}
.reliability-section-header {
flex-direction: column;
align-items: flex-start;
}
}

View File

@@ -4,6 +4,7 @@ import "./ReliabilityView.css";
type ReliabilityResponse = {
windowDays: number;
generatedAt: string;
resetAt: string | null;
headline: { inReviewFailureRate7d: number | null; reason?: string };
perDay: Array<{
date: string;
@@ -12,6 +13,7 @@ type ReliabilityResponse = {
postMergeAuditFailures: { block: number; warn: number; off: number } | null;
fileScopeInvariantFailures: number | null;
recoverAlreadyMergedReviewTasksRecoveries: number | null;
hasSamples?: boolean;
}>;
duration: { p50Ms: number | null; p95Ms: number | null; sampleCount: number; reason?: string };
mergeAttempts: { mean: number | null; max: number | null; histogram: Record<string, number>; reason?: string };
@@ -29,8 +31,20 @@ function formatDuration(value: number | null): string {
return `${minutes.toFixed(1)}m`;
}
function formatDateTime(value: string | null | undefined): string {
if (!value) {
return "—";
}
const parsed = new Date(value);
if (Number.isNaN(parsed.getTime())) {
return value;
}
return parsed.toLocaleString();
}
export function ReliabilityView() {
const [data, setData] = useState<ReliabilityResponse | null>(null);
const [showEmptyDays, setShowEmptyDays] = useState(false);
const load = useCallback(async () => {
const response = await fetch("/api/health/reliability");
@@ -63,6 +77,30 @@ export function ReliabilityView() {
return "var(--color-error)";
}, [data]);
const totalEntered = useMemo(
() => (data?.perDay ?? []).reduce((sum, row) => sum + row.tasksEnteredInReview, 0),
[data?.perDay],
);
const totalBounced = useMemo(
() => (data?.perDay ?? []).reduce((sum, row) => sum + row.tasksBouncedToInProgress, 0),
[data?.perDay],
);
const perDayRows = useMemo(() => {
if (!data?.perDay) {
return [];
}
if (showEmptyDays) {
return data.perDay;
}
return data.perDay.filter((row) => row.hasSamples !== false);
}, [data?.perDay, showEmptyDays]);
const mergeAttemptTaskCount = useMemo(
() => Object.values(data?.mergeAttempts.histogram ?? {}).reduce((sum, count) => sum + count, 0),
[data?.mergeAttempts.histogram],
);
return (
<section className="reliability-view">
<div className="card reliability-card reliability-headline-card">
@@ -72,11 +110,25 @@ export function ReliabilityView() {
? `Insufficient data — ${data?.headline.reason ?? "unknown"}`
: formatPercent(data.headline.inReviewFailureRate7d)}
</div>
<details className="reliability-details">
<summary>Details</summary>
<div className="reliability-details-content">
<div>{`${totalBounced} bounced / ${totalEntered} entered (last ${data?.windowDays ?? 7}d)`}</div>
<div>{`Window: ${data ? formatDateTime(data.resetAt ?? new Date(Date.parse(data.generatedAt) - data.windowDays * 86_400_000).toISOString()) : "—"} → ${formatDateTime(data?.generatedAt)}`}</div>
{data?.resetAt ? <div>{`Reset baseline: ${formatDateTime(data.resetAt)}`}</div> : null}
{data?.headline.reason ? <div>{`Reason: ${data.headline.reason}`}</div> : null}
</div>
</details>
</div>
<div className="reliability-grid">
<div className="card reliability-card">
<h3>In-review flow</h3>
<div className="reliability-section-header">
<h3>In-review flow</h3>
<button className="btn btn-sm" onClick={() => setShowEmptyDays((value) => !value)}>
{showEmptyDays ? "Hide empty days" : "Show empty days"}
</button>
</div>
<table className="reliability-table">
<thead>
<tr>
@@ -86,7 +138,7 @@ export function ReliabilityView() {
</tr>
</thead>
<tbody>
{data?.perDay.map((row) => (
{perDayRows.map((row) => (
<tr key={row.date}>
<td>{row.date}</td>
<td>{row.tasksEnteredInReview}</td>
@@ -102,6 +154,15 @@ export function ReliabilityView() {
<div className="reliability-stat-row"><span>P50</span><strong>{formatDuration(data?.duration.p50Ms ?? null)}</strong></div>
<div className="reliability-stat-row"><span>P95</span><strong>{formatDuration(data?.duration.p95Ms ?? null)}</strong></div>
<div className="reliability-muted">Samples: {data?.duration.sampleCount ?? 0}</div>
<details className="reliability-details">
<summary>More stats</summary>
<div className="reliability-details-content">
<div>{`P50 raw: ${data?.duration.p50Ms ?? "—"} ms`}</div>
<div>{`P95 raw: ${data?.duration.p95Ms ?? "—"} ms`}</div>
<div>{`Sample count: ${data?.duration.sampleCount ?? 0}`}</div>
{data?.duration.reason ? <div>{`Reason: ${data.duration.reason}`}</div> : null}
</div>
</details>
</div>
<div className="card reliability-card">
@@ -117,6 +178,14 @@ export function ReliabilityView() {
</li>
))}
</ul>
<details className="reliability-details">
<summary>More stats</summary>
<div className="reliability-details-content">
<div>{`Tasks counted: ${mergeAttemptTaskCount}`}</div>
<div>{`Histogram total: ${mergeAttemptTaskCount}`}</div>
{data?.mergeAttempts.reason ? <div>{`Reason: ${data.mergeAttempts.reason}`}</div> : null}
</div>
</details>
</div>
</div>
</section>