feat: Add Proxmox LXC container monitoring support

## Summary
Add support for monitoring Proxmox LXC containers through the Capture agent's
/api/v1/metrics/proxmox endpoint. This feature is opt-in via a new setting
in the infrastructure monitor configuration.

## Backend Changes
- Add enableProxmoxContainers field to Monitor schema and types
- Update networkService to conditionally fetch Proxmox metrics
- Handle HTTP 207 multi-status responses and merge errors
- Add containers field to Check schema for storing container data
- Update validation schemas for the new setting

## Frontend Changes
- Add ContainerStats component with charts and stat boxes
- Add Containers tab to infrastructure monitor details (conditional)
- Add enableProxmoxContainers switch in monitor create/edit form
- Fix chart colors for disk I/O and network I/O to be distinct
- Add dotColor2 prop to InfrastructureTooltip for multi-series charts
- Add translation keys to all 16 locale files

## How It Works
1. User enables "Proxmox container monitoring" in monitor settings
2. Checkmate appends /proxmox to the metrics URL when fetching
3. Container data is displayed in a dedicated tab with:
   - CPU, memory, disk, swap, and uptime stat boxes
   - Interactive charts for CPU, memory, disk I/O, network I/O
4. Errors from Capture are merged and logged appropriately
This commit is contained in:
gorkem-bwl committed 2026-01-16 19:07:49 -05:00
1 parent 173a4e17d2
commit e9da602af6
35 files changed
+981 -64

No files matched your search

@@ -154,7 +154,10 @@ export const InfrastructureTooltip = ({
yKey,
yIdx = -1,
yLabel,
yKey2,
yLabel2,
dotColor,
dotColor2,
dateRange,
formatter = getFormattedPercentage,
}) => {
@@ -216,7 +219,37 @@ export const InfrastructureTooltip = ({
</Typography>
</Stack>
</Box>
{/* Display original value */}
{yKey2 && yLabel2 && (
<Box mt={theme.spacing(1)}>
<Box
display="inline-block"
width={theme.spacing(4)}
height={theme.spacing(4)}
backgroundColor={dotColor2 || dotColor}
sx={{ borderRadius: "50%" }}
/>
<Stack
display="inline-flex"
direction="row"
justifyContent="space-between"
ml={theme.spacing(3)}
sx={{
"& span": {
color: theme.palette.primary.contrastTextTertiary,
fontSize: 11,
fontWeight: 500,
},
}}
>
<Typography
component="span"
sx={{ opacity: 0.8 }}
>
{`${yLabel2} ${formatter(payload[0].payload[yKey2])}`}
</Typography>
</Stack>
</Box>
)}
</Box>
);
}
@@ -234,7 +267,10 @@ InfrastructureTooltip.propTypes = {
yKey: PropTypes.string,
yIdx: PropTypes.number,
yLabel: PropTypes.string,
yKey2: PropTypes.string,
yLabel2: PropTypes.string,
dotColor: PropTypes.string,
dotColor2: PropTypes.string,
dateRange: PropTypes.string,
};
@@ -18,6 +18,7 @@ const useInfrastructureMonitorForm = () => {
usage_temperature: "",
secret: "",
selectedDisks: [],
enableProxmoxContainers: false,
});
const onChangeForm = (name, value) => {
@@ -50,6 +51,7 @@ const useInfrastructureMonitorForm = () => {
usage_temperature: gt.temperature !== undefined ? gt.temperature.toString() : "",
secret: "",
selectedDisks: [],
enableProxmoxContainers: false,
}));
}, []);
@@ -84,6 +86,7 @@ const useInfrastructureMonitorForm = () => {
: "",
secret: monitor.secret || "",
selectedDisks: monitor.selectedDisks || [],
enableProxmoxContainers: monitor.enableProxmoxContainers ?? false,
}));
}, []);
return {
@@ -31,6 +31,7 @@ const useInfrastructureSubmit = () => {
: {}),
secret: infrastructureMonitor.secret,
selectedDisks: infrastructureMonitor.selectedDisks,
enableProxmoxContainers: infrastructureMonitor.enableProxmoxContainers,
};
return form;
};
@@ -50,6 +51,7 @@ const useInfrastructureSubmit = () => {
temperature,
usage_temperature,
selectedDisks,
enableProxmoxContainers,
...rest
} = form;
@@ -67,6 +69,7 @@ const useInfrastructureSubmit = () => {
type: "hardware",
notifications: infrastructureMonitor.notifications,
selectedDisks,
enableProxmoxContainers,
thresholds,
};
// Handle create or update
@@ -5,7 +5,7 @@ import FieldWrapper from "@/Components/v1/Inputs/FieldWrapper/index.jsx";
import Link from "@/Components/v1/Link/index.jsx";
import Select from "@/Components/v1/Inputs/Select/index.jsx";
import TextInput from "@/Components/v1/Inputs/TextInput/index.jsx";
import { Box, Stack, Typography, Button, ButtonGroup } from "@mui/material";
import { Box, Stack, Typography, Button, ButtonGroup, Switch, FormControlLabel } from "@mui/material";
import { HttpAdornment } from "@/Components/v1/Inputs/TextInput/Adornments/index.jsx";
import MonitorStatusHeader from "./Components/MonitorStatusHeader.jsx";
import MonitorActionButtons from "./Components/MonitorActionButtons.jsx";
@@ -368,6 +368,34 @@ const CreateInfrastructureMonitor = () => {
/>
)}
<ConfigBox>
<Box>
<Typography
component="h2"
variant="h2"
>
{t("proxmoxContainerMonitoring")}
</Typography>
<Typography component="p">
{t("proxmoxContainerMonitoringDescription")}
</Typography>
</Box>
<Stack>
<FormControlLabel
sx={{ marginLeft: theme.spacing(0) }}
control={
<Switch
name="enableProxmoxContainers"
checked={infrastructureMonitor.enableProxmoxContainers}
onChange={handleCheckboxChange}
sx={{ mr: theme.spacing(2) }}
/>
}
label={t("enableProxmoxContainers")}
/>
</Stack>
</ConfigBox>
<ConfigBox>
<Box>
<Typography
@@ -0,0 +1,141 @@
import PropTypes from "prop-types";
import { Stack, Typography } from "@mui/material";
import InfraAreaChart from "../AreaChartBoxes/InfraAreaChart.jsx";
import {
TzTick,
InfrastructureTooltip,
NetworkTick,
PercentTick,
} from "@/Components/v1/Charts/Utils/chartUtils.jsx";
import { useTheme } from "@emotion/react";
import { useTranslation } from "react-i18next";
import { useHardwareUtils } from "../../Hooks/useHardwareUtils.jsx";
const ContainerCharts = ({ containerData, dateRange }) => {
const theme = useTheme();
const { t } = useTranslation();
const { formatBytesPerSecondString } = useHardwareUtils();
if (!containerData?.length) {
return <Typography>{t("noContainerStatsAvailable")}</Typography>;
}
const formatPercentage = (value) => `${(value * 100).toFixed(1)}%`;
const configs = [
{
type: "container-cpu",
data: containerData,
dataKeys: ["cpuUsage"],
heading: t("cpuUsage"),
strokeColor: theme.palette.success.main,
gradientStartColor: theme.palette.success.main,
yLabel: t("usage"),
xTick: <TzTick dateRange={dateRange} />,
yTick: <PercentTick />,
toolTip: (
<InfrastructureTooltip
dotColor={theme.palette.success.main}
yKey={"cpuUsage"}
yLabel={t("cpuUsage") + ": "}
dateRange={dateRange}
formatter={formatPercentage}
/>
),
},
{
type: "container-memory",
data: containerData,
dataKeys: ["memoryUsage"],
heading: t("memoryUsage"),
strokeColor: theme.palette.accent.main,
gradientStartColor: theme.palette.accent.main,
yLabel: t("usage"),
xTick: <TzTick dateRange={dateRange} />,
yTick: <PercentTick />,
toolTip: (
<InfrastructureTooltip
dotColor={theme.palette.accent.main}
yKey={"memoryUsage"}
yLabel={t("memoryUsage") + ": "}
dateRange={dateRange}
formatter={formatPercentage}
/>
),
},
{
type: "container-disk-io",
data: containerData,
dataKeys: ["diskRead", "diskWrite"],
heading: t("diskIO"),
// Don't pass strokeColor - let chart use distinct colors from palette
yLabel: t("rate"),
xTick: <TzTick dateRange={dateRange} />,
yTick: <NetworkTick formatter={formatBytesPerSecondString} />,
toolTip: (
<InfrastructureTooltip
dotColor={"#3182bd"}
yKey={"diskRead"}
yLabel={t("diskRead") + ": "}
dotColor2={"#6baed6"}
yKey2={"diskWrite"}
yLabel2={t("diskWrite") + ": "}
dateRange={dateRange}
formatter={formatBytesPerSecondString}
/>
),
},
{
type: "container-network-io",
data: containerData,
dataKeys: ["netIn", "netOut"],
heading: t("networkIO"),
// Don't pass strokeColor - let chart use distinct colors from palette
yLabel: t("rate"),
xTick: <TzTick dateRange={dateRange} />,
yTick: <NetworkTick formatter={formatBytesPerSecondString} />,
toolTip: (
<InfrastructureTooltip
dotColor={"#3182bd"}
yKey={"netIn"}
yLabel={t("networkIn") + ": "}
dotColor2={"#6baed6"}
yKey2={"netOut"}
yLabel2={t("networkOut") + ": "}
dateRange={dateRange}
formatter={formatBytesPerSecondString}
/>
),
},
];
return (
<Stack
direction={"row"}
gap={theme.spacing(8)}
flexWrap="wrap"
sx={{
"& > *": {
flexBasis: `calc(50% - ${theme.spacing(8)})`,
maxWidth: `calc(50% - ${theme.spacing(8)})`,
},
}}
>
{configs.map((config) => (
<InfraAreaChart
key={config.type}
config={config}
/>
))}
</Stack>
);
};
ContainerCharts.propTypes = {
containerData: PropTypes.array.isRequired,
dateRange: PropTypes.string.isRequired,
};
export default ContainerCharts;
@@ -0,0 +1,130 @@
import PropTypes from "prop-types";
import StatusBoxes from "@/Components/v1/StatusBoxes/index.jsx";
import StatBox from "@/Components/v1/StatBox/index.jsx";
import { Typography } from "@mui/material";
import { useTranslation } from "react-i18next";
import { useHardwareUtils } from "../../Hooks/useHardwareUtils.jsx";
const formatUptime = (seconds) => {
if (!seconds || seconds === 0) return "0s";
const days = Math.floor(seconds / 86400);
const hours = Math.floor((seconds % 86400) / 3600);
const minutes = Math.floor((seconds % 3600) / 60);
if (days > 0) {
return `${days}d ${hours}h`;
} else if (hours > 0) {
return `${hours}h ${minutes}m`;
} else if (minutes > 0) {
return `${minutes}m`;
}
return `${Math.floor(seconds)}s`;
};
const formatPercentage = (value) => {
if (value === undefined || value === null) return "0%";
return `${(value * 100).toFixed(1)}%`;
};
// Map container status to Checkmate monitor status for theming
const containerStatusToMonitorStatus = (status) => {
if (status === "running") return "up";
if (status === "stopped") return "down";
return "pending";
};
const ContainerStatBoxes = ({ shouldRender, container }) => {
const { t } = useTranslation();
const { formatBytes } = useHardwareUtils();
if (!container) {
return <Typography>{t("noContainerSelected")}</Typography>;
}
const monitorStatus = containerStatusToMonitorStatus(container.status);
return (
<StatusBoxes
shouldRender={shouldRender}
flexWrap="wrap"
>
<StatBox
gradient={true}
status={monitorStatus}
heading={t("status")}
subHeading={container.status || "unknown"}
/>
<StatBox
heading={t("type")}
subHeading={
<Typography component="span">
{(container.type || "lxc").toUpperCase()}
</Typography>
}
/>
<StatBox
heading={t("uptime")}
subHeading={formatUptime(container.uptime)}
/>
<StatBox
heading={t("cpuUsage")}
subHeading={
<>
{formatPercentage(container.cpu_usage)}
<Typography component="span">
({container.cpu_cores || 0} {t("cores")})
</Typography>
</>
}
/>
<StatBox
heading={t("memoryUsage")}
subHeading={
<>
{formatBytes(container.memory_used)}
<Typography component="span"> / </Typography>
{formatBytes(container.memory_total)}
</>
}
/>
<StatBox
heading={t("diskUsage")}
subHeading={
<>
{formatBytes(container.disk_used)}
<Typography component="span"> / </Typography>
{formatBytes(container.disk_total)}
</>
}
/>
</StatusBoxes>
);
};
ContainerStatBoxes.propTypes = {
shouldRender: PropTypes.bool.isRequired,
container: PropTypes.shape({
vmid: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
name: PropTypes.string,
node: PropTypes.string,
status: PropTypes.string,
type: PropTypes.string,
uptime: PropTypes.number,
cpu_cores: PropTypes.number,
cpu_usage: PropTypes.number,
memory_used: PropTypes.number,
memory_total: PropTypes.number,
memory_usage: PropTypes.number,
swap_used: PropTypes.number,
swap_total: PropTypes.number,
disk_used: PropTypes.number,
disk_total: PropTypes.number,
disk_read: PropTypes.number,
disk_write: PropTypes.number,
network_in: PropTypes.number,
network_out: PropTypes.number,
}),
};
export default ContainerStatBoxes;
@@ -0,0 +1,125 @@
import PropTypes from "prop-types";
import { useState, useEffect } from "react";
import { Box, Typography } from "@mui/material";
import { useTranslation } from "react-i18next";
import { useTheme } from "@emotion/react";
import Select from "@/Components/v1/Inputs/Select/index.jsx";
import ContainerStatBoxes from "./ContainerStatBoxes.jsx";
import ContainerCharts from "./ContainerCharts.jsx";
import MonitorTimeFrameHeader from "@/Components/v1/MonitorTimeFrameHeader/index.jsx";
const getAvailableContainers = (containers) => {
return (containers || [])
.filter((c) => c.vmid && c.name)
.map((c) => ({
vmid: String(c.vmid),
name: c.name,
node: c.node,
status: c.status,
type: c.type,
}));
};
const getContainerData = (checks, vmid) => {
if (!vmid) return [];
return (checks || [])
.map((check) => {
const container = (check.containers || []).find(
(c) => String(c.vmid) === String(vmid)
);
if (!container) return null;
return {
_id: check._id,
cpuUsage: container.avgCpuUsage ?? 0,
memoryUsage: container.avgMemoryUsage ?? 0,
diskRead: container.deltaDiskRead ?? 0,
diskWrite: container.deltaDiskWrite ?? 0,
netIn: container.deltaNetIn ?? 0,
netOut: container.deltaNetOut ?? 0,
};
})
.filter(Boolean);
};
const ContainerStats = ({ containers, checks, isLoading, dateRange, setDateRange }) => {
const { t } = useTranslation();
const theme = useTheme();
const availableContainers = getAvailableContainers(containers);
const [selectedContainer, setSelectedContainer] = useState("");
useEffect(() => {
if (availableContainers.length > 0 && !selectedContainer) {
setSelectedContainer(availableContainers[0].vmid);
}
}, [availableContainers, selectedContainer]);
const containerData = getContainerData(checks, selectedContainer);
const currentContainer = containers?.find(
(c) => String(c.vmid) === String(selectedContainer)
);
if (!containers?.length) {
return (
<Box
display="flex"
justifyContent="center"
alignItems="center"
minHeight={200}
>
<Typography color={theme.palette.primary.contrastTextTertiary}>
{t("noContainersAvailable")}
</Typography>
</Box>
);
}
return (
<>
<ContainerStatBoxes
shouldRender={!isLoading}
container={currentContainer}
/>
<Box
display="flex"
justifyContent="space-between"
alignItems="flex-end"
gap={theme.spacing(4)}
>
{availableContainers.length > 0 && (
<Select
name="container"
label={t("container")}
value={selectedContainer}
onChange={(e) => setSelectedContainer(e.target.value)}
items={availableContainers.map((c) => ({
_id: c.vmid,
name: `${c.name} (${c.vmid}) - ${c.node}`,
}))}
sx={{ minWidth: 250 }}
/>
)}
<MonitorTimeFrameHeader
isLoading={isLoading}
dateRange={dateRange}
setDateRange={setDateRange}
/>
</Box>
<ContainerCharts
containerData={containerData}
dateRange={dateRange}
/>
</>
);
};
ContainerStats.propTypes = {
containers: PropTypes.array,
checks: PropTypes.array,
isLoading: PropTypes.bool.isRequired,
dateRange: PropTypes.string.isRequired,
setDateRange: PropTypes.func.isRequired,
};
export default ContainerStats;
@@ -8,6 +8,7 @@ import GaugeBoxes from "./Components/GaugeBoxes/index.jsx";
import AreaChartBoxes from "./Components/AreaChartBoxes/index.jsx";
import GenericFallback from "@/Components/v1/GenericFallback/index.jsx";
import NetworkStats from "./Components/NetworkStats/index.jsx";
import ContainerStats from "./Components/ContainerStats/index.jsx";
import CustomTabList from "@/Components/v1/Tab/index.jsx";
import TabContext from "@mui/lab/TabContext";
@@ -102,6 +103,12 @@ const InfrastructureDetails = () => {
label={t("network")}
value="network"
/>
{monitor?.enableProxmoxContainers && (
<Tab
label={t("containers")}
value="containers"
/>
)}
</CustomTabList>
{tab === "details" && (
<>
@@ -134,6 +141,15 @@ const InfrastructureDetails = () => {
setDateRange={setDateRange}
/>
)}
{tab === "containers" && monitor?.enableProxmoxContainers && (
<ContainerStats
containers={monitor?.stats?.aggregateData?.latestCheck?.containers || []}
isLoading={isLoading}
checks={monitor?.stats?.checks}
dateRange={dateRange}
setDateRange={setDateRange}
/>
)}
</TabContext>
</Stack>
);
+1
View File
@@ -450,6 +450,7 @@ const infrastructureMonitorValidation = joi.object({
}),
notifications: joi.array().items(joi.string()),
selectedDisks: joi.array().items(joi.string()).optional(),
enableProxmoxContainers: joi.boolean(),
});
const notificationValidation = joi.object({
+22 -7
View File
@@ -85,7 +85,9 @@
"networkError": "",
"fallback": {
"title": "",
"checks": [""],
"checks": [
""
],
"actionButton": ""
},
"createButton": "",
@@ -930,7 +932,9 @@
"generalSettings": "",
"contents": "",
"fallback": {
"checks": [""],
"checks": [
""
],
"title": "",
"actionButton": ""
}
@@ -985,28 +989,36 @@
},
"infrastructureMonitor": {
"fallback": {
"checks": [""],
"checks": [
""
],
"title": "",
"actionButton": ""
}
},
"maintenanceWindow": {
"fallback": {
"checks": [""],
"checks": [
""
],
"title": "",
"actionButton": ""
}
},
"pageSpeed": {
"fallback": {
"checks": [""],
"checks": [
""
],
"title": "",
"actionButton": ""
}
},
"uptimeMonitor": {
"fallback": {
"checks": [""],
"checks": [
""
],
"title": "",
"actionButton": ""
}
@@ -1104,5 +1116,8 @@
"packetsReceivedRate": "",
"packetsSent": "",
"rate": "",
"selectInterface": ""
"selectInterface": "",
"proxmoxContainerMonitoring": "Proxmox container monitoring",
"proxmoxContainerMonitoringDescription": "Enable monitoring of Proxmox LXC containers on this infrastructure node. Requires Capture agent to be configured with Proxmox API credentials.",
"enableProxmoxContainers": "Enable container monitoring"
}
+22 -7
View File
@@ -85,7 +85,9 @@
"networkError": "",
"fallback": {
"title": "",
"checks": [""],
"checks": [
""
],
"actionButton": ""
},
"createButton": "",
@@ -930,7 +932,9 @@
"generalSettings": "",
"contents": "",
"fallback": {
"checks": [""],
"checks": [
""
],
"title": "",
"actionButton": ""
}
@@ -985,28 +989,36 @@
},
"infrastructureMonitor": {
"fallback": {
"checks": [""],
"checks": [
""
],
"title": "",
"actionButton": ""
}
},
"maintenanceWindow": {
"fallback": {
"checks": [""],
"checks": [
""
],
"title": "",
"actionButton": ""
}
},
"pageSpeed": {
"fallback": {
"checks": [""],
"checks": [
""
],
"title": "",
"actionButton": ""
}
},
"uptimeMonitor": {
"fallback": {
"checks": [""],
"checks": [
""
],
"title": "",
"actionButton": ""
}
@@ -1104,5 +1116,8 @@
"packetsReceivedRate": "",
"packetsSent": "",
"rate": "",
"selectInterface": ""
"selectInterface": "",
"proxmoxContainerMonitoring": "Proxmox container monitoring",
"proxmoxContainerMonitoringDescription": "Enable monitoring of Proxmox LXC containers on this infrastructure node. Requires Capture agent to be configured with Proxmox API credentials.",
"enableProxmoxContainers": "Enable container monitoring"
}
+4 -1
View File
@@ -1136,5 +1136,8 @@
"disk_selection_info": "Momentan wurde keine Festplatte erkannt.",
"disk_selection_description": "Wählen Sie die spezifischen Festplatten aus, die Sie überwachen möchten."
}
}
},
"proxmoxContainerMonitoring": "Proxmox container monitoring",
"proxmoxContainerMonitoringDescription": "Enable monitoring of Proxmox LXC containers on this infrastructure node. Requires Capture agent to be configured with Proxmox API credentials.",
"enableProxmoxContainers": "Enable container monitoring"
}
+3
View File
@@ -181,6 +181,9 @@
"infrastructureServerUrlLabel": "Server URL",
"infrastructureDisplayNameLabel": "Display name",
"infrastructureAuthorizationSecretLabel": "Authorization secret",
"proxmoxContainerMonitoring": "Proxmox container monitoring",
"proxmoxContainerMonitoringDescription": "Enable monitoring of Proxmox LXC containers on this infrastructure node. Requires Capture agent to be configured with Proxmox API credentials.",
"enableProxmoxContainers": "Enable container monitoring",
"gb": "GB",
"mb": "MB",
"mem": "Mem",
+22 -7
View File
@@ -85,7 +85,9 @@
"networkError": "",
"fallback": {
"title": "",
"checks": [""],
"checks": [
""
],
"actionButton": ""
},
"createButton": "",
@@ -930,7 +932,9 @@
"generalSettings": "",
"contents": "",
"fallback": {
"checks": [""],
"checks": [
""
],
"title": "",
"actionButton": ""
}
@@ -985,28 +989,36 @@
},
"infrastructureMonitor": {
"fallback": {
"checks": [""],
"checks": [
""
],
"title": "",
"actionButton": ""
}
},
"maintenanceWindow": {
"fallback": {
"checks": [""],
"checks": [
""
],
"title": "",
"actionButton": ""
}
},
"pageSpeed": {
"fallback": {
"checks": [""],
"checks": [
""
],
"title": "",
"actionButton": ""
}
},
"uptimeMonitor": {
"fallback": {
"checks": [""],
"checks": [
""
],
"title": "",
"actionButton": ""
}
@@ -1104,5 +1116,8 @@
"packetsReceivedRate": "",
"packetsSent": "",
"rate": "",
"selectInterface": ""
"selectInterface": "",
"proxmoxContainerMonitoring": "Proxmox container monitoring",
"proxmoxContainerMonitoringDescription": "Enable monitoring of Proxmox LXC containers on this infrastructure node. Requires Capture agent to be configured with Proxmox API credentials.",
"enableProxmoxContainers": "Enable container monitoring"
}
+22 -7
View File
@@ -85,7 +85,9 @@
"networkError": "",
"fallback": {
"title": "",
"checks": [""],
"checks": [
""
],
"actionButton": ""
},
"createButton": "",
@@ -930,7 +932,9 @@
"generalSettings": "",
"contents": "",
"fallback": {
"checks": [""],
"checks": [
""
],
"title": "",
"actionButton": ""
}
@@ -985,28 +989,36 @@
},
"infrastructureMonitor": {
"fallback": {
"checks": [""],
"checks": [
""
],
"title": "",
"actionButton": ""
}
},
"maintenanceWindow": {
"fallback": {
"checks": [""],
"checks": [
""
],
"title": "",
"actionButton": ""
}
},
"pageSpeed": {
"fallback": {
"checks": [""],
"checks": [
""
],
"title": "",
"actionButton": ""
}
},
"uptimeMonitor": {
"fallback": {
"checks": [""],
"checks": [
""
],
"title": "",
"actionButton": ""
}
@@ -1104,5 +1116,8 @@
"packetsReceivedRate": "",
"packetsSent": "",
"rate": "",
"selectInterface": ""
"selectInterface": "",
"proxmoxContainerMonitoring": "Proxmox container monitoring",
"proxmoxContainerMonitoringDescription": "Enable monitoring of Proxmox LXC containers on this infrastructure node. Requires Capture agent to be configured with Proxmox API credentials.",
"enableProxmoxContainers": "Enable container monitoring"
}
+4 -1
View File
@@ -1136,5 +1136,8 @@
"disk_selection_info": "Aucun disque détecté pour le moment.",
"disk_selection_description": "Sélectionnez les disques spécifiques que vous souhaitez surveiller."
}
}
},
"proxmoxContainerMonitoring": "Proxmox container monitoring",
"proxmoxContainerMonitoringDescription": "Enable monitoring of Proxmox LXC containers on this infrastructure node. Requires Capture agent to be configured with Proxmox API credentials.",
"enableProxmoxContainers": "Enable container monitoring"
}
+19 -6
View File
@@ -934,7 +934,9 @@
"generalSettings": "一般設定",
"contents": "コンテンツ",
"fallback": {
"checks": [""],
"checks": [
""
],
"title": "",
"actionButton": ""
}
@@ -989,28 +991,36 @@
},
"infrastructureMonitor": {
"fallback": {
"checks": [""],
"checks": [
""
],
"title": "",
"actionButton": ""
}
},
"maintenanceWindow": {
"fallback": {
"checks": [""],
"checks": [
""
],
"title": "",
"actionButton": ""
}
},
"pageSpeed": {
"fallback": {
"checks": [""],
"checks": [
""
],
"title": "",
"actionButton": ""
}
},
"uptimeMonitor": {
"fallback": {
"checks": [""],
"checks": [
""
],
"title": "",
"actionButton": ""
}
@@ -1115,5 +1125,8 @@
"disk_selection_info": "現在ディスクが検出されていません。",
"disk_selection_description": "監視したい特定のディスクを選択してください。"
}
}
},
"proxmoxContainerMonitoring": "Proxmox container monitoring",
"proxmoxContainerMonitoringDescription": "Enable monitoring of Proxmox LXC containers on this infrastructure node. Requires Capture agent to be configured with Proxmox API credentials.",
"enableProxmoxContainers": "Enable container monitoring"
}
+4 -1
View File
@@ -1136,5 +1136,8 @@
"disk_selection_info": "Nenhum disco detectado no momento.",
"disk_selection_description": "Selecione os discos específicos que você deseja monitorar."
}
}
},
"proxmoxContainerMonitoring": "Proxmox container monitoring",
"proxmoxContainerMonitoringDescription": "Enable monitoring of Proxmox LXC containers on this infrastructure node. Requires Capture agent to be configured with Proxmox API credentials.",
"enableProxmoxContainers": "Enable container monitoring"
}
+4 -1
View File
@@ -1136,5 +1136,8 @@
"disk_selection_info": "На данный момент диск не обнаружен.",
"disk_selection_description": "Выберите конкретные диски, которые вы хотите отслеживать."
}
}
},
"proxmoxContainerMonitoring": "Proxmox container monitoring",
"proxmoxContainerMonitoringDescription": "Enable monitoring of Proxmox LXC containers on this infrastructure node. Requires Capture agent to be configured with Proxmox API credentials.",
"enableProxmoxContainers": "Enable container monitoring"
}
+4 -1
View File
@@ -1136,5 +1136,8 @@
"disk_selection_info": "ไม่พบดิสก์ในขณะนี้",
"disk_selection_description": "เลือกดิสก์ที่คุณต้องการตรวจสอบ"
}
}
},
"proxmoxContainerMonitoring": "Proxmox container monitoring",
"proxmoxContainerMonitoringDescription": "Enable monitoring of Proxmox LXC containers on this infrastructure node. Requires Capture agent to be configured with Proxmox API credentials.",
"enableProxmoxContainers": "Enable container monitoring"
}
+22 -7
View File
@@ -85,7 +85,9 @@
"networkError": "Ağ hatası oluştu",
"fallback": {
"title": "",
"checks": [""],
"checks": [
""
],
"actionButton": ""
},
"createButton": "Bildirim kanalı oluştur",
@@ -930,7 +932,9 @@
"generalSettings": "Genel ayarlar",
"contents": "İçerikler",
"fallback": {
"checks": [""],
"checks": [
""
],
"title": "",
"actionButton": ""
}
@@ -985,28 +989,36 @@
},
"infrastructureMonitor": {
"fallback": {
"checks": [""],
"checks": [
""
],
"title": "",
"actionButton": ""
}
},
"maintenanceWindow": {
"fallback": {
"checks": [""],
"checks": [
""
],
"title": "",
"actionButton": ""
}
},
"pageSpeed": {
"fallback": {
"checks": [""],
"checks": [
""
],
"title": "",
"actionButton": ""
}
},
"uptimeMonitor": {
"fallback": {
"checks": [""],
"checks": [
""
],
"title": "",
"actionButton": ""
}
@@ -1104,5 +1116,8 @@
"packetsReceivedRate": "",
"packetsSent": "",
"rate": "",
"selectInterface": ""
"selectInterface": "",
"proxmoxContainerMonitoring": "Proxmox container monitoring",
"proxmoxContainerMonitoringDescription": "Enable monitoring of Proxmox LXC containers on this infrastructure node. Requires Capture agent to be configured with Proxmox API credentials.",
"enableProxmoxContainers": "Enable container monitoring"
}
+7 -2
View File
@@ -86,7 +86,9 @@
"networkError": "",
"fallback": {
"title": "",
"checks": [""]
"checks": [
""
]
},
"createButton": "",
"createTitle": "",
@@ -834,5 +836,8 @@
"selectEnabled": "",
"title": ""
}
}
},
"proxmoxContainerMonitoring": "Proxmox container monitoring",
"proxmoxContainerMonitoringDescription": "Enable monitoring of Proxmox LXC containers on this infrastructure node. Requires Capture agent to be configured with Proxmox API credentials.",
"enableProxmoxContainers": "Enable container monitoring"
}
+7 -2
View File
@@ -86,7 +86,9 @@
"networkError": "",
"fallback": {
"title": "",
"checks": [""]
"checks": [
""
]
},
"createButton": "",
"createTitle": "",
@@ -834,5 +836,8 @@
"selectEnabled": "",
"title": ""
}
}
},
"proxmoxContainerMonitoring": "Proxmox container monitoring",
"proxmoxContainerMonitoringDescription": "Enable monitoring of Proxmox LXC containers on this infrastructure node. Requires Capture agent to be configured with Proxmox API credentials.",
"enableProxmoxContainers": "Enable container monitoring"
}
+14 -3
View File
@@ -1004,14 +1004,22 @@
},
"maintenanceWindow": {
"fallback": {
"checks": ["标记维护时段", "消除所有误解", "停止在维护窗口内发送警报"],
"checks": [
"标记维护时段",
"消除所有误解",
"停止在维护窗口内发送警报"
],
"title": "维护时段用于:",
"actionButton": "让我们创建您的第一个维护时段!"
}
},
"pageSpeed": {
"fallback": {
"checks": ["报告页面的用户体验", "帮助分析网页速度", "就如何改进页面提出建议"],
"checks": [
"报告页面的用户体验",
"帮助分析网页速度",
"就如何改进页面提出建议"
],
"title": "PageSpeed 监视器用于:",
"actionButton": "让我们创建您的第一个 PageSpeed 监视器!"
}
@@ -1128,5 +1136,8 @@
"disk_selection_info": "目前没有检测到磁盘。",
"disk_selection_description": "选择您要监控的特定磁盘。"
}
}
},
"proxmoxContainerMonitoring": "Proxmox container monitoring",
"proxmoxContainerMonitoringDescription": "Enable monitoring of Proxmox LXC containers on this infrastructure node. Requires Capture agent to be configured with Proxmox API credentials.",
"enableProxmoxContainers": "Enable container monitoring"
}
+23 -6
View File
@@ -934,7 +934,9 @@
"generalSettings": "",
"contents": "內容",
"fallback": {
"checks": [""],
"checks": [
""
],
"title": "",
"actionButton": "讓我們建立您的第一個狀態頁面!"
}
@@ -989,28 +991,40 @@
},
"infrastructureMonitor": {
"fallback": {
"checks": ["追蹤伺服器的效能", "識別瓶頸並優化資源使用", "透過即時監控確保可靠性"],
"checks": [
"追蹤伺服器的效能",
"識別瓶頸並優化資源使用",
"透過即時監控確保可靠性"
],
"title": "",
"actionButton": "讓我們建立您的第一個基礎設施監視器!"
}
},
"maintenanceWindow": {
"fallback": {
"checks": ["標記您的維護期間", "消除任何誤解", "在維護時段停止發送警報"],
"checks": [
"標記您的維護期間",
"消除任何誤解",
"在維護時段停止發送警報"
],
"title": "",
"actionButton": "讓我們建立您的第一個維護時段!"
}
},
"pageSpeed": {
"fallback": {
"checks": [""],
"checks": [
""
],
"title": "",
"actionButton": "讓我們建立您的第一個 PageSpeed 監視器!"
}
},
"uptimeMonitor": {
"fallback": {
"checks": [""],
"checks": [
""
],
"title": "",
"actionButton": "讓我們建立您的第一個正常運行時間監視器!"
}
@@ -1108,5 +1122,8 @@
"packetsReceivedRate": "",
"packetsSent": "",
"rate": "",
"selectInterface": ""
"selectInterface": "",
"proxmoxContainerMonitoring": "Proxmox container monitoring",
"proxmoxContainerMonitoringDescription": "Enable monitoring of Proxmox LXC containers on this infrastructure node. Requires Capture agent to be configured with Proxmox API credentials.",
"enableProxmoxContainers": "Enable container monitoring"
}