import { useState, useCallback } from 'react'; import { useNavigate } from 'react-router'; import { Badge } from '@cameleer/design-system'; import type { LogEntryResponse } from '../../api/queries/logs'; import { attributeBadgeColor } from '../../utils/attribute-color'; import styles from './LogEntry.module.css'; function levelColor(level: string): string { switch (level?.toUpperCase()) { case 'ERROR': return 'var(--error)'; case 'WARN': return 'var(--warning)'; case 'INFO': return 'var(--success)'; case 'DEBUG': return 'var(--running)'; case 'TRACE': return 'var(--text-muted)'; default: return 'var(--text-secondary)'; } } function formatTime(iso: string): string { const d = new Date(iso); const h = String(d.getHours()).padStart(2, '0'); const m = String(d.getMinutes()).padStart(2, '0'); const s = String(d.getSeconds()).padStart(2, '0'); const ms = String(d.getMilliseconds()).padStart(3, '0'); return `${h}:${m}:${s}.${ms}`; } function abbreviateLogger(name: string | null): string { if (!name) return ''; const parts = name.split('.'); if (parts.length <= 2) return name; return parts.slice(0, -1).map((p) => p[0]).join('.') + '.' + parts[parts.length - 1]; } function truncate(text: string, max: number): string { return text.length > max ? text.slice(0, max) + '\u2026' : text; } interface LogEntryProps { entry: LogEntryResponse; } export function LogEntry({ entry }: LogEntryProps) { const [expanded, setExpanded] = useState(false); const navigate = useNavigate(); const hasStack = !!entry.stackTrace; const hasExchange = !!entry.exchangeId; const handleViewExchange = useCallback((e: React.MouseEvent) => { e.stopPropagation(); if (!entry.exchangeId || !entry.application) return; const routeId = entry.mdc?.['camel.routeId'] || '_'; navigate(`/exchanges/${entry.application}/${routeId}/${entry.exchangeId}`); }, [entry, navigate]); const handleCopyMessage = useCallback(async (e: React.MouseEvent) => { e.stopPropagation(); await navigator.clipboard.writeText(entry.message); }, [entry.message]); return (
{entry.stackTrace}
)}
{entry.mdc && Object.keys(entry.mdc).length > 0 && (