refactor(telemetry): chart scale labels, calmer vitals and error styling, usage-first tabs

- sparklines get start/end date and max-value footers
- vitals rating shown by value color instead of badges
- error rows use plain counts, subtle resolve button, terse empty state
- telemetry tab order: usage, players, functions, events, errors; usage is default
This commit is contained in:
2026-08-25 22:35:16 -07:00
parent 7ea189aa61
commit fd0489a22f
12 changed files with 222 additions and 238 deletions
@@ -1,7 +1,6 @@
import { Suspense, useMemo, useState } from "react";
import { Trans, useLingui } from "@lingui/react/macro";
import {
Badge,
Divider,
Group,
SegmentedControl,
@@ -45,25 +44,18 @@ const vitalRating = (name: VitalName, value: number): "good" | "ok" | "poor" =>
return "ok";
};
const VitalBadge = ({ name, value }: { name: VitalName; value: number }) => {
const vitalColor = (name: VitalName, value: number): string | undefined => {
const rating = vitalRating(name, value);
const color = rating === "good" ? "green" : rating === "ok" ? "yellow" : "red";
return (
<Badge color={color} variant="light" size="sm">
{rating === "good" ? (
<Trans>Good</Trans>
) : rating === "ok" ? (
<Trans>Needs improvement</Trans>
) : (
<Trans>Poor</Trans>
)}
</Badge>
);
if (rating === "good") return undefined;
return rating === "ok" ? "yellow.8" : "red";
};
const formatVital = (name: VitalName, value: number) =>
name === "CLS" ? value.toFixed(2) : `${Math.round(value)}ms`;
const dayLabel = (i18n: { date: (d: Date, opts?: Intl.DateTimeFormatOptions) => string }, day: string) =>
i18n.date(new Date(`${day}T12:00:00Z`), { month: "short", day: "numeric" });
const topItems = (totals: Map<string, number>, onClick?: (dim: string) => void) =>
[...totals.entries()]
.sort((a, b) => b[1] - a[1])
@@ -75,6 +67,7 @@ const topItems = (totals: Map<string, number>, onClick?: (dim: string) => void)
}));
const FnDurationDetail = ({ fn, from, to }: { fn: string; from: string; to: string }) => {
const { i18n } = useLingui();
const { data: rows } = useRollupRange({
metrics: ["server_fn.duration.p50", "server_fn.duration.p95"],
from,
@@ -87,7 +80,17 @@ const FnDurationDetail = ({ fn, from, to }: { fn: string; from: string; to: stri
return (
<Stack gap="xs">
<Sparkline data={p50} series2={p95} height={64} showArea />
<Sparkline
data={p50}
series2={p95}
height={64}
showArea
scale={{
start: dayLabel(i18n, from),
end: dayLabel(i18n, to),
formatValue: (value) => `${Math.round(value)}ms`,
}}
/>
<Group gap="md">
<Group gap={6}>
<svg width={18} height={8} aria-hidden>
@@ -119,7 +122,7 @@ const FnDurationDetail = ({ fn, from, to }: { fn: string; from: string; to: stri
};
const UsageSections = ({ from, to }: { from: string; to: string }) => {
const { t } = useLingui();
const { t, i18n } = useLingui();
const [selectedFn, setSelectedFn] = useState<string | null>(null);
const { isOpen: fnDetailOpened, open: openFnDetail, close: closeFnDetail } = useSheet();
@@ -159,6 +162,7 @@ const UsageSections = ({ from, to }: { from: string; to: string }) => {
label={<Trans>Daily active players</Trans>}
value={(dauSeries[dauSeries.length - 1] ?? 0).toLocaleString()}
spark={dauSeries}
sparkScale={{ start: dayLabel(i18n, from), end: dayLabel(i18n, to) }}
/>
<SimpleGrid cols={3} spacing="sm">
<StatTile
@@ -200,9 +204,10 @@ const UsageSections = ({ from, to }: { from: string; to: string }) => {
<Trans>Errors</Trans>
</Title>
<StatTile
label={<Trans>Client errors per day</Trans>}
label={<Trans>Client errors</Trans>}
value={errorSeries.reduce((sum, value) => sum + value, 0).toLocaleString()}
spark={errorSeries}
sparkScale={{ start: dayLabel(i18n, from), end: dayLabel(i18n, to) }}
/>
</Stack>
@@ -218,7 +223,7 @@ const UsageSections = ({ from, to }: { from: string; to: string }) => {
key={name}
label={name}
value={value !== undefined ? formatVital(name, value) : "—"}
caption={value !== undefined ? <VitalBadge name={name} value={value} /> : undefined}
valueColor={value !== undefined ? vitalColor(name, value) : undefined}
/>
))}
</SimpleGrid>