infra locale

This commit is contained in:
Alex Holliday committed 2025-12-11 13:30:43 -08:00
1 parent 64d1ba08f9
commit 63dd455e4a
8 files changed
+121 -45

No files matched your search

@@ -8,6 +8,7 @@ import { useTheme } from "@mui/material/styles";
import { alpha } from "@mui/material/styles";
import { useState } from "react";
import Tooltip from "@mui/material/Tooltip";
import { useTranslation } from "react-i18next";
const CenterLabel = ({ viewBox, value }: any) => {
const { cx, cy } = viewBox;
@@ -21,15 +22,16 @@ const CenterLabel = ({ viewBox, value }: any) => {
};
export const ChartPageSpeedReport = ({ latestCheck }: { latestCheck: any }) => {
const { t } = useTranslation();
const theme = useTheme();
const [hoverTitle, setHoverTitle] = useState<string | null>(null);
const LABELS: Record<string, string> = {
FCP: "First Contentful Paint",
SI: "Speed Index",
LCP: "Largest Contentful Paint",
TBT: "Total Blocking Time",
CLS: "Cumulative Layout Shift",
FCP: t("common.charts.pageSpeed.fcp"),
SI: t("common.charts.pageSpeed.si"),
LCP: t("common.charts.pageSpeed.lcp"),
TBT: t("common.charts.pageSpeed.tbt"),
CLS: t("common.charts.pageSpeed.cls"),
};
const metrics = [
{ key: "fcp", color: alpha("#1DE9B6", 0.6), weight: 0.1 },
@@ -80,7 +82,7 @@ export const ChartPageSpeedReport = ({ latestCheck }: { latestCheck: any }) => {
return (
<BaseChart
icon={<FileText size={20} strokeWidth={1.5} />}
title="Average PageSpeed score"
title={t("common.charts.pageSpeed.title")}
>
<Tooltip
open={Boolean(hoverTitle)}
@@ -4,6 +4,7 @@ import { BarChart3 } from "lucide-react";
import { BaseChart } from "@/components/monitors/Chart";
import Typography from "@mui/material/Typography";
import { useTranslation } from "react-i18next";
import { getPageSpeedPalette } from "@/utils/MonitorUtils";
import { useTheme } from "@mui/material/styles";
@@ -16,6 +17,7 @@ const MetricBox = ({
value: number;
weight: number;
}) => {
const { t } = useTranslation();
const theme = useTheme();
const palette = getPageSpeedPalette(value);
return (
@@ -32,7 +34,7 @@ const MetricBox = ({
<Typography textTransform={"uppercase"}>{label}</Typography>
<Stack direction="row" justifyContent={"space-between"}>
<Typography>{`${value}%`}</Typography>
<Typography>{`Weight: ${weight}%`}</Typography>
<Typography>{`${t("common.charts.pageSpeed.weight")}: ${weight}%`}</Typography>
</Stack>
</Stack>
<Box
@@ -53,31 +55,35 @@ export const ChartPageSpeedReportLegend = ({
latestCheck: any;
}) => {
const theme = useTheme();
const { t } = useTranslation();
return (
<BaseChart icon={<BarChart3 size={20} strokeWidth={1.5} />} title="PageSpeed report">
<BaseChart
icon={<BarChart3 size={20} strokeWidth={1.5} />}
title="PageSpeed report"
>
<Stack gap={theme.spacing(4)}>
<MetricBox
label="Speed index (SI)"
label={t("common.charts.pageSpeed.si")}
value={Math.floor(latestCheck?.si * 100 || 0 * 100)}
weight={10}
/>
<MetricBox
label="First contentful paint (FCP)"
label={t("common.charts.pageSpeed.fcp")}
value={Math.floor(latestCheck?.fcp * 100 || 0 * 100)}
weight={10}
/>
<MetricBox
label="Cumulative layout shift (CLS)"
label={t("common.charts.pageSpeed.cls")}
value={Math.floor(latestCheck?.cls * 100 || 0 * 100)}
weight={25}
/>
<MetricBox
label="Total blocking time (TBT)"
label={t("common.charts.pageSpeed.tbt")}
value={Math.floor(latestCheck?.tbt * 100 || 0 * 100)}
weight={30}
/>
<MetricBox
label="Largest contentful paint (LCP)"
label={t("common.charts.pageSpeed.lcp")}
value={Math.floor(latestCheck?.lcp * 100 || 0 * 100)}
weight={25}
/>
@@ -87,6 +87,7 @@ const createGradient = ({
export const HistogramInfrastructure = ({
range,
title,
type,
idx,
checks,
xKey,
@@ -101,6 +102,7 @@ export const HistogramInfrastructure = ({
}: {
range: string;
title: string;
type: string;
idx: number | null;
checks: IInfraCheck[];
xKey: string;
@@ -118,7 +120,7 @@ export const HistogramInfrastructure = ({
let avgTemps: { _id: string; avg_temp: number | null }[] = [];
let tempYDomain: number[] = [];
if (title === "temp") {
if (type === "temp") {
avgTemps = checks.map((check) => {
const temps = check.cpu.temperature || [];
if (temps.length === 0) return { ...check, avg_temp: null };
@@ -135,14 +137,14 @@ export const HistogramInfrastructure = ({
}
return (
<BaseChart icon={null} title={idx !== null ? title + ` ${idx}` : title}>
<BaseChart icon={null} title={title}>
<ResponsiveContainer width="100%" height={200}>
<AreaChart data={title === "temp" ? avgTemps : checks}>
<AreaChart data={type === "temp" ? avgTemps : checks}>
<XAxis
dataKey={xKey}
tick={(props) => <XTick {...props} range={range} />}
/>
<YAxis domain={title === "temp" ? tempYDomain : yDomain} />
<YAxis domain={type === "temp" ? tempYDomain : yDomain} />
<CartesianGrid
stroke={theme.palette.divider}
+48 -1
View File
@@ -39,6 +39,29 @@
"title": "Average Response Time",
"lowLabel": "Low",
"highLabel": "High"
},
"pageSpeed": {
"weight": "Weight",
"title": "Average PageSpeed score",
"fcp": "First Contentful Paint (FCP)",
"si": "Speed Index (SI)",
"lcp": "Largest Contentful Paint (LCP)",
"tbt": "Total Blocking Time (TBT)",
"cls": "Cumulative Layout Shift (CLS)"
},
"infrastructure": {
"memory": {
"title": "Memory"
},
"cpu": {
"title": "CPU"
},
"temp": {
"title": "Temp"
},
"disk": {
"title": "Disk {{idx}}"
}
}
}
},
@@ -69,7 +92,14 @@
"activeFor": "Active for",
"lastCheck": "Last checked",
"lastResponseTime": "Last response time",
"certificate": "Certificate expiry"
"certificate": "Certificate expiry",
"cpuPhysical": "CPU (physical)",
"cpuLogical": "CPU (logical)",
"cpuFrequency": "CPU frequency",
"cpuTemperature": "Avg CPU temp",
"memory": "Memory",
"disk": "Disk",
"os": "OS"
},
"table": {
"headers": {
@@ -221,6 +251,23 @@
"optionDiskUsage": "Disk usage (%)",
"optionTemperature": "Temperature (°C)"
}
},
"gauges": {
"memory": {
"title": "Memory usage",
"upperLabel": "Used",
"lowerLabel": "Free"
},
"cpu": {
"title": "CPU usage",
"upperLabel": "Current frequency",
"lowerLabel": "Max frequency"
},
"disk": {
"title": "Disk {{idx}} usage",
"upperLabel": "Used",
"lowerLabel": "Free"
}
}
}
},
@@ -5,6 +5,7 @@ import prettyMilliseconds from "pretty-ms";
import { getStatusPalette } from "@/utils/MonitorUtils";
import { InfraDetailsGraphs } from "@/pages/infrastructure/InfraDetailsGraphs";
import { useTranslation } from "react-i18next";
import { useGet, usePatch } from "@/hooks/UseApi";
import { useState } from "react";
import { useTheme } from "@mui/material/styles";
@@ -25,6 +26,7 @@ import { config } from "@/config/index";
const GLOBAL_REFRESH = config.GLOBAL_REFRESH;
const InfraDetailsPage = () => {
const { t } = useTranslation();
const theme = useTheme();
const { id } = useParams();
const [range, setRange] = useState("2h");
@@ -68,13 +70,13 @@ const InfraDetailsPage = () => {
<Stack direction="row" gap={theme.spacing(8)} flexWrap={"wrap"}>
<StatBox
palette={palette}
title="Active for"
title={t("monitors.common.stats.activeFor")}
subtitle={prettyMilliseconds(streakDuration, {
secondsDecimalDigits: 0,
})}
/>
<StatBox
title="Last check"
title={t("monitors.common.stats.lastCheck")}
subtitle={
lastChecked >= 0
? `${prettyMilliseconds(lastChecked, {
@@ -84,35 +86,40 @@ const InfraDetailsPage = () => {
}
/>
<StatBox
title="Last response time"
title={t("monitors.common.stats.lastResponseTime")}
subtitle={
stats?.lastResponseTime ? `${stats?.lastResponseTime} ms` : "N/A"
}
/>
<StatBox
title="CPU (physical)"
title={t("monitors.common.stats.cpuPhysical")}
subtitle={getCores(checks[0]?.cpu?.physical_core)}
/>
<StatBox
title="CPU (logical)"
title={t("monitors.common.stats.cpuLogical")}
subtitle={getCores(checks[0]?.cpu?.logical_core)}
/>
<StatBox
title="CPU frequency"
title={t("monitors.common.stats.cpuFrequency")}
subtitle={getFrequency(checks[0]?.cpu?.current_frequency)}
/>
<StatBox
title="Avg CPU temp"
title={t("monitors.common.stats.cpuTemperature")}
subtitle={getAvgTemp(checks[0]?.cpu?.temperature)}
/>
<StatBox
title="Memory"
title={t("monitors.common.stats.memory")}
subtitle={getGbs(checks[0]?.memory?.total_bytes)}
/>
<StatBox title="Disk" subtitle={getDiskTotalGbs(checks[0]?.disk)} />
<StatBox title="OS" subtitle={getOsAndPlatform(checks[0]?.host)} />
<StatBox
title={t("monitors.common.stats.disk")}
subtitle={getDiskTotalGbs(checks[0]?.disk)}
/>
<StatBox
title={t("monitors.common.stats.os")}
subtitle={getOsAndPlatform(checks[0]?.host)}
/>
</Stack>
{/* <Typography variant="h1">Infrastructure overview</Typography> */}
<InfraDetailsGauges checks={checks} />
<HeaderRange loading={isValidating} range={range} setRange={setRange} />
@@ -3,6 +3,7 @@ import Typography from "@mui/material/Typography";
import { BaseChart } from "@/components/monitors/Chart";
import { Gauge } from "@/components/design-elements";
import { useTranslation } from "react-i18next";
import { getGbs, getFrequency } from "./InfraUtils";
import type { IInfraCheck } from "@/types/check";
import { useTheme } from "@mui/material/styles";
@@ -42,6 +43,7 @@ const InfraDetailGauge = ({
};
export const InfraDetailsGauges = ({ checks }: { checks: IInfraCheck[] }) => {
const { t } = useTranslation();
const theme = useTheme();
const isSmall = useMediaQuery(theme.breakpoints.down("md"));
return (
@@ -51,30 +53,31 @@ export const InfraDetailsGauges = ({ checks }: { checks: IInfraCheck[] }) => {
alignItems={"center"}
>
<InfraDetailGauge
title="Memory Usage"
title={t("monitors.infrastructure.gauges.memory.title")}
progress={(checks[0]?.memory.usage_percent || 0) * 100}
upperLabel="Used"
upperLabel={t("monitors.infrastructure.gauges.memory.upperLabel")}
upperValue={getGbs(checks[0]?.memory.used_bytes)}
lowerLabel="Free"
lowerLabel={t("monitors.infrastructure.gauges.memory.lowerLabel")}
lowerValue={getGbs(checks[0]?.memory.total_bytes)}
/>
<InfraDetailGauge
title="CPU Usage"
title={t("monitors.infrastructure.gauges.cpu.title")}
progress={(checks[0]?.cpu.usage_percent || 0) * 100}
upperLabel="Current frequency"
upperLabel={t("monitors.infrastructure.gauges.cpu.upperLabel")}
upperValue={getFrequency(checks[0]?.cpu.current_frequency)}
lowerLabel="Max Frequency"
lowerLabel={t("monitors.infrastructure.gauges.cpu.lowerLabel")}
lowerValue={getFrequency(checks[0]?.cpu.frequency)}
/>
{checks[0]?.disk?.map((disk, idx) => {
return (
<InfraDetailGauge
key={disk.device + idx}
title={`Disk ${idx} usage`}
// title={`Disk ${idx} usage`}
title={t("monitors.infrastructure.gauges.disk.title", { idx })}
progress={(disk.usage_percent || 0) * 100}
upperLabel="Used"
upperLabel={t("monitors.infrastructure.gauges.disk.upperLabel")}
upperValue={getGbs(disk.used_bytes)}
lowerLabel="Free"
lowerLabel={t("monitors.infrastructure.gauges.disk.lowerLabel")}
lowerValue={getGbs(disk.total_bytes)}
/>
);
@@ -1,14 +1,16 @@
import Grid from "@mui/material/Grid";
import { HistogramInfrastructure } from "@/components/monitors";
import { useTranslation } from "react-i18next";
import type { IInfraCheck } from "@/types/check";
import { useMemo } from "react";
import { useTheme } from "@mui/material/styles";
import useMediaQuery from "@mui/material/useMediaQuery";
const getChartConfigs = (theme: any, checks: IInfraCheck[]) => {
const getChartConfigs = (theme: any, checks: IInfraCheck[], t: any) => {
return [
{
title: t("common.charts.infrastructure.memory.title"),
type: "memory",
dataKeys: ["memory.usage_percent"],
strokeColor: theme.palette.primary.main,
@@ -17,6 +19,7 @@ const getChartConfigs = (theme: any, checks: IInfraCheck[]) => {
idx: null,
},
{
title: t("common.charts.infrastructure.cpu.title"),
type: "cpu",
dataKeys: ["cpu.used_percent"],
strokeColor: theme.palette.success.main,
@@ -25,6 +28,7 @@ const getChartConfigs = (theme: any, checks: IInfraCheck[]) => {
idx: null,
},
{
title: t("common.charts.infrastructure.temp.title"),
type: "temp",
dataKeys: ["avg_temp"],
strokeColor: theme.palette.error.main,
@@ -33,6 +37,7 @@ const getChartConfigs = (theme: any, checks: IInfraCheck[]) => {
idx: null,
},
...(checks[0]?.disk?.map((_, idx) => ({
title: t("common.charts.infrastructure.disk.title", { idx }),
type: "disk",
dataKeys: [`disk[${idx}].usage_percent`],
strokeColor: theme.palette.warning.main,
@@ -52,9 +57,10 @@ export const InfraDetailsGraphs = ({
}) => {
const theme = useTheme();
const isSmall = useMediaQuery(theme.breakpoints.down("md"));
const { t } = useTranslation();
const chartConfigs = useMemo(
() => getChartConfigs(theme, checks),
[theme, checks]
() => getChartConfigs(theme, checks, t),
[theme, checks, t]
);
return (
<Grid container spacing={theme.spacing(8)}>
@@ -66,7 +72,8 @@ export const InfraDetailsGraphs = ({
>
<HistogramInfrastructure
range={range}
title={config.type}
title={config.title}
type={config.type}
idx={config.idx}
key={`${config.type}-${config.idx ?? ""}`}
checks={checks}
@@ -5,6 +5,7 @@ import { HistogramPageSpeedScores } from "@/components/monitors/HistogramPageSpe
import { ChartPageSpeedReport } from "@/components/monitors/ChartPageSpeedReport";
import { ChartPageSpeedReportLegend } from "@/components/monitors/ChartPageSpeedReportLegend";
import { useTranslation } from "react-i18next";
import { useState } from "react";
import { useParams } from "react-router";
import { useTheme } from "@mui/material/styles";
@@ -18,6 +19,7 @@ import { config } from "@/config/index";
const GLOBAL_REFRESH = config.GLOBAL_REFRESH;
const PageSpeedDetailsPage = () => {
const { t } = useTranslation();
const theme = useTheme();
const { id } = useParams();
const [range, setRange] = useState("2h");
@@ -62,13 +64,13 @@ const PageSpeedDetailsPage = () => {
<Stack direction="row" gap={theme.spacing(8)}>
<StatBox
palette={palette}
title="Active for"
title={t("monitors.common.stats.activeFor")}
subtitle={prettyMilliseconds(streakDuration, {
secondsDecimalDigits: 0,
})}
/>
<StatBox
title="Last check"
title={t("monitors.common.stats.lastCheck")}
subtitle={
lastChecked >= 0
? `${prettyMilliseconds(lastChecked, {
@@ -78,7 +80,7 @@ const PageSpeedDetailsPage = () => {
}
/>
<StatBox
title="Last response time"
title={t("monitors.common.stats.lastResponseTime")}
subtitle={
stats?.lastResponseTime ? `${stats?.lastResponseTime} ms` : "N/A"
}