desk_agent_2.0 / components /LogMonitor.tsx
harvesthealth's picture
Upload folder using huggingface_hub
c2ebec8 verified
import React, { useEffect, useState } from 'react';
import { MonitoringLog } from '../types';
import { Terminal, AlertTriangle, CheckCircle, Clock, FileText } from 'lucide-react';
const LogMonitor: React.FC = () => {
const [logs, setLogs] = useState<MonitoringLog[]>([]);
const [summary, setSummary] = useState<string>("Waiting for logs to generate summary...");
const [isMonitoring, setIsMonitoring] = useState(false);
// Simulate incoming logs
useEffect(() => {
let interval: ReturnType<typeof setInterval>;
if (isMonitoring) {
interval = setInterval(() => {
const sources: ('JulesAPI' | 'HuggingFace' | 'System')[] = ['JulesAPI', 'HuggingFace', 'System'];
const levels: ('INFO' | 'WARN' | 'ERROR')[] = ['INFO', 'INFO', 'INFO', 'WARN', 'INFO']; // Mostly info
const randomSource = sources[Math.floor(Math.random() * sources.length)];
const randomLevel = levels[Math.floor(Math.random() * levels.length)];
const newLog: MonitoringLog = {
id: Math.random().toString(36),
timestamp: new Date().toISOString(),
source: randomSource,
level: randomLevel,
message: generateMockLogMessage(randomSource, randomLevel)
};
setLogs(prev => {
const newLogs = [newLog, ...prev].slice(0, 100);
updateSummary(newLogs); // Trigger summary update
return newLogs;
});
}, 3000);
}
return () => clearInterval(interval);
}, [isMonitoring]);
const generateMockLogMessage = (source: string, level: string) => {
if (source === 'JulesAPI') {
return level === 'ERROR'
? 'Session ID #8492 connection timeout.'
: 'Received activity update: Code generation in progress.';
}
if (source === 'HuggingFace') {
return level === 'WARN'
? 'Build container utilizing 85% memory.'
: 'Successfully pulled layer sha256:e7c96db...';
}
return 'Health check ping passed.';
};
const updateSummary = (currentLogs: MonitoringLog[]) => {
const errors = currentLogs.filter(l => l.level === 'ERROR').length;
const warns = currentLogs.filter(l => l.level === 'WARN').length;
const latest = currentLogs[0];
setSummary(`Status: ${errors > 0 ? 'Issues Detected' : 'Healthy'}.
Found ${errors} errors and ${warns} warnings in the last batch.
Latest activity from ${latest?.source || 'System'}: ${latest?.message || 'None'}.
Sending condensed report to Jules...`);
};
return (
<div className="bg-gray-900 rounded-xl border border-gray-800 h-full flex flex-col">
<div className="p-4 border-b border-gray-800 flex justify-between items-center bg-gray-900/50">
<div className="flex items-center gap-3">
<div className="p-2 bg-gray-800 rounded-lg">
<Terminal className="w-5 h-5 text-emerald-400" />
</div>
<div>
<h2 className="text-lg font-bold text-white">Live Monitor</h2>
<div className="flex items-center gap-2 text-xs text-gray-400">
<span>Monitoring Agent Active</span>
<span className="w-1 h-1 bg-gray-500 rounded-full"></span>
<span>Polling Interval: 10s</span>
</div>
</div>
</div>
<button
onClick={() => setIsMonitoring(!isMonitoring)}
className={`px-4 py-2 rounded-lg text-sm font-medium transition-colors ${
isMonitoring
? 'bg-red-500/10 text-red-400 border border-red-500/20 hover:bg-red-500/20'
: 'bg-emerald-500/10 text-emerald-400 border border-emerald-500/20 hover:bg-emerald-500/20'
}`}
>
{isMonitoring ? 'Stop Monitoring' : 'Start Monitoring'}
</button>
</div>
{/* Summary Panel */}
<div className="bg-blue-900/10 border-b border-blue-900/20 p-4">
<div className="flex items-center gap-2 mb-2">
<FileText className="w-4 h-4 text-blue-400" />
<h3 className="text-sm font-semibold text-blue-300">Agent Summary (For Jules)</h3>
</div>
<p className="text-sm text-gray-300 font-mono leading-relaxed whitespace-pre-line">
{isMonitoring ? summary : "Start monitoring to generate summaries..."}
</p>
</div>
<div className="flex-1 overflow-y-auto p-2 font-mono text-sm bg-black/50 space-y-1">
{logs.length === 0 ? (
<div className="h-full flex flex-col items-center justify-center text-gray-500 gap-2">
<Clock className="w-8 h-8 opacity-50" />
<p>Waiting for logs stream...</p>
</div>
) : (
logs.map((log) => (
<div key={log.id} className="flex gap-3 hover:bg-white/5 p-1.5 rounded transition-colors group">
<span className="text-gray-500 text-xs w-32 shrink-0">{log.timestamp.split('T')[1].slice(0, 12)}</span>
<span className={`text-xs font-bold w-24 shrink-0 uppercase ${
log.source === 'JulesAPI' ? 'text-blue-400' :
log.source === 'HuggingFace' ? 'text-yellow-400' : 'text-purple-400'
}`}>
{log.source}
</span>
<span className={`text-xs font-bold w-12 shrink-0 ${
log.level === 'ERROR' ? 'text-red-500' :
log.level === 'WARN' ? 'text-orange-400' : 'text-gray-400'
}`}>
[{log.level}]
</span>
<span className="text-gray-300 break-all">{log.message}</span>
</div>
))
)}
</div>
<div className="p-3 border-t border-gray-800 bg-gray-900 text-xs text-gray-500 flex justify-between">
<span>Connected to gradio_logsview</span>
<span>Mode: Summarization</span>
</div>
</div>
);
};
export default LogMonitor;