import { useQuery } from '@tanstack/react-query'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Badge } from '@/components/ui/badge'; import { Loader2, Clock } from 'lucide-react'; import { format } from 'date-fns'; import { supabase } from '@/lib/supabaseClient'; interface CorrelatedLogsViewProps { requestId: string; traceId?: string; } interface TimelineEvent { timestamp: Date; type: 'error' | 'edge' | 'database' | 'approval'; message: string; severity?: string; metadata?: Record; } export function CorrelatedLogsView({ requestId, traceId }: CorrelatedLogsViewProps) { const { data: events, isLoading } = useQuery({ queryKey: ['correlated-logs', requestId, traceId], queryFn: async () => { const events: TimelineEvent[] = []; // Fetch application error const { data: error } = await supabase .from('request_metadata') .select('*') .eq('request_id', requestId) .single(); if (error) { events.push({ timestamp: new Date(error.created_at), type: 'error', message: error.error_message || 'Unknown error', severity: error.error_type || undefined, metadata: { endpoint: error.endpoint, method: error.method, status_code: error.status_code, }, }); } // Fetch approval metrics const { data: approval } = await supabase .from('approval_transaction_metrics') .select('*') .eq('request_id', requestId) .maybeSingle(); if (approval && approval.created_at) { events.push({ timestamp: new Date(approval.created_at), type: 'approval', message: approval.success ? 'Approval successful' : (approval.error_message || 'Approval failed'), severity: approval.success ? 'success' : 'error', metadata: { items_count: approval.items_count, duration_ms: approval.duration_ms || undefined, }, }); } // TODO: Fetch edge function logs (requires Management API access) // TODO: Fetch database logs (requires analytics API access) // Sort chronologically events.sort((a, b) => a.timestamp.getTime() - b.timestamp.getTime()); return events; }, }); const getTypeColor = (type: string): "default" | "destructive" | "outline" | "secondary" => { switch (type) { case 'error': return 'destructive'; case 'approval': return 'destructive'; case 'edge': return 'default'; case 'database': return 'secondary'; default: return 'outline'; } }; if (isLoading) { return (
); } if (!events || events.length === 0) { return (

No correlated logs found for this request.

); } return ( Timeline for Request {requestId.slice(0, 8)}
{/* Timeline line */}
{events.map((event, index) => (
{/* Timeline dot */}
{event.type.toUpperCase()} {event.severity && ( {event.severity} )} {format(event.timestamp, 'HH:mm:ss.SSS')}

{event.message}

{event.metadata && Object.keys(event.metadata).length > 0 && (
{Object.entries(event.metadata).map(([key, value]) => (
{key}: {String(value)}
))}
)}
))}
); }