Created a new chart
parent
4dfd972615
commit
2b79159d35
|
|
@ -2,107 +2,84 @@ import { io } from 'socket.io-client';
|
||||||
|
|
||||||
class MetricsService {
|
class MetricsService {
|
||||||
constructor(baseUrl) {
|
constructor(baseUrl) {
|
||||||
console.log('MetricsService constructor');
|
|
||||||
this.baseUrl = baseUrl || window.location.origin;
|
this.baseUrl = baseUrl || window.location.origin;
|
||||||
this.socket = null;
|
this.socket = null;
|
||||||
this.subscriptions = new Map();
|
this.subscriptions = new Map();
|
||||||
|
this.pendingRequests = new Map();
|
||||||
}
|
}
|
||||||
|
|
||||||
// HTTP методы - адаптированы под ваш бэкенд
|
// Инициализация WebSocket соединения
|
||||||
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 методы - остаются без изменений
|
|
||||||
connectWebSocket() {
|
connectWebSocket() {
|
||||||
if (this.socket && this.socket.connected) return;
|
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'],
|
transports: ['websocket'],
|
||||||
withCredentials: true,
|
withCredentials: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
this.socket.on('connect', () => {
|
this.socket.on('connect', () => {
|
||||||
console.log('Socket.IO connected');
|
console.log('WebSocket connected');
|
||||||
// Подписаться заново на все метрики
|
// Восстанавливаем подписки при переподключении
|
||||||
for (const [metric, callbacks] of this.subscriptions.entries()) {
|
this.subscriptions.forEach((_, metric) => {
|
||||||
this.socket.emit('subscribe-metric', { metric });
|
this.socket.emit('subscribe-metric', { metric });
|
||||||
}
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
this.socket.on('disconnect', () => {
|
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) || [];
|
const callbacks = this.subscriptions.get(metric) || [];
|
||||||
callbacks.forEach(cb => cb(data));
|
callbacks.forEach(cb => cb(data));
|
||||||
});
|
});
|
||||||
|
|
||||||
this.socket.on('metrics-error', payload => {
|
this.socket.on('metrics-error', ({ error, requestId }) => {
|
||||||
console.error('Metrics error:', payload);
|
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) {
|
subscribeToMetric(metric, callback, interval = 5000) {
|
||||||
this.connectWebSocket();
|
this.connectWebSocket();
|
||||||
|
|
||||||
|
|
@ -116,7 +93,7 @@ class MetricsService {
|
||||||
return () => this.unsubscribeFromMetric(metric, callback);
|
return () => this.unsubscribeFromMetric(metric, callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Отписка от метрики
|
||||||
unsubscribeFromMetric(metric, callback) {
|
unsubscribeFromMetric(metric, callback) {
|
||||||
const callbacks = this.subscriptions.get(metric) || [];
|
const callbacks = this.subscriptions.get(metric) || [];
|
||||||
const filtered = callbacks.filter(cb => cb !== callback);
|
const filtered = callbacks.filter(cb => cb !== callback);
|
||||||
|
|
@ -131,7 +108,7 @@ class MetricsService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Закрытие соединения
|
||||||
disconnectWebSocket() {
|
disconnectWebSocket() {
|
||||||
if (this.socket) {
|
if (this.socket) {
|
||||||
this.socket.close();
|
this.socket.close();
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ import {
|
||||||
import MenuItem from "./SidebarMenuComponents/MenuItem";
|
import MenuItem from "./SidebarMenuComponents/MenuItem";
|
||||||
import SidebarFooter from "./SidebarMenuComponents/SidebarFooter";
|
import SidebarFooter from "./SidebarMenuComponents/SidebarFooter";
|
||||||
import { statusManager1 } from "../TreeChart/dataUtils";
|
import { statusManager1 } from "../TreeChart/dataUtils";
|
||||||
|
import tabContent from "../TreeChart/tabContent";
|
||||||
|
|
||||||
|
|
||||||
const SidebarResizer = styled('div')(({ theme }) => ({
|
const SidebarResizer = styled('div')(({ theme }) => ({
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,6 @@ import Box from '@mui/material/Box';
|
||||||
const PrometheusChart = lazy(() => import('../../Charts2/PrometheusChart'));
|
const PrometheusChart = lazy(() => import('../../Charts2/PrometheusChart'));
|
||||||
import LazyChartBatchRenderer from "../hooks/LazyChartBatchRender";
|
import LazyChartBatchRenderer from "../hooks/LazyChartBatchRender";
|
||||||
|
|
||||||
// Функция для генерации названия метрики на основе id
|
|
||||||
const getMetricName = (id) => {
|
const getMetricName = (id) => {
|
||||||
return `zvks_apiforsnmp_measure_${id}`;
|
return `zvks_apiforsnmp_measure_${id}`;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue