/** * OpenAI API Logs Panel Component * * Simple, clean panel to monitor OpenAI API calls: * - Real-time log viewer (last 100 calls from memory) * - Token usage statistics * - Response time tracking * - Operation breakdown */ import React, { useState, useEffect, useCallback } from 'react'; import { Zap, RefreshCw, Clock, Brain, Trash2, Check, XCircle, AlertTriangle, BarChart3, Activity, Hash, Cpu, TrendingUp } from 'lucide-react'; import { getToken } from '../../services/api'; const API_BASE = import.meta.env.VITE_API_URL || ''; // Status badge const StatusBadge = ({ status }) => { const isSuccess = status === 'success'; return ( {isSuccess ? : } {status} ); }; // Response time indicator const ResponseTimeIndicator = ({ ms }) => { if (!ms) return -; let color; if (ms < 1000) color = '#10b981'; else if (ms < 3000) color = '#f59e0b'; else color = '#ef4444'; return ( {ms >= 1000 ? `${(ms / 1000).toFixed(1)}s` : `${ms}ms`} ); }; function OpenAILogsPanel() { const [logs, setLogs] = useState([]); const [stats, setStats] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [autoRefresh, setAutoRefresh] = useState(true); // Fetch logs const fetchLogs = useCallback(async () => { setLoading(true); setError(null); try { const token = getToken(); const response = await fetch(`${API_BASE}/api/admin/openai-logs?limit=50`, { headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' } }); if (response.ok) { const data = await response.json(); if (data.success) { setLogs(data.logs || []); setStats(data.stats || null); } } else { throw new Error('Failed to fetch OpenAI logs'); } } catch (err) { setError(err.message); } finally { setLoading(false); } }, []); // Clear logs const clearLogs = async () => { if (!window.confirm('Clear all OpenAI API logs from memory?')) return; try { const token = getToken(); const response = await fetch(`${API_BASE}/api/admin/openai-logs`, { method: 'DELETE', headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' } }); if (response.ok) { setLogs([]); setStats(null); } } catch (err) { setError(err.message); } }; useEffect(() => { fetchLogs(); }, [fetchLogs]); // Auto-refresh every 5 seconds useEffect(() => { if (!autoRefresh) return; const interval = setInterval(fetchLogs, 5000); return () => clearInterval(interval); }, [autoRefresh, fetchLogs]); // Format timestamp const formatTime = (isoString) => { if (!isoString) return '-'; const date = new Date(isoString); return date.toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit', second: '2-digit' }); }; return (
{/* Header */}

OpenAI API Logs

Real-time monitoring • Last 100 calls (in-memory)

{/* Stats Cards */} {stats && (
Total Calls
{stats.total_calls || 0}
Success Rate
{stats.success_rate || 100}%
Total Tokens
{(stats.total_tokens || 0).toLocaleString()}
Avg Response
{stats.avg_response_time_ms || 0}ms
)} {/* Operations Breakdown */} {stats?.operations && Object.keys(stats.operations).length > 0 && (

Operations Breakdown

{Object.entries(stats.operations).map(([op, count]) => ( {op}: {count} ))}
)} {/* Error display */} {error && (
{error}
)} {/* Logs Table */}
{logs.length === 0 ? ( ) : ( logs.map((log, idx) => ( )) )}
Time Operation Model Tokens Time Status

No API calls logged yet

Logs appear here when the app makes OpenAI API calls

{formatTime(log.timestamp)} {log.operation} {log.model} {log.total_tokens ? ( {log.total_tokens.toLocaleString()} ) : '-'} {log.error_message && (
{log.error_message}
)}
{/* Footer Info */}
📊 Showing {logs.length} of last 100 calls (stored in-memory) {autoRefresh && '🔄 Auto-refreshing every 5s'}
{/* Spinner styles */}
); } export default OpenAILogsPanel;