mirror of
https://github.com/bluewave-labs/Checkmate.git
synced 2026-01-03 16:20:06 -06:00
resolve disk selection persistence and validation issues
This commit is contained in:
@@ -91,6 +91,7 @@ Feel free to ask questions or share your ideas - we'd love to hear from you!
|
||||
- Website monitoring
|
||||
- Page speed monitoring
|
||||
- Infrastructure monitoring (memory, disk usage, CPU performance, network etc) - requires [Capture](https://github.com/bluewave-labs/capture) agent
|
||||
- Selective disk monitoring with mountpoint selection
|
||||
- Docker monitoring
|
||||
- Ping monitoring
|
||||
- SSL monitoring
|
||||
|
||||
@@ -387,6 +387,7 @@ const useUpdateMonitor = () => {
|
||||
...(monitor.type === "hardware" && {
|
||||
thresholds: monitor.thresholds,
|
||||
secret: monitor.secret,
|
||||
selectedDisks: monitor.selectedDisks,
|
||||
}),
|
||||
};
|
||||
await networkService.updateMonitor({
|
||||
|
||||
@@ -11,7 +11,6 @@ const DiskSelection = ({ availableDisks, selectedDisks, onChange }) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const handleDiskChange = (event, mountpoint) => {
|
||||
// Le composant Checkbox personnalisé renvoie l'event natif
|
||||
const isChecked = event.target.checked;
|
||||
let newSelectedDisks = [];
|
||||
|
||||
@@ -37,42 +36,38 @@ const DiskSelection = ({ availableDisks, selectedDisks, onChange }) => {
|
||||
|
||||
<Stack gap={theme.spacing(6)}>
|
||||
{(!availableDisks || availableDisks.length === 0) ? (
|
||||
<Typography
|
||||
variant="body2"
|
||||
<Typography
|
||||
variant="body2"
|
||||
sx={{ fontStyle: 'italic', opacity: 0.8 }}
|
||||
>
|
||||
{t("v1.infrastructure.disk_selection_info")}
|
||||
</Typography>
|
||||
) : (
|
||||
availableDisks.map((disk) => (
|
||||
/* Reproduction exacte de la structure de CustomThreshold
|
||||
pour garantir l'alignement parfait avec la section Alertes
|
||||
*/
|
||||
<Stack
|
||||
key={disk.mountpoint}
|
||||
direction={{ sm: "column", md: "row" }}
|
||||
spacing={theme.spacing(2)}
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
// Mêmes largeurs que dans CustomThreshold pour aligner les labels
|
||||
width: { md: "45%", lg: "25%", xl: "20%" },
|
||||
}}
|
||||
justifyContent="flex-start"
|
||||
availableDisks.map((disk) => {
|
||||
const identifier = disk.mountpoint || disk.device;
|
||||
return (
|
||||
<Stack
|
||||
key={identifier}
|
||||
direction={{ sm: "column", md: "row" }}
|
||||
spacing={theme.spacing(2)}
|
||||
>
|
||||
<Checkbox
|
||||
id={`disk-${disk.mountpoint}`}
|
||||
name={disk.mountpoint}
|
||||
label={disk.mountpoint}
|
||||
isChecked={selectedDisks.includes(disk.mountpoint)}
|
||||
onChange={(e) => handleDiskChange(e, disk.mountpoint)}
|
||||
/>
|
||||
</Box>
|
||||
{/* Pas de deuxième Stack ici car nous n'avons pas besoin
|
||||
du champ TextInput pour la sélection simple
|
||||
*/}
|
||||
</Stack>
|
||||
))
|
||||
<Box
|
||||
sx={{
|
||||
width: "100%",
|
||||
}}
|
||||
justifyContent="flex-start"
|
||||
>
|
||||
<Checkbox
|
||||
id={`disk-${identifier}`}
|
||||
name={identifier}
|
||||
label={identifier}
|
||||
isChecked={selectedDisks.includes(identifier)}
|
||||
onChange={(e) => handleDiskChange(e, identifier)}
|
||||
/>
|
||||
</Box>
|
||||
</Stack>
|
||||
)
|
||||
})
|
||||
)}
|
||||
</Stack>
|
||||
</ConfigBox>
|
||||
|
||||
@@ -29,11 +29,11 @@ const useInfrastructureSubmit = () => {
|
||||
...(infrastructureMonitor.disk
|
||||
? { usage_disk: infrastructureMonitor.usage_disk }
|
||||
: {}),
|
||||
temperature: infrastructureMonitor.temperature,
|
||||
...(infrastructureMonitor.temperature
|
||||
? { usage_temperature: infrastructureMonitor.usage_temperature }
|
||||
: {}),
|
||||
secret: infrastructureMonitor.secret,
|
||||
selectedDisks: infrastructureMonitor.selectedDisks,
|
||||
};
|
||||
return form;
|
||||
};
|
||||
@@ -52,6 +52,7 @@ const useInfrastructureSubmit = () => {
|
||||
usage_disk,
|
||||
temperature,
|
||||
usage_temperature,
|
||||
selectedDisks,
|
||||
...rest
|
||||
} = form;
|
||||
|
||||
@@ -68,6 +69,7 @@ const useInfrastructureSubmit = () => {
|
||||
description: form.name,
|
||||
type: "hardware",
|
||||
notifications: infrastructureMonitor.notifications,
|
||||
selectedDisks,
|
||||
thresholds,
|
||||
};
|
||||
// Handle create or update
|
||||
|
||||
@@ -14,7 +14,7 @@ import DiskSelection from "./Components/DiskSelection.jsx";
|
||||
// Utils
|
||||
import NotificationsConfig from "@/Components/v1/NotificationConfig/index.jsx";
|
||||
import { useGetNotificationsByTeamId } from "../../../../Hooks/v1/useNotifications.js";
|
||||
import NetworkService from "../../../../Utils/NetworkService";
|
||||
import { networkService } from "../../../../Utils/NetworkService";
|
||||
import { useParams } from "react-router-dom";
|
||||
import { useState, useEffect } from "react";
|
||||
import { useTheme } from "@emotion/react";
|
||||
@@ -75,9 +75,9 @@ const CreateInfrastructureMonitor = () => {
|
||||
...(isCreate
|
||||
? [{ name: "Create", path: "/infrastructure/create" }]
|
||||
: [
|
||||
{ name: "Details", path: `/infrastructure/${monitorId}` },
|
||||
{ name: "Configure", path: `/infrastructure/configure/${monitorId}` },
|
||||
]),
|
||||
{ name: "Details", path: `/infrastructure/${monitorId}` },
|
||||
{ name: "Configure", path: `/infrastructure/configure/${monitorId}` },
|
||||
]),
|
||||
];
|
||||
// Populate form fields if editing
|
||||
useEffect(() => {
|
||||
@@ -89,23 +89,30 @@ const CreateInfrastructureMonitor = () => {
|
||||
setHttps(monitor.url.startsWith("https"));
|
||||
initializeInfrastructureMonitorForUpdate(monitor);
|
||||
const fetchLastCheck = async () => {
|
||||
try {
|
||||
const params = {
|
||||
dateRange: "recent",
|
||||
limit: 1,
|
||||
sortOrder: "desc",
|
||||
};
|
||||
// On utilise NetworkService directement
|
||||
const response = await NetworkService.get(`/api/v1/checks/${monitorId}`, { params });
|
||||
const disks = response?.data?.checks?.[0]?.payload?.disks || [];
|
||||
setAvailableDisks(disks);
|
||||
} catch (error) {
|
||||
console.error("Erreur pendant la récupération des disques:", error);
|
||||
setAvailableDisks([]); // En cas d'erreur, on met un tableau vide
|
||||
}
|
||||
};
|
||||
try {
|
||||
const { stats } = monitor ?? {};
|
||||
let latestCheck = stats?.aggregateData?.latestCheck;
|
||||
let disks = latestCheck?.disk || [];
|
||||
|
||||
fetchLastCheck();
|
||||
if (disks.length > 0) {
|
||||
setAvailableDisks(disks);
|
||||
return;
|
||||
}
|
||||
|
||||
const response = await networkService.getChecksByMonitor({
|
||||
monitorId,
|
||||
dateRange: "all",
|
||||
rowsPerPage: 1,
|
||||
sortOrder: "desc",
|
||||
});
|
||||
disks = response?.data?.data?.checks?.[0]?.disk || [];
|
||||
setAvailableDisks(disks);
|
||||
} catch (error) {
|
||||
setAvailableDisks([]);
|
||||
}
|
||||
};
|
||||
|
||||
fetchLastCheck();
|
||||
}
|
||||
}, [
|
||||
isCreate,
|
||||
@@ -154,14 +161,7 @@ const CreateInfrastructureMonitor = () => {
|
||||
isPausing ||
|
||||
notificationsAreLoading;
|
||||
|
||||
// --- AJOUT TEMPORAIRE : Fausses données ---
|
||||
const MOCK_DISKS = [
|
||||
{ mountpoint: "C:" },
|
||||
{ mountpoint: "D:" },
|
||||
{ mountpoint: "/mnt/data" },
|
||||
{ mountpoint: "/var/lib/docker" }
|
||||
];
|
||||
// -----------------------------------------
|
||||
|
||||
|
||||
return (
|
||||
<Box className="create-infrastructure-monitor">
|
||||
@@ -359,15 +359,15 @@ const CreateInfrastructureMonitor = () => {
|
||||
/>
|
||||
|
||||
{monitorId && (
|
||||
<DiskSelection
|
||||
availableDisks={availableDisks}
|
||||
selectedDisks={infrastructureMonitor.selectedDisks}
|
||||
onChange={(newSelectedDisks) =>
|
||||
onChangeForm("selectedDisks", newSelectedDisks)
|
||||
}
|
||||
/>
|
||||
)}
|
||||
|
||||
<DiskSelection
|
||||
availableDisks={availableDisks}
|
||||
selectedDisks={infrastructureMonitor.selectedDisks}
|
||||
onChange={(newSelectedDisks) =>
|
||||
onChangeForm("selectedDisks", newSelectedDisks)
|
||||
}
|
||||
/>
|
||||
)}
|
||||
|
||||
<ConfigBox>
|
||||
<Box>
|
||||
<Typography
|
||||
|
||||
@@ -46,20 +46,27 @@ const Gauges = ({ isLoading = false, monitor }) => {
|
||||
metricTwo: t("frequency"),
|
||||
valueTwo: `${(cpuFrequency / 1000).toFixed(2)} Ghz`,
|
||||
},
|
||||
...(latestCheck?.disk ?? []).map((disk, idx) => ({
|
||||
type: "disk",
|
||||
diskIndex: idx,
|
||||
value: decimalToPercentage(disk.usage_percent),
|
||||
heading: `Disk${idx} usage`,
|
||||
metricOne: t("used"),
|
||||
valueOne: formatBytes(disk.total_bytes - disk.free_bytes, true),
|
||||
metricTwo: t("total"),
|
||||
valueTwo: formatBytes(disk.total_bytes, true),
|
||||
metricThree: t("device"),
|
||||
valueThree: formatDeviceName(disk.device),
|
||||
metricFour: t("mountpoint"),
|
||||
valueFour: formatMountpoint(disk.mountpoint),
|
||||
})),
|
||||
...(latestCheck?.disk ?? [])
|
||||
.filter((disk) => {
|
||||
if (!monitor?.selectedDisks || monitor.selectedDisks.length === 0) {
|
||||
return true;
|
||||
}
|
||||
return monitor.selectedDisks.includes(disk.mountpoint || disk.device);
|
||||
})
|
||||
.map((disk, idx) => ({
|
||||
type: "disk",
|
||||
diskIndex: idx,
|
||||
value: decimalToPercentage(disk.usage_percent),
|
||||
heading: `Disk${idx} usage`,
|
||||
metricOne: t("used"),
|
||||
valueOne: formatBytes(disk.total_bytes - disk.free_bytes, true),
|
||||
metricTwo: t("total"),
|
||||
valueTwo: formatBytes(disk.total_bytes, true),
|
||||
metricThree: t("device"),
|
||||
valueThree: formatDeviceName(disk.device),
|
||||
metricFour: t("mountpoint"),
|
||||
valueFour: formatMountpoint(disk.mountpoint),
|
||||
})),
|
||||
];
|
||||
|
||||
return (
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Typography } from "@mui/material";
|
||||
import { Typography, Tooltip } from "@mui/material";
|
||||
import { useTheme } from "@emotion/react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
@@ -121,19 +121,84 @@ const useHardwareUtils = () => {
|
||||
};
|
||||
|
||||
const formatDeviceName = (device) => {
|
||||
const deviceStr = String(device || '');
|
||||
|
||||
// Extract the last part of the path (after last '/')
|
||||
const parts = deviceStr.split('/');
|
||||
const lastPart = parts[parts.length - 1];
|
||||
|
||||
// If there's more than one part, show with "..." prefix
|
||||
const displayText = parts.length > 1 ? `.../${lastPart}` : deviceStr;
|
||||
|
||||
// Always show tooltip with full device path
|
||||
return (
|
||||
<>
|
||||
{String(device)}
|
||||
</>
|
||||
<Tooltip title={deviceStr} arrow placement="top">
|
||||
<Typography
|
||||
component="span"
|
||||
sx={{
|
||||
cursor: 'default',
|
||||
display: 'inline-block',
|
||||
userSelect: 'none',
|
||||
whiteSpace: 'nowrap',
|
||||
overflow: 'hidden',
|
||||
textOverflow: 'ellipsis',
|
||||
maxWidth: '100%'
|
||||
}}
|
||||
>
|
||||
{displayText}
|
||||
</Typography>
|
||||
</Tooltip>
|
||||
);
|
||||
};
|
||||
|
||||
const formatMountpoint = (mountpoint) => {
|
||||
const mountpointStr = String(mountpoint || '');
|
||||
|
||||
if (!mountpointStr) {
|
||||
return (
|
||||
<Tooltip title="No mountpoint available" arrow placement="top">
|
||||
<Typography
|
||||
component="span"
|
||||
sx={{
|
||||
cursor: 'default',
|
||||
display: 'inline-block',
|
||||
userSelect: 'none',
|
||||
color: 'text.secondary',
|
||||
fontStyle: 'italic'
|
||||
}}
|
||||
>
|
||||
N/A
|
||||
</Typography>
|
||||
</Tooltip>
|
||||
);
|
||||
}
|
||||
|
||||
// Extract the last part of the path (after last '/')
|
||||
const parts = mountpointStr.split('/');
|
||||
const lastPart = parts[parts.length - 1];
|
||||
|
||||
// If there's more than one part, show with "..." prefix
|
||||
const displayText = parts.length > 1 ? `.../${lastPart}` : mountpointStr;
|
||||
|
||||
// Always show tooltip with full mountpoint path
|
||||
return (
|
||||
<>
|
||||
{String(mountpoint)}
|
||||
</>
|
||||
)
|
||||
<Tooltip title={mountpointStr} arrow placement="top">
|
||||
<Typography
|
||||
component="span"
|
||||
sx={{
|
||||
cursor: 'default',
|
||||
display: 'inline-block',
|
||||
userSelect: 'none',
|
||||
whiteSpace: 'nowrap',
|
||||
overflow: 'hidden',
|
||||
textOverflow: 'ellipsis',
|
||||
maxWidth: '100%'
|
||||
}}
|
||||
>
|
||||
{displayText}
|
||||
</Typography>
|
||||
</Tooltip>
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -144,44 +144,44 @@ const monitorValidation = joi.object({
|
||||
// Regex from https://gist.github.com/dperini/729294
|
||||
var urlRegex = new RegExp(
|
||||
"^" +
|
||||
// protocol identifier (optional)
|
||||
// short syntax // still required
|
||||
"(?:(?:https?|ftp):\\/\\/)?" +
|
||||
// user:pass BasicAuth (optional)
|
||||
"(?:" +
|
||||
// IP address dotted notation octets
|
||||
// excludes loopback network 0.0.0.0
|
||||
// excludes reserved space >= 224.0.0.0
|
||||
// excludes network & broadcast addresses
|
||||
// (first & last IP address of each class)
|
||||
"(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])" +
|
||||
"(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}" +
|
||||
"(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))" +
|
||||
"|" +
|
||||
// host & domain names, may end with dot
|
||||
// can be replaced by a shortest alternative
|
||||
// (?![-_])(?:[-\\w\\u00a1-\\uffff]{0,63}[^-_]\\.)+
|
||||
"(?:" +
|
||||
// Single hostname without dots (like localhost)
|
||||
"[a-z0-9\\u00a1-\\uffff][a-z0-9\\u00a1-\\uffff_-]{0,62}" +
|
||||
"|" +
|
||||
// Domain with dots
|
||||
"(?:" +
|
||||
"(?:" +
|
||||
"[a-z0-9\\u00a1-\\uffff]" +
|
||||
"[a-z0-9\\u00a1-\\uffff_-]{0,62}" +
|
||||
")?" +
|
||||
"[a-z0-9\\u00a1-\\uffff]\\." +
|
||||
")+" +
|
||||
// TLD identifier name, may end with dot
|
||||
"(?:[a-z\\u00a1-\\uffff]{2,}\\.?)" +
|
||||
")" +
|
||||
")" +
|
||||
// port number (optional)
|
||||
"(?::\\d{2,5})?" +
|
||||
// resource path (optional)
|
||||
"(?:[/?#]\\S*)?" +
|
||||
"$",
|
||||
// protocol identifier (optional)
|
||||
// short syntax // still required
|
||||
"(?:(?:https?|ftp):\\/\\/)?" +
|
||||
// user:pass BasicAuth (optional)
|
||||
"(?:" +
|
||||
// IP address dotted notation octets
|
||||
// excludes loopback network 0.0.0.0
|
||||
// excludes reserved space >= 224.0.0.0
|
||||
// excludes network & broadcast addresses
|
||||
// (first & last IP address of each class)
|
||||
"(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])" +
|
||||
"(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}" +
|
||||
"(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))" +
|
||||
"|" +
|
||||
// host & domain names, may end with dot
|
||||
// can be replaced by a shortest alternative
|
||||
// (?![-_])(?:[-\\w\\u00a1-\\uffff]{0,63}[^-_]\\.)+
|
||||
"(?:" +
|
||||
// Single hostname without dots (like localhost)
|
||||
"[a-z0-9\\u00a1-\\uffff][a-z0-9\\u00a1-\\uffff_-]{0,62}" +
|
||||
"|" +
|
||||
// Domain with dots
|
||||
"(?:" +
|
||||
"(?:" +
|
||||
"[a-z0-9\\u00a1-\\uffff]" +
|
||||
"[a-z0-9\\u00a1-\\uffff_-]{0,62}" +
|
||||
")?" +
|
||||
"[a-z0-9\\u00a1-\\uffff]\\." +
|
||||
")+" +
|
||||
// TLD identifier name, may end with dot
|
||||
"(?:[a-z\\u00a1-\\uffff]{2,}\\.?)" +
|
||||
")" +
|
||||
")" +
|
||||
// port number (optional)
|
||||
"(?::\\d{2,5})?" +
|
||||
// resource path (optional)
|
||||
"(?:[/?#]\\S*)?" +
|
||||
"$",
|
||||
"i"
|
||||
);
|
||||
if (!urlRegex.test(value)) {
|
||||
@@ -448,6 +448,7 @@ const infrastructureMonitorValidation = joi.object({
|
||||
"number.max": "Status window threshold cannot exceed 100%.",
|
||||
}),
|
||||
notifications: joi.array().items(joi.string()),
|
||||
selectedDisks: joi.array().items(joi.string()).optional(),
|
||||
});
|
||||
|
||||
const notificationValidation = joi.object({
|
||||
|
||||
@@ -1129,5 +1129,12 @@
|
||||
"packetsReceivedRate": "Rate empfangener Pakete",
|
||||
"packetsSent": "Gesendete Pakete",
|
||||
"rate": "Rate",
|
||||
"selectInterface": "Schnittstelle auswählen"
|
||||
"selectInterface": "Schnittstelle auswählen",
|
||||
"v1": {
|
||||
"infrastructure": {
|
||||
"disk_selection_title": "Festplattenauswahl",
|
||||
"disk_selection_info": "Momentan wurde keine Festplatte erkannt.",
|
||||
"disk_selection_description": "Wählen Sie die spezifischen Festplatten aus, die Sie überwachen möchten."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1129,5 +1129,12 @@
|
||||
"packetsReceivedRate": "",
|
||||
"packetsSent": "",
|
||||
"rate": "",
|
||||
"selectInterface": ""
|
||||
"selectInterface": "",
|
||||
"v1": {
|
||||
"infrastructure": {
|
||||
"disk_selection_title": "Sélection des disques",
|
||||
"disk_selection_info": "Aucun disque détecté pour le moment.",
|
||||
"disk_selection_description": "Sélectionnez les disques spécifiques que vous souhaitez surveiller."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1108,5 +1108,12 @@
|
||||
"packetsReceivedRate": "",
|
||||
"packetsSent": "",
|
||||
"rate": "",
|
||||
"selectInterface": ""
|
||||
"selectInterface": "",
|
||||
"v1": {
|
||||
"infrastructure": {
|
||||
"disk_selection_title": "ディスク選択",
|
||||
"disk_selection_info": "現在ディスクが検出されていません。",
|
||||
"disk_selection_description": "監視したい特定のディスクを選択してください。"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1129,5 +1129,12 @@
|
||||
"packetsReceivedRate": "",
|
||||
"packetsSent": "",
|
||||
"rate": "",
|
||||
"selectInterface": ""
|
||||
"selectInterface": "",
|
||||
"v1": {
|
||||
"infrastructure": {
|
||||
"disk_selection_title": "Seleção de Discos",
|
||||
"disk_selection_info": "Nenhum disco detectado no momento.",
|
||||
"disk_selection_description": "Selecione os discos específicos que você deseja monitorar."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1129,5 +1129,12 @@
|
||||
"packetsReceivedRate": "Скорость получения пакетов",
|
||||
"packetsSent": "Отправлено пакетов",
|
||||
"rate": "коэффициент",
|
||||
"selectInterface": "Выберите интерфейс"
|
||||
"selectInterface": "Выберите интерфейс",
|
||||
"v1": {
|
||||
"infrastructure": {
|
||||
"disk_selection_title": "Выбор дисков",
|
||||
"disk_selection_info": "На данный момент диск не обнаружен.",
|
||||
"disk_selection_description": "Выберите конкретные диски, которые вы хотите отслеживать."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1129,5 +1129,12 @@
|
||||
"packetsReceivedRate": "อัตราการรับแพ็กเก็ต",
|
||||
"packetsSent": "แพ็กเก็ตที่ส่ง",
|
||||
"rate": "อัตรา",
|
||||
"selectInterface": "เลือกอินเทอร์เฟซ"
|
||||
"selectInterface": "เลือกอินเทอร์เฟซ",
|
||||
"v1": {
|
||||
"infrastructure": {
|
||||
"disk_selection_title": "การเลือกดิสก์",
|
||||
"disk_selection_info": "ไม่พบดิสก์ในขณะนี้",
|
||||
"disk_selection_description": "เลือกดิสก์ที่คุณต้องการตรวจสอบ"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1121,5 +1121,12 @@
|
||||
"packetsReceivedRate": "数据包接收率",
|
||||
"packetsSent": "已发送数据包",
|
||||
"rate": "速度",
|
||||
"selectInterface": "选择接口"
|
||||
"selectInterface": "选择接口",
|
||||
"v1": {
|
||||
"infrastructure": {
|
||||
"disk_selection_title": "磁盘选择",
|
||||
"disk_selection_info": "目前没有检测到磁盘。",
|
||||
"disk_selection_description": "选择您要监控的特定磁盘。"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
74
docs/infrastructure-disk-selection.md
Normal file
74
docs/infrastructure-disk-selection.md
Normal file
@@ -0,0 +1,74 @@
|
||||
# Infrastructure Monitoring - Disk Selection
|
||||
|
||||
This guide explains how to use the selective disk monitoring feature in Checkmate's infrastructure monitoring.
|
||||
|
||||
## Overview
|
||||
|
||||
By default, Checkmate monitors all detected disks on your server. The disk selection feature allows you to choose specific disks/mountpoints to monitor, giving you more control over what gets tracked and displayed.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Checkmate server running with [Capture agent](https://github.com/bluewave-labs/capture) installed on target server
|
||||
- An existing infrastructure monitor already created and configured
|
||||
- At least one disk detected by the Capture agent
|
||||
|
||||
## Using Disk Selection
|
||||
|
||||
### Accessing the Feature
|
||||
|
||||
1. Navigate to your Infrastructure monitors page
|
||||
2. Click on an existing infrastructure monitor to view details
|
||||
3. Click the "Configure" or "Edit" button
|
||||
4. Scroll down to the **Disk Selection** section
|
||||
|
||||
> **Note:** The disk selection feature is only available when editing existing monitors that have already detected disks.
|
||||
|
||||
### Selecting Disks to Monitor
|
||||
|
||||
1. **View Available Disks**: The system automatically detects all disks/mountpoints from your server
|
||||
2. **Select Disks**: Check the boxes next to the disks you want to monitor
|
||||
3. **Apply Changes**: Click "Save" to update your monitor configuration
|
||||
|
||||
### Understanding Disk Identifiers
|
||||
|
||||
Disks are identified by their mountpoint or device name:
|
||||
- **Mountpoint**: `/` (root), `/home`, `/var`, etc.
|
||||
- **Device**: `/dev/sda1`, `/dev/nvme0n1p1`, etc.
|
||||
|
||||
### Behavior
|
||||
|
||||
- **All disks selected**: Shows all detected disks in gauges and charts
|
||||
- **Specific disks selected**: Only shows selected disks in the monitoring interface
|
||||
- **No disks detected**: Displays "No disk detected for the moment" message
|
||||
|
||||
## What Gets Filtered
|
||||
|
||||
When you select specific disks, the following elements are filtered:
|
||||
|
||||
- **Disk Usage Gauges**: Only selected disks appear in the dashboard
|
||||
- **Disk Usage Charts**: Time-series charts show only selected disks
|
||||
- **Monitor Table**: Summary view reflects only selected disk usage
|
||||
|
||||
## Example Use Cases
|
||||
|
||||
- **Server with multiple drives**: Monitor only critical system disks, ignore temporary storage
|
||||
- **Database servers**: Focus monitoring on database partition while ignoring logs partition
|
||||
- **Web servers**: Monitor web content disk separately from system disk
|
||||
- **Development environments**: Track only project-specific mountpoints
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### No Disks Appearing
|
||||
- Verify the Capture agent is running on the target server
|
||||
- Check that the agent has proper permissions to read disk information
|
||||
- Ensure the monitor has been running long enough to collect at least one check
|
||||
|
||||
### Missing Disk Information
|
||||
- Some disks may not be accessible to the Capture agent due to permissions
|
||||
- Virtual or network-mounted disks may not appear in the list
|
||||
- Check the Capture agent logs for any disk detection errors
|
||||
|
||||
## Related Documentation
|
||||
|
||||
- [Infrastructure Monitoring Setup](https://docs.checkmate.so/checkmate-2.1)
|
||||
- [Capture Agent Installation](https://github.com/bluewave-labs/capture)
|
||||
Reference in New Issue
Block a user