add worker table
This commit is contained in:
1 parent
599c599588
commit
caf8f22fec
6 files changed
+174
-7
No files matched your search
@@ -2,7 +2,7 @@ import Stack from "@mui/material/Stack";
|
||||
import Typography from "@mui/material/Typography";
|
||||
import Box from "@mui/material/Box";
|
||||
import { TableJobs, TableFailedJobs } from "./components/TableJobs";
|
||||
|
||||
import { TableWorkers } from "./components/TableWorkers";
|
||||
import { useTheme } from "@mui/material";
|
||||
import { useTranslation, Trans } from "react-i18next";
|
||||
import { useGet, usePost } from "@/Hooks/UseApi";
|
||||
@@ -25,6 +25,10 @@ export const TabQueue = () => {
|
||||
const { post, loading: isFlushing } = usePost();
|
||||
|
||||
const jobs = queueData?.jobs ?? [];
|
||||
const workers = (queueData?.metrics?.workers ?? []).map((worker, idx) => ({
|
||||
...worker,
|
||||
id: idx,
|
||||
}));
|
||||
const metrics = queueData?.metrics ?? null;
|
||||
const hasNeverRun = !isLoading && metrics !== null && (metrics.totalRuns ?? 0) === 0;
|
||||
const noQueueData = !isLoading && metrics === null && jobs.length === 0;
|
||||
@@ -46,6 +50,34 @@ export const TabQueue = () => {
|
||||
return (
|
||||
<Stack gap={theme.spacing(16)}>
|
||||
<Metrics metrics={metrics} />
|
||||
<Stack gap={theme.spacing(3)}>
|
||||
<Stack gap={theme.spacing(1)}>
|
||||
<Typography
|
||||
variant="eyebrow"
|
||||
color={theme.palette.text.secondary}
|
||||
>
|
||||
{t("pages.logs.workers")}
|
||||
</Typography>
|
||||
<Typography color={theme.palette.text.secondary}>
|
||||
<Trans
|
||||
i18nKey="pages.logs.workersExplainers"
|
||||
components={{
|
||||
highlight: (
|
||||
<Box
|
||||
component="span"
|
||||
bgcolor={theme.palette.rowStatus.running}
|
||||
color={theme.palette.text.primary}
|
||||
px={SPACING.SM}
|
||||
py={SPACING.XXS}
|
||||
borderRadius={theme.shape.borderRadius}
|
||||
/>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
</Typography>
|
||||
</Stack>
|
||||
<TableWorkers queueWorkers={workers} />
|
||||
</Stack>
|
||||
<Stack gap={theme.spacing(3)}>
|
||||
<Stack gap={theme.spacing(1)}>
|
||||
<Typography
|
||||
|
||||
@@ -127,6 +127,27 @@ export const TableJobs = ({ jobs }: TableJobsProps) => {
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "lockedBy",
|
||||
content: t("pages.logs.table.headers.lockedBy"),
|
||||
render: (row) => {
|
||||
const lockedBy = row.lockedBy;
|
||||
if (!lockedBy) {
|
||||
return <Typography sx={cellSx}>-</Typography>;
|
||||
}
|
||||
|
||||
const workerId = lockedBy.split(":")[2];
|
||||
const shortWorkerId = workerId.slice(workerId.length - 8);
|
||||
return (
|
||||
<Typography
|
||||
title={workerId}
|
||||
sx={cellSx}
|
||||
>
|
||||
{`...${shortWorkerId}`}
|
||||
</Typography>
|
||||
);
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
import { Table } from "@/Components/design-elements";
|
||||
import { Typography, useTheme } from "@mui/material";
|
||||
import { formatTimestamp } from "@/Utils/TimeUtils";
|
||||
|
||||
import { useTranslation } from "react-i18next";
|
||||
import type { QueueWorker } from "@/Types/Queue";
|
||||
import type { Header } from "@/Components/design-elements";
|
||||
|
||||
type QueueWorkerWithId = QueueWorker & { id: number };
|
||||
|
||||
interface TableWorkersProps {
|
||||
queueWorkers: QueueWorkerWithId[];
|
||||
}
|
||||
|
||||
export const TableWorkers = ({ queueWorkers }: TableWorkersProps) => {
|
||||
const { t } = useTranslation();
|
||||
const theme = useTheme();
|
||||
|
||||
const cellSx = {
|
||||
whiteSpace: "nowrap" as const,
|
||||
overflow: "hidden",
|
||||
textOverflow: "ellipsis",
|
||||
maxWidth: 220,
|
||||
};
|
||||
|
||||
const headers: Header<QueueWorkerWithId>[] = [
|
||||
{
|
||||
id: "host",
|
||||
content: t("pages.logs.table.headers.host"),
|
||||
render: (row) => {
|
||||
const host = row.workerId.split(":")[0];
|
||||
return (
|
||||
<Typography
|
||||
fontFamily={theme.typography.fontFamilyMonospace}
|
||||
sx={cellSx}
|
||||
>
|
||||
{host}
|
||||
</Typography>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "processId",
|
||||
content: t("pages.logs.table.headers.processId"),
|
||||
render: (row) => {
|
||||
const processId = row.workerId.split(":")[1];
|
||||
return (
|
||||
<Typography
|
||||
fontFamily={theme.typography.fontFamilyMonospace}
|
||||
sx={cellSx}
|
||||
>
|
||||
{processId}
|
||||
</Typography>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "id",
|
||||
content: t("pages.logs.table.headers.workerId"),
|
||||
render: (row) => {
|
||||
const workerId = row.workerId.split(":")[2];
|
||||
const shortWorkerId = workerId.slice(workerId.length - 8);
|
||||
return (
|
||||
<Typography
|
||||
fontFamily={theme.typography.fontFamilyMonospace}
|
||||
title={workerId}
|
||||
sx={cellSx}
|
||||
>
|
||||
{`...${shortWorkerId}`}
|
||||
</Typography>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "mode",
|
||||
content: t("pages.logs.table.headers.workerMode"),
|
||||
render: (row) => <Typography sx={cellSx}>{row.mode}</Typography>,
|
||||
},
|
||||
{
|
||||
id: "lastSeen",
|
||||
content: t("pages.logs.table.headers.lastSeenAt"),
|
||||
render: (row) => (
|
||||
<Typography sx={cellSx}>{formatTimestamp(row.lastSeenAt)}</Typography>
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<Table
|
||||
headers={headers}
|
||||
data={queueWorkers}
|
||||
/>
|
||||
);
|
||||
};
|
||||
@@ -8,7 +8,7 @@ import { useTranslation } from "react-i18next";
|
||||
|
||||
const LogsPage = () => {
|
||||
const { t } = useTranslation();
|
||||
const [activeTab, setActiveTab] = useState<number>(0);
|
||||
const [activeTab, setActiveTab] = useState<number>(1);
|
||||
return (
|
||||
<BasePage headerKey="logs">
|
||||
<Tabs
|
||||
|
||||
@@ -1,5 +1,14 @@
|
||||
import type { MonitorType } from "./Monitor";
|
||||
|
||||
export const QueueModes = ["primary", "worker"] as const;
|
||||
export type QueueMode = (typeof QueueModes)[number];
|
||||
|
||||
export type QueueWorker = {
|
||||
workerId: string; // hostname:pid:uuid
|
||||
mode: QueueMode;
|
||||
lastSeenAt: number; // epoch ms of the last heartbeat
|
||||
};
|
||||
|
||||
export interface QueueJobFailure {
|
||||
monitorId: string | number;
|
||||
monitorUrl: string | null;
|
||||
@@ -9,23 +18,26 @@ export interface QueueJobFailure {
|
||||
failReason: string | null;
|
||||
}
|
||||
|
||||
export interface QueueMetrics {
|
||||
export type QueueMetrics = {
|
||||
jobs: number;
|
||||
activeJobs: number;
|
||||
failingJobs: number;
|
||||
jobsWithFailures: QueueJobFailure[];
|
||||
totalRuns: number;
|
||||
totalFailures: number;
|
||||
}
|
||||
workers: QueueWorker[];
|
||||
};
|
||||
|
||||
export interface QueueJobSummary {
|
||||
export type QueueJobSummary = {
|
||||
monitorId: string | number;
|
||||
monitorUrl: string | null;
|
||||
monitorType: MonitorType | null;
|
||||
monitorType: string | null;
|
||||
monitorInterval: number | null;
|
||||
monitorGeoInterval: number | null;
|
||||
monitorActive: boolean | null;
|
||||
active: boolean;
|
||||
lockedBy: string | null;
|
||||
lockedUntil: number | null;
|
||||
lockedAt: number | null;
|
||||
runCount: number;
|
||||
failCount: number;
|
||||
@@ -35,7 +47,7 @@ export interface QueueJobSummary {
|
||||
lastRunTook: number | null;
|
||||
lastFailedAt: number | null;
|
||||
repeat: number | null;
|
||||
}
|
||||
};
|
||||
|
||||
export interface QueueData {
|
||||
jobs: QueueJobSummary[];
|
||||
|
||||
@@ -933,6 +933,8 @@
|
||||
"logLevelSelect": {
|
||||
"label": "Log level"
|
||||
},
|
||||
"workers": "Workers",
|
||||
"workersExplainers": "Shows worker processes. Worker IDs are truncated, hover for full ID",
|
||||
"jobQueue": "Job queue",
|
||||
"jobQueueExplainer": "<highlight>Highlighted rows</highlight> are jobs currently being processed by a worker.",
|
||||
"failedJobs": "Failed jobs",
|
||||
@@ -1000,6 +1002,11 @@
|
||||
},
|
||||
"table": {
|
||||
"headers": {
|
||||
"host": "Host",
|
||||
"processId": "Process ID",
|
||||
"workerId": "Worker ID",
|
||||
"workerMode": "Worker mode",
|
||||
"lastSeenAt": "Last seen at",
|
||||
"state": "State",
|
||||
"timestamp": "Timestamp",
|
||||
"level": "Level",
|
||||
@@ -1010,6 +1017,7 @@
|
||||
"failCount": "Count",
|
||||
"lastRunAt": "Last run at",
|
||||
"lockedAt": "Locked at",
|
||||
"lockedBy": "Locked by",
|
||||
"lastFinishedAt": "Last finished at",
|
||||
"lastRunTook": "Last run took",
|
||||
"lastFailedAt": "Last failed",
|
||||
|
||||
Reference in new issue
Block a user