/** * 日志查看器 */ import React, { useState } from 'react'; import { Card, Table, Tag, Input, Select, DatePicker, Space, Button, Drawer } from 'antd'; import { SearchOutlined, FilterOutlined, DownloadOutlined, EyeOutlined, } from '@ant-design/icons'; import type { ColumnsType } from 'antd/es/table'; const { Search } = Input; const { RangePicker } = DatePicker; const { Option } = Select; interface LogEntry { id: string; timestamp: string; level: 'INFO' | 'WARN' | 'ERROR' | 'DEBUG'; service: string; user?: string; action: string; details: string; ip?: string; request_id?: string; } const LogViewer: React.FC = () => { const [selectedLog, setSelectedLog] = useState(null); const [drawerVisible, setDrawerVisible] = useState(false); const [filterLevel, setFilterLevel] = useState('all'); const [filterService, setFilterService] = useState('all'); // 模拟日志数据 const logs: LogEntry[] = [ { id: '1', timestamp: '2024-06-17 17:15:32', level: 'INFO', service: 'API', user: 'user@example.com', action: 'User Login', details: 'User successfully logged in', ip: '192.168.1.100', request_id: 'req_abc123', }, { id: '2', timestamp: '2024-06-17 17:14:28', level: 'WARN', service: 'API', user: 'admin@example.com', action: 'Failed Login Attempt', details: 'Invalid password provided (attempt 2/5)', ip: '192.168.1.101', request_id: 'req_def456', }, { id: '3', timestamp: '2024-06-17 17:12:45', level: 'ERROR', service: 'Database', action: 'Connection Timeout', details: 'PostgreSQL connection pool exhausted, timeout after 5s', request_id: 'req_ghi789', }, { id: '4', timestamp: '2024-06-17 17:10:15', level: 'INFO', service: 'Celery', action: 'Task Completed', details: 'Video processing task completed successfully', request_id: 'task_jkl012', }, { id: '5', timestamp: '2024-06-17 17:08:52', level: 'WARN', service: 'ObjectStorage', action: 'Slow Upload', details: 'File upload took 3.2s (>1s threshold)', ip: '192.168.1.102', request_id: 'req_mno345', }, { id: '6', timestamp: '2024-06-17 17:05:33', level: 'ERROR', service: 'API', user: 'user2@example.com', action: 'Permission Denied', details: 'User attempted to access admin endpoint without permission', ip: '192.168.1.103', request_id: 'req_pqr678', }, { id: '7', timestamp: '2024-06-17 17:03:21', level: 'INFO', service: 'API', user: 'user3@example.com', action: 'Workspace Created', details: 'New workspace "My Project" created', ip: '192.168.1.104', request_id: 'req_stu901', }, { id: '8', timestamp: '2024-06-17 17:01:08', level: 'DEBUG', service: 'Redis', action: 'Cache Miss', details: 'Cache key "workspace:123" not found, fetching from DB', request_id: 'req_vwx234', }, ]; const getLevelColor = (level: string) => { const colors: Record = { INFO: 'blue', WARN: 'orange', ERROR: 'red', DEBUG: 'default', }; return colors[level] || 'default'; }; const handleViewDetails = (log: LogEntry) => { setSelectedLog(log); setDrawerVisible(true); }; const columns: ColumnsType = [ { title: '时间', dataIndex: 'timestamp', key: 'timestamp', width: 180, sorter: (a, b) => a.timestamp.localeCompare(b.timestamp), }, { title: '级别', dataIndex: 'level', key: 'level', width: 100, render: (level: string) => {level}, filters: [ { text: 'INFO', value: 'INFO' }, { text: 'WARN', value: 'WARN' }, { text: 'ERROR', value: 'ERROR' }, { text: 'DEBUG', value: 'DEBUG' }, ], onFilter: (value, record) => record.level === value, }, { title: '服务', dataIndex: 'service', key: 'service', width: 120, filters: [ { text: 'API', value: 'API' }, { text: 'Database', value: 'Database' }, { text: 'Celery', value: 'Celery' }, { text: 'ObjectStorage', value: 'ObjectStorage' }, { text: 'Redis', value: 'Redis' }, ], onFilter: (value, record) => record.service === value, }, { title: '用户', dataIndex: 'user', key: 'user', width: 180, render: (user?: string) => user || '-', }, { title: '操作', dataIndex: 'action', key: 'action', width: 200, }, { title: '详情', dataIndex: 'details', key: 'details', ellipsis: true, }, { title: '操作', key: 'actions', width: 100, render: (_, record) => ( ), }, ]; return (

日志查看器

} style={{ width: 300 }} /> `共 ${total} 条日志`, }} scroll={{ x: 1200 }} /> {/* 日志详情抽屉 */} setDrawerVisible(false)} > {selectedLog && (
时间:
{selectedLog.timestamp}
级别:
{selectedLog.level}
服务:
{selectedLog.service}
{selectedLog.user && (
用户:
{selectedLog.user}
)}
操作:
{selectedLog.action}
详细信息:
{selectedLog.details}
{selectedLog.ip && (
IP 地址:
{selectedLog.ip}
)} {selectedLog.request_id && (
Request ID:
{selectedLog.request_id}
)}
)}
); }; export default LogViewer; export const Component = LogViewer;