"use client"; import { Activity, AlertTriangle, CheckCircle, Clock, Download, RefreshCw, Shield, TrendingUp, XCircle, Zap, } from "lucide-react"; import { useCallback, useEffect, useState } from "react"; import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; import { useToast } from "@/hooks/use-toast"; interface BatchMetrics { operationStartTime: number; requestCount: number; successCount: number; failureCount: number; retryCount: number; totalCost: number; averageLatency: number; circuitBreakerTrips: number; performanceStats: { p50: number; p95: number; p99: number; }; } interface CircuitBreakerStatus { isOpen: boolean; failures: number; lastFailureTime: number; } interface SchedulerConfig { enabled: boolean; intervals: { batchCreation: number; statusCheck: number; resultProcessing: number; retryFailures: number; }; thresholds: { maxRetries: number; circuitBreakerThreshold: number; batchSize: number; }; } interface SchedulerStatus { isRunning: boolean; createBatchesRunning: boolean; checkStatusRunning: boolean; processResultsRunning: boolean; retryFailedRunning: boolean; isPaused: boolean; consecutiveErrors: number; lastErrorTime: Date | null; circuitBreakers: Record; config: SchedulerConfig; } interface MonitoringData { timestamp: string; metrics: Record | BatchMetrics; schedulerStatus: SchedulerStatus; circuitBreakerStatus: Record; systemHealth: { schedulerRunning: boolean; circuitBreakersOpen: boolean; pausedDueToErrors: boolean; consecutiveErrors: number; }; } function HealthStatusIcon({ status }: { status: string }) { if (status === "healthy") return ; if (status === "warning") return ; if (status === "critical") return ; return null; } function SystemHealthCard({ health, schedulerStatus, }: { health: { status: string; message: string }; schedulerStatus: { csvImport?: boolean; processing?: boolean; batch?: boolean; }; }) { return ( System Health
{health.message}
CSV Import Scheduler: {schedulerStatus?.csvImport ? "Running" : "Stopped"}
Processing Scheduler: {schedulerStatus?.processing ? "Running" : "Stopped"}
Batch Scheduler: {schedulerStatus?.batch ? "Running" : "Stopped"}
); } function CircuitBreakerCard({ circuitBreakerStatus, }: { circuitBreakerStatus: Record | null; }) { return ( Circuit Breakers {circuitBreakerStatus && Object.keys(circuitBreakerStatus).length > 0 ? (
{Object.entries(circuitBreakerStatus).map(([key, status]) => (
{key}: {status as string}
))}
) : (

No circuit breakers configured

)}
); } export default function BatchMonitoringDashboard() { const [monitoringData, setMonitoringData] = useState( null ); const [isLoading, setIsLoading] = useState(true); const [selectedCompany, setSelectedCompany] = useState("all"); const [autoRefresh, setAutoRefresh] = useState(true); const { toast } = useToast(); const fetchMonitoringData = useCallback(async () => { try { const params = new URLSearchParams(); if (selectedCompany !== "all") { params.set("companyId", selectedCompany); } const response = await fetch(`/api/admin/batch-monitoring?${params}`); if (response.ok) { const data = await response.json(); setMonitoringData(data); } else { throw new Error("Failed to fetch monitoring data"); } } catch (error) { console.error("Failed to fetch batch monitoring data:", error); toast({ title: "Error", description: "Failed to load batch monitoring data", variant: "destructive", }); } finally { setIsLoading(false); } }, [selectedCompany, toast]); useEffect(() => { fetchMonitoringData(); }, [fetchMonitoringData]); useEffect(() => { if (!autoRefresh) return; const interval = setInterval(fetchMonitoringData, 30000); // Refresh every 30 seconds return () => clearInterval(interval); }, [autoRefresh, fetchMonitoringData]); const exportLogs = async (format: "json" | "csv") => { try { const response = await fetch("/api/admin/batch-monitoring/export", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ startDate: new Date(Date.now() - 24 * 60 * 60 * 1000).toISOString(), // Last 24 hours endDate: new Date().toISOString(), format, }), }); if (response.ok) { const blob = await response.blob(); const url = window.URL.createObjectURL(blob); const a = document.createElement("a"); a.href = url; a.download = `batch-logs-${Date.now()}.${format}`; document.body.appendChild(a); a.click(); window.URL.revokeObjectURL(url); document.body.removeChild(a); toast({ title: "Success", description: `Batch logs exported as ${format.toUpperCase()}`, }); } } catch (_error) { toast({ title: "Error", description: "Failed to export logs", variant: "destructive", }); } }; const getHealthStatus = () => { if (!monitoringData) return { status: "unknown", color: "gray" }; const { systemHealth } = monitoringData; if (!systemHealth.schedulerRunning) { return { status: "critical", color: "red", message: "Scheduler not running", }; } if (systemHealth.pausedDueToErrors) { return { status: "warning", color: "yellow", message: "Paused due to errors", }; } if (systemHealth.circuitBreakersOpen) { return { status: "warning", color: "yellow", message: "Circuit breakers open", }; } if (systemHealth.consecutiveErrors > 0) { return { status: "warning", color: "yellow", message: `${systemHealth.consecutiveErrors} consecutive errors`, }; } return { status: "healthy", color: "green", message: "All systems operational", }; }; const renderMetricsCards = () => { if (!monitoringData) return null; const metrics = Array.isArray(monitoringData.metrics) ? monitoringData.metrics[0] : typeof monitoringData.metrics === "object" && "operationStartTime" in monitoringData.metrics ? monitoringData.metrics : Object.values(monitoringData.metrics)[0]; if (!metrics) return null; const successRate = metrics.requestCount > 0 ? ((metrics.successCount / metrics.requestCount) * 100).toFixed(1) : "0"; return (
Total Requests
{metrics.requestCount}

{metrics.successCount} successful, {metrics.failureCount} failed

Success Rate
{successRate}%

{metrics.retryCount} retries performed

Average Latency
{metrics.averageLatency.toFixed(0)}ms

P95: {metrics.performanceStats.p95}ms

Total Cost
€{metrics.totalCost.toFixed(4)}

Circuit breaker trips: {metrics.circuitBreakerTrips}

); }; const renderSystemStatus = () => { if (!monitoringData) return null; const health = getHealthStatus(); const { schedulerStatus, circuitBreakerStatus } = monitoringData; return (
); }; if (isLoading) { return (

Loading batch monitoring data...

); } return (

Batch Processing Monitor

Real-time monitoring of OpenAI Batch API operations

{renderSystemStatus()} {renderMetricsCards()} Overview Logs Export Batch Processing Overview
Last updated:{" "} {monitoringData?.timestamp ? new Date(monitoringData.timestamp).toLocaleString() : "Never"}
{monitoringData && (
                  {JSON.stringify(monitoringData, null, 2)}
                
)}
Recent Batch Processing Logs

Real-time batch processing logs will be displayed here. For detailed log analysis, use the export feature.

Export Batch Processing Data

Export batch processing logs and metrics for detailed analysis.

); }