diff --git a/src/Charts2/PrometheusChart.jsx b/src/Charts2/PrometheusChart.jsx index 65f0fb2..db9afa7 100644 --- a/src/Charts2/PrometheusChart.jsx +++ b/src/Charts2/PrometheusChart.jsx @@ -55,7 +55,7 @@ const PrometheusChart = ({ metricInfo, chartHeight = 580 }) => { const downsampleData = (data, maxPoints = 500) => { if (data.length <= maxPoints) return data; - + const ratio = Math.ceil(data.length / maxPoints); return data.filter((_, index) => index % ratio === 0); }; @@ -64,7 +64,7 @@ const PrometheusChart = ({ metricInfo, chartHeight = 580 }) => { const seconds = (endTime.getTime() - startTime.getTime()) / 1000; return Math.max(Math.ceil(seconds / maxPoints), 1); // в секундах }; - + // Обновляем логи при изменении данных useEffect(() => { @@ -92,13 +92,13 @@ const PrometheusChart = ({ metricInfo, chartHeight = 580 }) => { }; const step = calculateStep(start, end); -const data = await metricsService.fetchMetricsRange( - metricName, - Math.floor(start.getTime() / 1000), - Math.floor(end.getTime() / 1000), - step, - extendedFilters -); + const data = await metricsService.fetchMetricsRange( + metricName, + Math.floor(start.getTime() / 1000), + Math.floor(end.getTime() / 1000), + step, + extendedFilters + ); const formattedData = downsampleData(formatMetricData(data), 100); //КОЛИЧЕСТВО ТОЧЕК НА ГРАФИКЕ @@ -256,12 +256,6 @@ const data = await metricsService.fetchMetricsRange( source_id }} ranges={ranges} - /*ranges={ranges.length > 0 ? ranges : [ - { min: 0, max: 60, status: 1 }, - { min: 60, max: 80, status: 2 }, - { min: 80, max: 90, status: 3 }, - { min: 90, max: 100, status: 4 } - ]}*/ /> {showLogs && ( diff --git a/src/Components/hooks/MetricsAnalyzer.jsx b/src/Components/hooks/MetricsAnalyzer.jsx new file mode 100644 index 0000000..989d0b0 --- /dev/null +++ b/src/Components/hooks/MetricsAnalyzer.jsx @@ -0,0 +1,156 @@ +import React, { useState, useEffect } from 'react'; +import axios from 'axios'; +import { + Button, + Typography, + Paper, + Box, + CircularProgress, + Alert, + Snackbar, + Table, + TableBody, + TableCell, + TableContainer, + TableHead, + TableRow +} from '@mui/material'; + +const MetricsAnalyzer = () => { + const [loading, setLoading] = useState(false); + const [metrics, setMetrics] = useState([]); + const [analysisResult, setAnalysisResult] = useState(null); + const [error, setError] = useState(null); + const [openSnackbar, setOpenSnackbar] = useState(false); + + const transformMetricsForAnalysis = (metrics) => { + return metrics.flatMap(metricResponse => + metricResponse.data.map(metricData => ({ + description: metricData.description, + device: parseInt(metricData.device, 10), + id: metricData.source_id, + name: metricData.__name__, + source: metricData.instance, + status: parseInt(metricData.status, 10), + timestamp: metricData.timestamp, + value: metricData.value.toString() + })) + ); + }; + + const analyzeMetrics = async () => { + try { + setLoading(true); + setError(null); + + // 1. Сначала загружаем метрики + const metricsResponse = await axios.get(`${import.meta.env.VITE_BACK_URL}/api/metrics/all-values`); + setMetrics(metricsResponse.data); + + // 2. Преобразуем и отправляем на анализ + const requestData = transformMetricsForAnalysis(metricsResponse.data); + const analysisResponse = await axios.get(`${import.meta.env.VITE_BACK_URL}:5134/api/metrics/rest`, { + data: requestData, + headers: { + 'Content-Type': 'application/json', + } + }); + + setAnalysisResult(analysisResponse.data); + setOpenSnackbar(true); + } catch (err) { + const errorMessage = err.response?.data?.message || + err.message || + 'Ошибка при анализе метрик'; + setError(errorMessage); + setOpenSnackbar(true); + } finally { + setLoading(false); + } + }; + + const handleCloseSnackbar = () => { + setOpenSnackbar(false); + }; + + return ( + + + Анализ метрик системы + + + + + + + {analysisResult && ( + + + Результаты анализа + + + {Array.isArray(analysisResult) ? ( + + + + + Параметр + Результат + Описание + + + + {analysisResult.map((item, index) => ( + + {item.name || item.parameter} + {item.value || item.result} + {item.description || '-'} + + ))} + +
+
+ ) : ( + + + {JSON.stringify(analysisResult, null, 2)} + + + )} +
+ )} + + + + {error || 'Анализ метрик успешно завершен'} + + +
+ ); +}; + +export default MetricsAnalyzer; \ No newline at end of file diff --git a/src/Components/hooks/TabContent.jsx b/src/Components/hooks/TabContent.jsx index cfc050b..5176b0b 100644 --- a/src/Components/hooks/TabContent.jsx +++ b/src/Components/hooks/TabContent.jsx @@ -2,10 +2,9 @@ import SystemStatusChart from "../../Charts/SystemStatusChart"; import TreeTable from "../UI/TreeTable"; import FlowChart from "../TreeChart/FlowChart"; import { getStatusColor } from "../TreeChart/dataUtils"; - +import MetricsAnalyzer from "./MetricsAnalyzer"; // Импортируем новый компонент const TabContent = ({ activeTab, tabs, statusHistories, treeData1, tabContent, handleOpenTab }) => { - // Функция для подсчета количества элементов каждого статуса const countStatuses = (data) => { const counts = { green: 0, yellow: 0, orange: 0, red: 0 }; @@ -66,6 +65,9 @@ const TabContent = ({ activeTab, tabs, statusHistories, treeData1, tabContent, h + + {/* Добавляем кнопку анализа + */} ); } else if (activeTab === "Визуализация") {