/** * Failures & Insights Component * Displays recent failures, error messages, and scheduler insights. */ import React, { useState, useEffect } from 'react'; import { Box, List, ListItem, ListItemIcon, ListItemText, AccordionSummary, AccordionDetails, Divider, CircularProgress } from '@mui/material'; import { Error as ErrorIcon, Warning as WarningIcon, Info as InfoIcon, ExpandMore as ExpandMoreIcon, CheckCircle as CheckCircleIcon } from '@mui/icons-material'; import { getExecutionLogs, getRecentSchedulerLogs, ExecutionLog } from '../../api/schedulerDashboard'; import { SchedulerStats } from '../../api/schedulerDashboard'; import { TerminalPaper, TerminalTypography, TerminalAlert, TerminalAccordion, terminalColors } from './terminalTheme'; interface FailuresInsightsProps { stats: SchedulerStats; } const FailuresInsights: React.FC = ({ stats }) => { const [recentFailures, setRecentFailures] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); useEffect(() => { const fetchFailures = async () => { try { setLoading(true); // First try to get execution logs with failed status const executionLogsResponse = await getExecutionLogs(10, 0, 'failed'); // Also get scheduler logs (which include job_failed events) const schedulerLogsResponse = await getRecentSchedulerLogs(); // Combine both, filtering for failed status const allFailures: ExecutionLog[] = [ ...executionLogsResponse.logs.filter(log => log.status === 'failed'), ...(schedulerLogsResponse.logs || []).filter(log => log.status === 'failed') ]; // Sort by execution_date descending (most recent first) and limit to 10 allFailures.sort((a, b) => { const dateA = new Date(a.execution_date).getTime(); const dateB = new Date(b.execution_date).getTime(); return dateB - dateA; }); setRecentFailures(allFailures.slice(0, 10)); } catch (err: any) { setError(err.message || 'Failed to fetch failures'); console.error('Error fetching failures:', err); } finally { setLoading(false); } }; fetchFailures(); }, []); const formatDate = (dateString: string) => { try { const date = new Date(dateString); return date.toLocaleString(); } catch { return dateString; } }; // Generate insights based on stats const generateInsights = () => { const insights: Array<{ type: 'info' | 'warning' | 'error' | 'success'; message: string }> = []; // Scheduler status insight if (!stats.running) { insights.push({ type: 'error', message: 'Scheduler is stopped. Tasks will not be executed until scheduler is restarted.' }); } else { insights.push({ type: 'success', message: 'Scheduler is running and processing tasks normally.' }); } // Active strategies insight if (stats.active_strategies_count === 0) { insights.push({ type: 'info', message: `No active strategies detected. Using ${stats.max_check_interval_minutes}min check interval (idle mode).` }); } else { insights.push({ type: 'info', message: `${stats.active_strategies_count} active strategy(ies) with monitoring tasks. Using ${stats.min_check_interval_minutes}min check interval.` }); } // Failure rate insight const totalExecutions = stats.tasks_executed + stats.tasks_failed; if (totalExecutions > 0) { const failureRate = (stats.tasks_failed / totalExecutions) * 100; if (failureRate > 20) { insights.push({ type: 'error', message: `High failure rate: ${failureRate.toFixed(1)}% of tasks are failing. Review error logs for details.` }); } else if (failureRate > 10) { insights.push({ type: 'warning', message: `Moderate failure rate: ${failureRate.toFixed(1)}% of tasks are failing. Monitor for patterns.` }); } else if (stats.tasks_failed > 0) { insights.push({ type: 'info', message: `Low failure rate: ${failureRate.toFixed(1)}% of tasks are failing. System is healthy.` }); } } // Check interval insight if (stats.intelligent_scheduling) { insights.push({ type: 'success', message: `Intelligent scheduling enabled. Interval automatically adjusts based on active strategies (${stats.min_check_interval_minutes}-${stats.max_check_interval_minutes}min range).` }); } // Last check insight if (stats.last_check) { try { const lastCheck = new Date(stats.last_check); const now = new Date(); const diffMins = Math.floor((now.getTime() - lastCheck.getTime()) / 60000); if (diffMins > stats.check_interval_minutes * 2) { insights.push({ type: 'warning', message: `Last check was ${diffMins} minutes ago. Expected interval is ${stats.check_interval_minutes} minutes. Scheduler may be delayed.` }); } } catch { // Ignore date parsing errors } } return insights; }; const insights = generateInsights(); return ( Failures & Insights {/* Recent Failures */} Recent Failures ({recentFailures.length}) {loading ? ( ) : error ? ( {error} ) : recentFailures.length === 0 ? ( }> No recent failures. All tasks are executing successfully. ) : ( {recentFailures.map((log, index) => ( } sx={{ '&:hover': { backgroundColor: 'rgba(0, 255, 0, 0.05)', } }} > {log.task?.task_title || `Task #${log.task_id}`} {formatDate(log.execution_date)} Component: {log.task?.component_name || 'Unknown'} {log.error_message && ( Error Message {log.error_message} )} {log.execution_time_ms && ( Execution time: {log.execution_time_ms}ms )} {log.user_id && ( User ID: {log.user_id} )} {index < recentFailures.length - 1 && } ))} )} {/* Scheduler Insights */} Scheduler Insights {insights.map((insight, index) => ( {insight.type === 'error' && } {insight.type === 'warning' && } {insight.type === 'info' && } {insight.type === 'success' && } {insight.message} } /> {index < insights.length - 1 && } ))} ); }; export default FailuresInsights;