feat(housekeeping): deliver system vertical

This commit is contained in:
simoleo89
2026-08-28 23:31:47 +02:00
parent 0117b45d74
commit 3788ecd9f1
33 changed files with 4548 additions and 423 deletions
@@ -0,0 +1,212 @@
import type { ReactNode } from "react";
import {
createCorrelationId,
fail,
type HousekeepingResult,
} from "../../../foundation/contracts";
import { HousekeepingPageShell } from "../../../foundation/page/housekeeping-page-shell";
import { HousekeepingPageState } from "../../../foundation/page/housekeeping-page-state";
import type { HousekeepingPageInput } from "../../../route-handlers";
import {
type SystemObservabilityQueryData,
type SystemObservabilityQueryInput,
systemObservabilityQuery,
} from "../queries/observability";
interface SystemObservabilityPageProps {
readonly result?: HousekeepingResult<SystemObservabilityQueryData>;
}
function pageState(
kind: "loading" | "empty" | "error",
title: string,
description: string,
) {
return (
<div data-housekeeping-state={kind}>
<HousekeepingPageState
state={kind}
title={title}
description={description}
/>
</div>
);
}
function forbiddenState() {
return (
<section
role="alert"
data-housekeeping-state="forbidden"
className="rounded-lg border border-[var(--admin-error)] bg-[var(--admin-surface)] p-4"
>
<h2 className="font-medium text-[var(--admin-text)]">Access denied</h2>
<p className="mt-1 text-sm text-[var(--admin-text-muted)]">
Your account cannot view this observability source.
</p>
</section>
);
}
function observabilityContent(data: SystemObservabilityQueryData) {
if (data.kind === "devops") {
return (
<div className="grid gap-4 lg:grid-cols-2">
<section className="rounded-lg border border-[var(--admin-border)] bg-[var(--admin-surface)] p-4">
<h2 className="font-medium text-[var(--admin-text)]">
Service health
</h2>
{data.health ? (
<dl className="mt-3 grid grid-cols-2 gap-2 text-sm text-[var(--admin-text-muted)]">
<dt>Database</dt>
<dd>{data.health.dbOk ? "Available" : "Unavailable"}</dd>
<dt>Redis</dt>
<dd>
{data.health.redisOk === null
? "Not configured"
: data.health.redisOk
? "Available"
: "Unavailable"}
</dd>
<dt>Emulator</dt>
<dd>{data.health.emulatorOk ? "Available" : "Unavailable"}</dd>
<dt>Online users</dt>
<dd>{data.health.onlineUsers}</dd>
</dl>
) : (
<p className="mt-3 text-sm text-[var(--admin-text-muted)]">
Health data is unavailable.
</p>
)}
</section>
{observationRows("Recent emulator errors", data.errors)}
</div>
);
}
if (data.kind === "devops-errors") {
return observationRows("Emulator errors", data.errors);
}
return (
<div className="space-y-4">
<div className="grid gap-3 sm:grid-cols-2 xl:grid-cols-4">
{data.metrics.map((metric) => (
<section
key={metric.label}
className="rounded-lg border border-[var(--admin-border)] bg-[var(--admin-surface)] p-4"
>
<p className="text-xs text-[var(--admin-text-muted)]">
{metric.label}
</p>
<p className="mt-1 text-xl font-semibold text-[var(--admin-text)]">
{metric.value}
</p>
</section>
))}
</div>
{observationRows(
data.kind === "logs" ? "Recent entries" : "Details",
data.rows,
)}
</div>
);
}
function observationRows(
title: string,
rows: readonly { id: string; primary: string; secondary?: string }[],
) {
return (
<section className="rounded-lg border border-[var(--admin-border)] bg-[var(--admin-surface)] p-4">
<h2 className="font-medium text-[var(--admin-text)]">{title}</h2>
<ul className="mt-3 divide-y divide-[var(--admin-border)]">
{rows.map((row) => (
<li key={row.id} className="py-2 text-sm">
<p className="font-medium text-[var(--admin-text)]">
{row.primary}
</p>
{row.secondary ? (
<p className="break-words text-[var(--admin-text-muted)]">
{row.secondary}
</p>
) : null}
</li>
))}
</ul>
</section>
);
}
function isEmpty(data: SystemObservabilityQueryData): boolean {
if (data.kind === "devops")
return data.health === null && data.errors.length === 0;
if (data.kind === "devops-errors") return data.errors.length === 0;
return data.metrics.length === 0 && data.rows.length === 0;
}
export function SystemObservabilityPage({
result,
}: SystemObservabilityPageProps) {
let body: ReactNode;
if (!result) {
body = pageState(
"loading",
"Loading observability data",
"Reading metrics and operational logs.",
);
} else if (!result.ok) {
body =
result.error.code === "FORBIDDEN"
? forbiddenState()
: pageState(
"error",
"Observability data unavailable",
`Request ${result.correlationId} could not be completed.`,
);
} else if (isEmpty(result.data)) {
body = pageState(
"empty",
"No observations",
"The selected source returned no records.",
);
} else {
body = (
<div
data-housekeeping-state={
result.data.partialDependencies.length > 0 ? "partial" : "ready"
}
className="space-y-4"
>
{result.data.partialDependencies.length > 0 ? (
<HousekeepingPageState
state="partial"
partialLabel="Partial data"
title="Some observability data is unavailable"
description={`Unavailable: ${result.data.partialDependencies.join(", ")}`}
/>
) : null}
{observabilityContent(result.data)}
</div>
);
}
return (
<HousekeepingPageShell
title="System observability"
description="Review metrics, service health, and operational records."
>
{body}
</HousekeepingPageShell>
);
}
export async function renderSystemObservabilityPage(
input: HousekeepingPageInput,
) {
const routeId = input.match
.routeId as SystemObservabilityQueryInput["routeId"];
const supported = routeId.startsWith("system.observability.");
const result = supported
? await systemObservabilityQuery.run(input.context, { routeId })
: fail("NOT_FOUND", "errors.housekeeping.notFound", createCorrelationId());
return <SystemObservabilityPage result={result} />;
}