From ecda7e0ef59fbdb471ccd13171fa63738a12cf81 Mon Sep 17 00:00:00 2001 From: Desktop Date: Fri, 14 Nov 2025 23:01:30 +0500 Subject: [PATCH] Update Status.tsx --- frontend/src/pages/Settings/Status.tsx | 233 ++++++++++++++++++++++++- 1 file changed, 231 insertions(+), 2 deletions(-) diff --git a/frontend/src/pages/Settings/Status.tsx b/frontend/src/pages/Settings/Status.tsx index db5e511a..ad658edb 100644 --- a/frontend/src/pages/Settings/Status.tsx +++ b/frontend/src/pages/Settings/Status.tsx @@ -1,7 +1,7 @@ -import { useState, useEffect } from "react"; +import { useState, useEffect, useRef } from "react"; import PageMeta from "../../components/common/PageMeta"; import ComponentCard from "../../components/common/ComponentCard"; -import { fetchAPI } from "../../services/api"; +import { fetchAPI, API_BASE_URL } from "../../services/api"; interface SystemStatus { timestamp: string; @@ -313,6 +313,9 @@ export default function Status() { + {/* API Monitoring Status Card */} + + {/* Last Updated */}
Last updated: {new Date(status.timestamp).toLocaleString()} @@ -321,3 +324,229 @@ export default function Status() { ); } + +// API Monitoring Component +interface APIEndpointStatus { + name: string; + endpoint: string; + status: 'healthy' | 'warning' | 'critical' | 'checking'; + responseTime: number | null; + statusCode: number | null; + lastChecked: Date | null; + error: string | null; +} + +function APIMonitoringCard() { + const initialEndpoints: APIEndpointStatus[] = [ + { name: 'Health Check', endpoint: '/api/ping/', status: 'checking', responseTime: null, statusCode: null, lastChecked: null, error: null }, + { name: 'System Status', endpoint: '/v1/system/status/', status: 'checking', responseTime: null, statusCode: null, lastChecked: null, error: null }, + { name: 'Auth Endpoint', endpoint: '/v1/auth/me/', status: 'checking', responseTime: null, statusCode: null, lastChecked: null, error: null }, + { name: 'Planner API', endpoint: '/v1/planner/keywords/?page=1&page_size=1', status: 'checking', responseTime: null, statusCode: null, lastChecked: null, error: null }, + { name: 'Writer API', endpoint: '/v1/writer/tasks/?page=1&page_size=1', status: 'checking', responseTime: null, statusCode: null, lastChecked: null, error: null }, + ]; + + const [endpoints, setEndpoints] = useState(initialEndpoints); + const endpointsRef = useRef(initialEndpoints); + + // Keep ref in sync with state + useEffect(() => { + endpointsRef.current = endpoints; + }, [endpoints]); + + const checkEndpoint = async (endpoint: APIEndpointStatus) => { + const startTime = performance.now(); + try { + const controller = new AbortController(); + const timeoutId = setTimeout(() => controller.abort(), 10000); // 10 second timeout + + const response = await fetch(`${API_BASE_URL}${endpoint.endpoint}`, { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + }, + credentials: 'include', + signal: controller.signal, + }); + + clearTimeout(timeoutId); + const endTime = performance.now(); + const responseTime = Math.round(endTime - startTime); + + // Determine status based on response time and status code + let status: 'healthy' | 'warning' | 'critical' = 'healthy'; + if (response.status >= 500) { + status = 'critical'; + } else if (response.status >= 400 || responseTime > 2000) { + status = 'warning'; + } else if (responseTime > 1000) { + status = 'warning'; + } + + return { + ...endpoint, + status, + responseTime, + statusCode: response.status, + lastChecked: new Date(), + error: null, + }; + } catch (err: any) { + const endTime = performance.now(); + const responseTime = Math.round(endTime - startTime); + + return { + ...endpoint, + status: 'critical' as const, + responseTime, + statusCode: null, + lastChecked: new Date(), + error: err.name === 'AbortError' ? 'Timeout' : err.message || 'Network Error', + }; + } + }; + + useEffect(() => { + const checkAllEndpoints = async () => { + // Check all endpoints in parallel using ref to get latest state + const results = await Promise.all( + endpointsRef.current.map(endpoint => checkEndpoint(endpoint)) + ); + setEndpoints(results); + }; + + // Initial check + checkAllEndpoints(); + + // Check every 5 seconds for real-time monitoring + const interval = setInterval(checkAllEndpoints, 5000); + + return () => clearInterval(interval); + }, []); + + const getStatusIcon = (status: string) => { + switch (status) { + case 'healthy': + return ( +
+
+ Online +
+ ); + case 'warning': + return ( +
+
+ Slow +
+ ); + case 'critical': + return ( +
+
+ Down +
+ ); + default: + return ( +
+
+ Checking... +
+ ); + } + }; + + const getResponseTimeColor = (responseTime: number | null) => { + if (responseTime === null) return 'text-gray-500 dark:text-gray-400'; + if (responseTime < 500) return 'text-green-600 dark:text-green-400'; + if (responseTime < 1000) return 'text-yellow-600 dark:text-yellow-400'; + if (responseTime < 2000) return 'text-orange-600 dark:text-orange-400'; + return 'text-red-600 dark:text-red-400'; + }; + + const overallStatus = endpoints.every(e => e.status === 'healthy') + ? 'healthy' + : endpoints.some(e => e.status === 'critical') + ? 'critical' + : 'warning'; + + return ( + +
+ {/* Overall Status */} +
+
+

Overall API Status

+

+ {endpoints.filter(e => e.status === 'healthy').length} of {endpoints.length} endpoints healthy +

+
+
+ {overallStatus === 'healthy' ? '✓ All Systems Operational' : + overallStatus === 'warning' ? '⚠ Some Issues Detected' : + '✗ Critical Issues'} +
+
+ + {/* Endpoints List */} +
+ {endpoints.map((endpoint, index) => ( +
+
+
+ + {endpoint.name} + + {getStatusIcon(endpoint.status)} +
+
+ {endpoint.endpoint} + {endpoint.responseTime !== null && ( + + {endpoint.responseTime}ms + + )} + {endpoint.statusCode && ( + = 200 && endpoint.statusCode < 300 + ? 'text-green-600 dark:text-green-400' + : endpoint.statusCode >= 400 && endpoint.statusCode < 500 + ? 'text-yellow-600 dark:text-yellow-400' + : 'text-red-600 dark:text-red-400' + }`}> + {endpoint.statusCode} + + )} +
+ {endpoint.error && ( +
+ {endpoint.error} +
+ )} + {endpoint.lastChecked && ( +
+ Last checked: {endpoint.lastChecked.toLocaleTimeString()} +
+ )} +
+
+ ))} +
+ + {/* Refresh Indicator */} +
+ + + Auto-refreshing every 5 seconds + +
+
+
+ ); +}