import React, { useState, useEffect } from 'react'; import axios from 'axios'; import './App.css'; import './CommandCenterPages.css'; function SLA() { const [slaData, setSlaData] = useState([]); const [days, setDays] = useState(30); const [maxDays, setMaxDays] = useState(30); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [currentPage, setCurrentPage] = useState(1); const [pageSize, setPageSize] = useState(10); const [totalItems, setTotalItems] = useState(0); const [effectiveDays, setEffectiveDays] = useState(30); const [limitedByRetention, setLimitedByRetention] = useState(false); useEffect(() => { // Fetch retention setting from server const fetchRetention = async () => { try { const response = await axios.get('/api/settings'); const retentionDays = response.data.retention_days || 30; setMaxDays(parseInt(retentionDays)); // Adjust current days if it exceeds retention if (days > retentionDays) { setDays(parseInt(retentionDays)); } } catch (error) { // Failed to fetch retention setting, use default } }; fetchRetention(); }, []); // eslint-disable-next-line react-hooks/exhaustive-deps const loadSLAData = React.useCallback(async () => { setLoading(true); setError(null); try { const response = await axios.get('/api/sla', { params: { days, page: currentPage, limit: pageSize } }); const data = Array.isArray(response.data.resources) ? response.data.resources : []; setSlaData(data); setTotalItems(response.data.total || data.length); setEffectiveDays(response.data.effective_days || days); setLimitedByRetention(Boolean(response.data.limited_by_retention)); setLoading(false); } catch (error) { setError(error.message); setLoading(false); } }, [days, currentPage, pageSize]); useEffect(() => { loadSLAData(); }, [loadSLAData]); if (loading) return
Loading SLA data...
; if (error) return
Error loading SLA data: {error}
; const overallStats = slaData && Array.isArray(slaData) && slaData.length > 0 ? { totalResources: slaData.length, meetingTarget: slaData.filter(s => s.meets_target).length, avgUptime: (slaData.reduce((sum, s) => sum + parseFloat(s.actual_uptime), 0) / slaData.length).toFixed(2), totalIncidents: slaData.reduce((sum, s) => sum + s.incidents, 0), totalDowntime: (slaData.reduce((sum, s) => sum + s.downtime_minutes, 0) / 60).toFixed(2), // Convert to hours } : null; return (
{limitedByRetention && (
⚠️ SLA data limited to {effectiveDays} days (server retention setting). Requested {days} days.
)}

SLA Dashboard

{[7, 14, 30, 90].map((d) => ( ))}
{limitedByRetention && (
Limited by data retention ({effectiveDays} days). Increase Retention in Settings to view longer periods.
)}
{overallStats && (

Total Resources

{overallStats.totalResources}

Meeting SLA Target

{overallStats.meetingTarget}/{overallStats.totalResources}

Average Uptime

{overallStats.avgUptime}%

Total Incidents

{overallStats.totalIncidents}

Total Downtime

{Math.round(overallStats.totalDowntime)}m

)} {slaData.length === 0 ? (

No SLA data available

Add resources to start tracking SLA metrics

) : (
{slaData.map((item, idx) => ( ))}
Resource Target Actual Status Checks Incidents Downtime
{item.resource_name} {item.sla_target}% {item.actual_uptime}% {item.meets_target ? '✓ PASS' : '✗ FAIL'} {item.successful_checks}/{item.total_checks} 0 ? '#f59e0b' : '#94a3b8' }}> {item.incidents} {item.downtime_minutes > 0 ? `${item.downtime_minutes}m` : '-'}
{totalItems > pageSize && (
Page { const page = Math.max(1, Math.min(Math.ceil(totalItems / pageSize), parseInt(e.target.value) || 1)); setCurrentPage(page); }} className="cc-input-sm" /> of {Math.ceil(totalItems / pageSize)}
)}
)}

SLA Report Summary

This report shows the Service Level Agreement (SLA) performance for all monitored resources over the last {effectiveDays} days. Resources meeting their target uptime are marked as PASS, while those below target are marked as FAIL.

Overall performance: {overallStats?.meetingTarget || 0} out of {overallStats?.totalResources || 0} resources ({overallStats ? Math.round((overallStats.meetingTarget / overallStats.totalResources) * 100) : 0}%) are meeting their SLA targets.

); } export default SLA;