'use client'; import { useEffect, useState, useRef } from 'react'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; import { RefreshCw, Download, Search, Pause, Play } from 'lucide-react'; interface LogViewerProps {} export function LogViewer() { const [logs, setLogs] = useState([]); const [loading, setLoading] = useState(true); const [autoRefresh, setAutoRefresh] = useState(true); const [filter, setFilter] = useState(''); const filteredLogsRef = useRef([]); const fetchLogs = async () => { try { const response = await fetch('/api/logs?lines=200'); const data = await response.json(); setLogs(data.logs || []); } catch (error) { console.error('Failed to fetch logs:', error); } finally { setLoading(false); } }; useEffect(() => { fetchLogs(); let interval: NodeJS.Timeout; if (autoRefresh) { interval = setInterval(fetchLogs, 3000); // Refresh every 3s } return () => clearInterval(interval); }, [autoRefresh]); const toggleAutoRefresh = () => { setAutoRefresh(!autoRefresh); }; const handleDownload = () => { const content = logs.join('\n'); const blob = new Blob([content], { type: 'text/plain' }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = `openclaw-logs-${new Date().toISOString()}.log`; a.click(); URL.revokeObjectURL(url); }; // Filter logs const filteredLogs = filter ? logs.filter((log) => log.toLowerCase().includes(filter.toLowerCase()) ) : logs; filteredLogsRef.current = filteredLogs; // Parse log level for styling const getLogStyle = (log: string) => { if (log.toLowerCase().includes('error') || log.toLowerCase().includes('failed')) return 'text-red-400'; if (log.toLowerCase().includes('warn')) return 'text-yellow-400'; if (log.toLowerCase().includes('info')) return 'text-blue-400'; return 'text-zinc-300'; }; return (
{/* Controls */}
setFilter(e.target.value)} className="pl-10 bg-zinc-900/50 border-zinc-700 focus:border-orange-500" />
{/* Log Display */} Gateway Logs {filteredLogs.length} entries
{loading && logs.length === 0 ? (
) : filteredLogs.length === 0 ? (
{filter ? 'No logs match your filter' : 'No logs available'}
) : (
{filteredLogs.map((log, index) => (
{log}
))}
)}

ℹ️ Logs refresh automatically every 3 seconds when auto-refresh is enabled.

); }