fixed bugs
test-org/trust-module-frontend/pipeline/pr-rc This commit looks good Details

pull/29/head
DmitriyA 2025-04-04 15:31:20 -04:00
parent 32ece2f0ff
commit a24b89220c
1 changed files with 81 additions and 97 deletions

View File

@ -43,9 +43,12 @@ const PrometheusChart = ({ metricName }) => {
}, []); }, []);
const setupWebSocket = useCallback(() => { const setupWebSocket = useCallback(() => {
if (socketRef.current?.connected) return socketRef.current; if (socketRef.current) {
// Если соединение уже существует, возвращаем его
if (socketRef.current) socketRef.current.disconnect(); if (socketRef.current.connected) return socketRef.current;
// Если соединение в процессе переподключения, тоже возвращаем
if (socketRef.current.reconnecting) return socketRef.current;
}
const socket = io('http://192.168.2.39:3000/metrics-ws', { const socket = io('http://192.168.2.39:3000/metrics-ws', {
transports: ['websocket'], transports: ['websocket'],
@ -97,104 +100,73 @@ const PrometheusChart = ({ metricName }) => {
}, []); }, []);
const fetchData = useCallback(() => { const fetchData = useCallback(() => {
try {
const now = Math.floor(Date.now() / 1000);
let start = useCustomRange
? Math.floor(startDate.getTime() / 1000)
: now - selectedRange.value;
let end = useCustomRange
? Math.floor(endDate.getTime() / 1000)
: now;
if (start >= end) {
console.error('Invalid time range: start >= end');
return;
}
const step = calculateStep(start, end);
console.log(`Fetching data for ${metricName}`, { start, end, step });
if (socketRef.current?.connected) {
socketRef.current.emit('get-metrics', {
metric: metricName,
start,
end,
step
});
} else {
console.error('WebSocket is not connected');
setupWebSocket();
}
} catch (error) {
console.error('Error in fetchData:', error);
}
}, [metricName, selectedRange, useCustomRange, startDate, endDate, calculateStep, setupWebSocket]);
const processMetricsData = useCallback((response) => {
const { metric, data } = response;
if (metric !== metricName) return;
if (!Array.isArray(data)) {
console.error('Invalid data format:', data);
return;
}
console.log('Processing metrics data:', data);
const now = Math.floor(Date.now() / 1000); const now = Math.floor(Date.now() / 1000);
const rangeSeconds = useCustomRange const start = now - selectedRange.value;
? Math.floor(endDate.getTime() / 1000) - Math.floor(startDate.getTime() / 1000) const end = now;
: selectedRange.value; const step = calculateStep(start, end);
const instancesData = {}; if (socketRef.current?.connected) {
socketRef.current.emit('get-metrics', {
data.forEach(item => { metric: metricName,
const instance = item.instance || 'default'; start,
const timestamp = item.timestamp; end,
const value = parseFloat(item.value); step,
_t: Date.now() // Добавляем timestamp для уникальности
if (!instancesData[instance]) {
instancesData[instance] = [];
}
const formatted = formatTime(timestamp, rangeSeconds);
instancesData[instance].push({
time: formatted.display, // для отображения
value: value,
timestamp: timestamp, // для сортировки
originalTime: formatted // для группировки
}); });
}
}, [metricName, selectedRange.value]); // Только необходимые зависимости
const groupBySecond = (points) => {
const grouped = [];
const timeMap = {};
points.forEach(point => {
const timeKey = Math.floor(point.timestamp / 1000);
if (!timeMap[timeKey]) {
timeMap[timeKey] = { ...point, count: 1 };
grouped.push(timeMap[timeKey]);
} else {
timeMap[timeKey].value = (timeMap[timeKey].value * timeMap[timeKey].count + point.value) /
(timeMap[timeKey].count + 1);
timeMap[timeKey].count += 1;
}
}); });
// Группируем точки с одинаковым временем (в пределах секунды) return grouped;
Object.keys(instancesData).forEach(instance => { };
const grouped = [];
const timeMap = {};
instancesData[instance].forEach(point => { const processMetricsData = useCallback((response) => {
const timeKey = Math.floor(point.timestamp / 1000); // группируем по секундам if (response.metric !== metricName || !Array.isArray(response.data)) return;
if (!timeMap[timeKey]) {
timeMap[timeKey] = { setChartData(prev => {
...point, const newData = { ...(prev || {}) };
count: 1
}; // Добавление новых точек
grouped.push(timeMap[timeKey]); response.data.forEach(item => {
} else { const instance = item.instance || 'default';
// Усредняем значения для точек в одну секунду if (!newData[instance]) newData[instance] = [];
timeMap[timeKey].value = (timeMap[timeKey].value * timeMap[timeKey].count + point.value) /
(timeMap[timeKey].count + 1); if (!newData[instance].some(p => p.timestamp === item.timestamp)) {
timeMap[timeKey].count += 1; newData[instance].push({
time: formatTime(item.timestamp, selectedRange.value).display,
value: parseFloat(item.value),
timestamp: item.timestamp
});
} }
}); });
instancesData[instance] = grouped.sort((a, b) => a.timestamp - b.timestamp); // Группировка и ограничение
}); Object.keys(newData).forEach(instance => {
newData[instance] = groupBySecond(newData[instance])
.sort((a, b) => a.timestamp - b.timestamp)
.slice(-1000);
});
return Object.keys(newData).length ? newData : prev;
});
}, [metricName, selectedRange.value, formatTime]);
console.log('Processed chart data:', instancesData);
setChartData(instancesData);
setSelectedGraphRange(null);
setFilteredData(null);
}, [metricName, formatTime, useCustomRange, startDate, endDate, selectedRange.value]);
const handleRangeChange = useCallback((event) => { const handleRangeChange = useCallback((event) => {
const selectedValue = event.target.value; const selectedValue = event.target.value;
const range = TIME_RANGES.find(r => r.value === parseInt(selectedValue, 10)); const range = TIME_RANGES.find(r => r.value === parseInt(selectedValue, 10));
@ -234,14 +206,26 @@ const PrometheusChart = ({ metricName }) => {
useEffect(() => { useEffect(() => {
if (!socketRef.current?.connected) return; if (!socketRef.current?.connected) return;
clearInterval(intervalRef.current); const fetchDataWrapper = () => {
fetchData(); try {
fetchData();
} catch (error) {
console.error('Error in interval fetch:', error);
}
};
intervalRef.current = setInterval(() => { // Сразу запросить данные
fetchData(); fetchDataWrapper();
}, selectedRange.interval);
return () => clearInterval(intervalRef.current); // Установить интервал
intervalRef.current = setInterval(fetchDataWrapper, selectedRange.interval);
return () => {
if (intervalRef.current) {
clearInterval(intervalRef.current);
intervalRef.current = null;
}
};
}, [fetchData, selectedRange.interval]); }, [fetchData, selectedRange.interval]);
useEffect(() => { useEffect(() => {