adding data analyzer
test-org/trust-module-frontend/pipeline/pr-rc This commit looks good
Details
test-org/trust-module-frontend/pipeline/pr-rc This commit looks good
Details
parent
61c623b93d
commit
ef5df6971d
|
|
@ -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 && (
|
||||
<StatusLogTable logs={statusLogs} />
|
||||
|
|
|
|||
|
|
@ -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 (
|
||||
<Box sx={{ maxWidth: 800, margin: '0 auto', mt: 4 }}>
|
||||
<Typography variant="h5" gutterBottom sx={{ mb: 3 }}>
|
||||
Анализ метрик системы
|
||||
</Typography>
|
||||
|
||||
<Box sx={{ display: 'flex', justifyContent: 'center', mb: 3 }}>
|
||||
<Button
|
||||
variant="contained"
|
||||
color="primary"
|
||||
onClick={analyzeMetrics}
|
||||
disabled={loading}
|
||||
startIcon={loading ? <CircularProgress size={24} /> : null}
|
||||
size="large"
|
||||
>
|
||||
{loading ? 'Выполняется анализ...' : 'Проанализировать метрики'}
|
||||
</Button>
|
||||
</Box>
|
||||
|
||||
{analysisResult && (
|
||||
<Paper elevation={3} sx={{ p: 3, mt: 2 }}>
|
||||
<Typography variant="h6" gutterBottom>
|
||||
Результаты анализа
|
||||
</Typography>
|
||||
|
||||
{Array.isArray(analysisResult) ? (
|
||||
<TableContainer>
|
||||
<Table size="small">
|
||||
<TableHead>
|
||||
<TableRow>
|
||||
<TableCell>Параметр</TableCell>
|
||||
<TableCell>Результат</TableCell>
|
||||
<TableCell>Описание</TableCell>
|
||||
</TableRow>
|
||||
</TableHead>
|
||||
<TableBody>
|
||||
{analysisResult.map((item, index) => (
|
||||
<TableRow key={index}>
|
||||
<TableCell>{item.name || item.parameter}</TableCell>
|
||||
<TableCell>{item.value || item.result}</TableCell>
|
||||
<TableCell>{item.description || '-'}</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</TableContainer>
|
||||
) : (
|
||||
<Box sx={{
|
||||
p: 2,
|
||||
backgroundColor: 'background.paper',
|
||||
borderRadius: 1,
|
||||
maxHeight: 400,
|
||||
overflow: 'auto'
|
||||
}}>
|
||||
<Typography variant="body2" component="pre">
|
||||
{JSON.stringify(analysisResult, null, 2)}
|
||||
</Typography>
|
||||
</Box>
|
||||
)}
|
||||
</Paper>
|
||||
)}
|
||||
|
||||
<Snackbar
|
||||
open={openSnackbar}
|
||||
autoHideDuration={6000}
|
||||
onClose={handleCloseSnackbar}
|
||||
anchorOrigin={{ vertical: 'top', horizontal: 'center' }}
|
||||
>
|
||||
<Alert
|
||||
onClose={handleCloseSnackbar}
|
||||
severity={error ? 'error' : 'success'}
|
||||
sx={{ width: '100%' }}
|
||||
>
|
||||
{error || 'Анализ метрик успешно завершен'}
|
||||
</Alert>
|
||||
</Snackbar>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
export default MetricsAnalyzer;
|
||||
|
|
@ -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
|
|||
|
||||
<label>Статус компонентов системы</label>
|
||||
<TreeTable data={treeData1} />
|
||||
|
||||
{/* Добавляем кнопку анализа
|
||||
<MetricsAnalyzer />*/}
|
||||
</div>
|
||||
);
|
||||
} else if (activeTab === "Визуализация") {
|
||||
|
|
|
|||
Loading…
Reference in New Issue