Created a new chart
parent
4dfd972615
commit
2b79159d35
|
|
@ -2,125 +2,102 @@ import { io } from 'socket.io-client';
|
|||
|
||||
class MetricsService {
|
||||
constructor(baseUrl) {
|
||||
console.log('MetricsService constructor');
|
||||
this.baseUrl = baseUrl || window.location.origin;
|
||||
this.socket = null;
|
||||
this.subscriptions = new Map();
|
||||
this.pendingRequests = new Map();
|
||||
}
|
||||
|
||||
// HTTP методы - адаптированы под ваш бэкенд
|
||||
async fetchMetricsRange(metric, start, end, step = 15) {
|
||||
try {
|
||||
// Формируем URL согласно вашему API
|
||||
const url = new URL(`${this.baseUrl}/api/metrics`);
|
||||
url.searchParams.append('metric', metric);
|
||||
url.searchParams.append('start', start);
|
||||
url.searchParams.append('end', end);
|
||||
url.searchParams.append('step', step);
|
||||
|
||||
console.log('Fetching metrics range from:', url.toString());
|
||||
|
||||
const response = await fetch(url.toString());
|
||||
|
||||
if (!response.ok) {
|
||||
const errorText = await response.text();
|
||||
throw new Error(`HTTP ${response.status}: ${errorText}`);
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
// Проверяем формат данных
|
||||
if (!Array.isArray(data)) {
|
||||
console.error('Unexpected data format:', data);
|
||||
throw new Error('Invalid data format: expected array');
|
||||
}
|
||||
|
||||
return data;
|
||||
} catch (error) {
|
||||
console.error('Error in fetchMetricsRange:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async fetchMetrics(metric) {
|
||||
try {
|
||||
// Формируем URL для текущих метрик
|
||||
const url = new URL(`${this.baseUrl}/api/metrics`);
|
||||
url.searchParams.append('metric', metric);
|
||||
|
||||
console.log('Fetching current metrics from:', url.toString());
|
||||
|
||||
const response = await fetch(url.toString());
|
||||
|
||||
if (!response.ok) {
|
||||
const errorText = await response.text();
|
||||
throw new Error(`HTTP ${response.status}: ${errorText}`);
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
// Проверяем формат данных
|
||||
if (!Array.isArray(data)) {
|
||||
console.error('Unexpected data format:', data);
|
||||
throw new Error('Invalid data format: expected array');
|
||||
}
|
||||
|
||||
return data;
|
||||
} catch (error) {
|
||||
console.error('Error in fetchMetrics:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
// WebSocket методы - остаются без изменений
|
||||
// Инициализация WebSocket соединения
|
||||
connectWebSocket() {
|
||||
if (this.socket && this.socket.connected) return;
|
||||
console.trace('connectWebSocket called');
|
||||
this.socket = io(`${this.baseUrl}/api/metrics-ws`, {
|
||||
|
||||
this.socket = io(`${this.baseUrl.replace('http', 'ws')}/api/metrics-ws`, {
|
||||
transports: ['websocket'],
|
||||
withCredentials: true,
|
||||
});
|
||||
|
||||
|
||||
this.socket.on('connect', () => {
|
||||
console.log('Socket.IO connected');
|
||||
// Подписаться заново на все метрики
|
||||
for (const [metric, callbacks] of this.subscriptions.entries()) {
|
||||
console.log('WebSocket connected');
|
||||
// Восстанавливаем подписки при переподключении
|
||||
this.subscriptions.forEach((_, metric) => {
|
||||
this.socket.emit('subscribe-metric', { metric });
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
this.socket.on('disconnect', () => {
|
||||
console.log('Socket.IO disconnected');
|
||||
console.log('WebSocket disconnected');
|
||||
});
|
||||
|
||||
this.socket.on('metrics-data', ({ metric, data }) => {
|
||||
|
||||
this.socket.on('metrics-data', ({ metric, data, requestId }) => {
|
||||
// Обработка исторических данных
|
||||
if (requestId && this.pendingRequests.has(requestId)) {
|
||||
const { resolve } = this.pendingRequests.get(requestId);
|
||||
resolve(data);
|
||||
this.pendingRequests.delete(requestId);
|
||||
return;
|
||||
}
|
||||
|
||||
// Обработка реального времени
|
||||
const callbacks = this.subscriptions.get(metric) || [];
|
||||
callbacks.forEach(cb => cb(data));
|
||||
});
|
||||
|
||||
this.socket.on('metrics-error', payload => {
|
||||
console.error('Metrics error:', payload);
|
||||
|
||||
this.socket.on('metrics-error', ({ error, requestId }) => {
|
||||
if (requestId && this.pendingRequests.has(requestId)) {
|
||||
const { reject } = this.pendingRequests.get(requestId);
|
||||
reject(new Error(error));
|
||||
this.pendingRequests.delete(requestId);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Запрос исторических данных через WebSocket
|
||||
async fetchMetricsRange(metric, start, end, step = 15) {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.connectWebSocket();
|
||||
|
||||
const requestId = `range-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
||||
this.pendingRequests.set(requestId, { resolve, reject });
|
||||
|
||||
this.socket.emit('get-metrics', {
|
||||
metric,
|
||||
start,
|
||||
end,
|
||||
step,
|
||||
isRangeQuery: true,
|
||||
requestId
|
||||
});
|
||||
|
||||
// Таймаут запроса
|
||||
setTimeout(() => {
|
||||
if (this.pendingRequests.has(requestId)) {
|
||||
this.pendingRequests.delete(requestId);
|
||||
reject(new Error('Request timeout'));
|
||||
}
|
||||
}, 30000);
|
||||
});
|
||||
}
|
||||
|
||||
// Подписка на обновления в реальном времени
|
||||
subscribeToMetric(metric, callback, interval = 5000) {
|
||||
this.connectWebSocket();
|
||||
|
||||
|
||||
if (!this.subscriptions.has(metric)) {
|
||||
this.subscriptions.set(metric, []);
|
||||
this.socket.emit('subscribe-metric', { metric, interval });
|
||||
}
|
||||
|
||||
|
||||
this.subscriptions.get(metric).push(callback);
|
||||
|
||||
|
||||
return () => this.unsubscribeFromMetric(metric, callback);
|
||||
}
|
||||
|
||||
|
||||
// Отписка от метрики
|
||||
unsubscribeFromMetric(metric, callback) {
|
||||
const callbacks = this.subscriptions.get(metric) || [];
|
||||
const filtered = callbacks.filter(cb => cb !== callback);
|
||||
|
||||
|
||||
if (filtered.length === 0) {
|
||||
this.subscriptions.delete(metric);
|
||||
if (this.socket && this.socket.connected) {
|
||||
|
|
@ -130,8 +107,8 @@ class MetricsService {
|
|||
this.subscriptions.set(metric, filtered);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Закрытие соединения
|
||||
disconnectWebSocket() {
|
||||
if (this.socket) {
|
||||
this.socket.close();
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ import {
|
|||
import MenuItem from "./SidebarMenuComponents/MenuItem";
|
||||
import SidebarFooter from "./SidebarMenuComponents/SidebarFooter";
|
||||
import { statusManager1 } from "../TreeChart/dataUtils";
|
||||
import tabContent from "../TreeChart/tabContent";
|
||||
|
||||
|
||||
const SidebarResizer = styled('div')(({ theme }) => ({
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ import Box from '@mui/material/Box';
|
|||
const PrometheusChart = lazy(() => import('../../Charts2/PrometheusChart'));
|
||||
import LazyChartBatchRenderer from "../hooks/LazyChartBatchRender";
|
||||
|
||||
// Функция для генерации названия метрики на основе id
|
||||
const getMetricName = (id) => {
|
||||
return `zvks_apiforsnmp_measure_${id}`;
|
||||
};
|
||||
|
|
@ -13,11 +12,11 @@ const getMetricName = (id) => {
|
|||
const getAllChildIds = (node) => {
|
||||
let ids = [];
|
||||
if (node.id) {
|
||||
ids.push(node.id);
|
||||
ids.push(node.id);
|
||||
}
|
||||
if (node.items && node.items.length > 0) {
|
||||
node.items.forEach((child) => {
|
||||
ids = ids.concat(getAllChildIds(child));
|
||||
ids = ids.concat(getAllChildIds(child));
|
||||
});
|
||||
}
|
||||
return ids;
|
||||
|
|
@ -26,8 +25,8 @@ const getAllChildIds = (node) => {
|
|||
// Компонент Skeleton для графика
|
||||
const ChartSkeleton = () => (
|
||||
<Box sx={{ width: '100%' }}>
|
||||
<Skeleton variant="text" width="60%" height={30} />
|
||||
<Skeleton variant="rectangular" width="100%" height={300} sx={{ mt: 2 }} />
|
||||
<Skeleton variant="text" width="60%" height={30} />
|
||||
<Skeleton variant="rectangular" width="100%" height={300} sx={{ mt: 2 }} />
|
||||
</Box>
|
||||
);
|
||||
|
||||
|
|
@ -35,7 +34,7 @@ const ChartSkeleton = () => (
|
|||
const ContainerSkeleton = () => (
|
||||
<Box sx={{ width: '100%' }}>
|
||||
<Skeleton variant="text" width="40%" height={40} /> {/* Заголовок */}
|
||||
<Skeleton variant="text" width="80%" height={20} sx={{ mt: 1 }} />
|
||||
<Skeleton variant="text" width="80%" height={20} sx={{ mt: 1 }} />
|
||||
<Box sx={{ mt: 2 }}>
|
||||
{[...Array(3)].map((_, i) => (
|
||||
<ChartSkeleton key={i} />
|
||||
|
|
|
|||
Loading…
Reference in New Issue