import React, { useEffect, useState, useRef } from 'react'; import axios from 'axios'; import DatePicker from 'react-datepicker'; import 'react-datepicker/dist/react-datepicker.css'; import LineChartComponent from './Components/LineChartComponent'; const MAX_POINTS = 20; const COLORS = ['#3e95cd', '#8e5ea2', '#3cba9f', '#e8c3b9', '#c45850']; const TIME_RANGES = [ { label: '1 минута', value: 60, interval: 3000 }, { label: '5 минут', value: 300, interval: 15000 }, { label: '30 минут', value: 1800, interval: 90000 }, { label: '1 час', value: 3600, interval: 180000 }, { label: '3 часа', value: 10800, interval: 540000 }, { label: '6 часов', value: 21600, interval: 1080000 }, { label: '12 часов', value: 43200, interval: 2160000 }, { label: '24 часа', value: 86400, interval: 4320000 }, { label: '2 дня', value: 172800, interval: 8640000 }, { label: '7 дней', value: 604800, interval: 30240000 }, { label: '30 дней', value: 2592000, interval: 129600000 }, { label: '90 дней', value: 7776000, interval: 388800000 }, { label: '6 месяцев', value: 15552000, interval: 777600000 }, { label: '9 месяцев', value: 23328000, interval: 1166400000 }, { label: '1 год', value: 31536000, interval: 1576800000 }, ]; const PrometheusChart = ({ metricName }) => { const [chartData, setChartData] = useState({}); const [selectedRange, setSelectedRange] = useState(TIME_RANGES[0]); const [startDate, setStartDate] = useState(new Date()); const [endDate, setEndDate] = useState(new Date()); const [useCustomRange, setUseCustomRange] = useState(false); const [selectedGraphRange, setSelectedGraphRange] = useState(null); // Выбранный диапазон const [filteredData, setFilteredData] = useState(null); // Отфильтрованные данные const intervalRef = useRef(null); const fetchData = async () => { try { let start, end; if (useCustomRange) { start = Math.floor(startDate.getTime() / 1000); end = Math.floor(endDate.getTime() / 1000); } else { end = Math.floor(Date.now() / 1000); start = end - selectedRange.value; } let step; const range = end - start; if (range <= 3600) step = 5; else if (range <= 21600) step = 30; else if (range <= 86400) step = 120; else step = 300; const response = await axios.get('http://192.168.2.39:3000/metrics', { params: { metric: metricName, start, end, step }, }); const result = response.data; let metrics = Array.isArray(result) ? result : result.data || []; if (!Array.isArray(metrics)) { metrics = []; } const timePoints = []; for (let t = start; t <= end; t += step) { const date = new Date(t * 1000); const formattedTime = range > 86400 ? date.toLocaleString([], { day: '2-digit', month: '2-digit', hour: '2-digit', minute: '2-digit' }) : date.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit', second: '2-digit' }); timePoints.push(formattedTime); } const updatedData = {}; metrics.forEach(m => { const date = new Date(m.timestamp); const formattedTime = range > 86400 ? date.toLocaleString([], { day: '2-digit', month: '2-digit', hour: '2-digit', minute: '2-digit' }) : date.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit', second: '2-digit' }); const key = `${m.instance}-${m.device || m.scrape_job}`; if (!updatedData[key]) updatedData[key] = {}; updatedData[key][formattedTime] = m.value; }); const chartData = {}; Object.keys(updatedData).forEach(key => { chartData[key] = timePoints.map(time => ({ time, value: updatedData[key][time] ?? null, })); }); setChartData(chartData); } catch (error) { console.error('Ошибка при загрузке метрик:', error); } }; useEffect(() => { fetchData(); intervalRef.current = setInterval(() => { fetchData(); }, selectedRange.interval); return () => { if (intervalRef.current) { clearInterval(intervalRef.current); } }; }, [metricName, selectedRange, useCustomRange, startDate, endDate]); const handleRangeChange = (event) => { const selectedValue = event.target.value; const range = TIME_RANGES.find(range => range.value === parseInt(selectedValue, 10)); setSelectedRange(range); setUseCustomRange(false); setSelectedGraphRange(null); // Сбрасываем выбранный диапазон setFilteredData(null); // Сбрасываем отфильтрованные данные }; const handleCustomRangeChange = () => { setUseCustomRange(true); setSelectedGraphRange(null); // Сбрасываем выбранный диапазон setFilteredData(null); // Сбрасываем отфильтрованные данные }; useEffect(() => { if (selectedGraphRange) { const { startIndex, endIndex } = selectedGraphRange; const allTimes = Object.values(chartData) .flat() .map(point => point.time) .filter((time, index, self) => self.indexOf(time) === index); const data = allTimes.map(time => { const point = { time }; Object.keys(chartData).forEach(key => { const instanceData = chartData[key].find(p => p.time === time); point[key] = instanceData ? instanceData.value : null; }); return point; }); const filtered = data.slice(startIndex, endIndex + 1); setFilteredData(filtered); // Сохраняем отфильтрованные данные } else { setFilteredData(null); // Сбрасываем фильтрацию, если диапазон не выбран } }, [selectedGraphRange, chartData]); if (!Object.keys(chartData).length) return

Loading...

; const allTimes = Object.values(chartData) .flat() .map(point => point.time) .filter((time, index, self) => self.indexOf(time) === index); const data = allTimes.map(time => { const point = { time }; Object.keys(chartData).forEach(key => { const instanceData = chartData[key].find(p => p.time === time); point[key] = instanceData ? instanceData.value : null; }); return point; }); return (
setStartDate(date)} showTimeSelect timeFormat="HH:mm" timeIntervals={15} dateFormat="yyyy-MM-dd HH:mm" />
setEndDate(date)} showTimeSelect timeFormat="HH:mm" timeIntervals={15} dateFormat="yyyy-MM-dd HH:mm" />
); }; export default PrometheusChart;