import { Injectable, OnDestroy } from '@angular/core'; import { BehaviorSubject, Observable, Subject, Subscription } from 'rxjs'; import { LogEntry } from '../models/log.model'; import { AuthService } from './auth.service'; @Injectable({ providedIn: 'root' }) export class LogService implements OnDestroy { private logStreamSubject = new Subject(); logStream$ = this.logStreamSubject.asObservable(); private logs: LogEntry[] = []; private logsSubject = new BehaviorSubject([]); logs$ = this.logsSubject.asObservable(); private eventSource: EventSource | null = null; private isConnected = false; private subscriptions: Subscription = new Subscription(); private currentSessionId?: string; constructor(private authService: AuthService) { this.initializeAuthSubscription(); } // 初始化认证状态订阅 private initializeAuthSubscription() { this.subscriptions.add( this.authService.authState$.subscribe(authState => { console.log('LogService: 认证状态变化', authState.isAuthenticated); if (authState.isAuthenticated) { // 用户已登录,连接日志流 this.connectToLogStream(); } else { // 用户登出,断开日志流 this.disconnect(); // 添加日志通知 this.addLog({ id: Date.now().toString(), timestamp: new Date(), level: 'info', message: '用户未登录,日志流未连接', source: 'log-service' }); } }) ); } // 连接到日志流 connectToLogStream(sessionId?: string) { if (this.eventSource) { this.eventSource.close(); } // 检查是否已登录 if (!this.authService.isAuthenticated()) { console.warn('未登录状态,不连接日志流'); return; } // 获取认证token const token = this.authService.getToken(); if (!token) { console.error('无法获取认证token'); return; } // 构建带认证参数的URL let url = `/api/logs/stream?token=${encodeURIComponent(token)}`; if (sessionId) { url += `&sessionId=${sessionId}`; } console.log('连接日志流URL:', url); this.eventSource = new EventSource(url); this.eventSource.onopen = () => { console.log('日志流连接已建立'); this.isConnected = true; this.addLog({ id: Date.now().toString(), timestamp: new Date(), level: 'info', message: '已连接到日志流', source: 'log-service' }); }; this.eventSource.onmessage = (event) => { const logData = event.data; if (logData && logData !== ': heartbeat') { const logEntry: LogEntry = { id: Date.now().toString(), timestamp: new Date(), level: 'info', // 默认级别,实际可能从日志中解析 message: logData, source: 'opencode' }; // 尝试解析日志级别 if (logData.toLowerCase().includes('error')) { logEntry.level = 'error'; } else if (logData.toLowerCase().includes('warn')) { logEntry.level = 'warn'; } else if (logData.toLowerCase().includes('debug')) { logEntry.level = 'debug'; } // 尝试提取会话ID const sessionMatch = logData.match(/session[:\s-]*([a-zA-Z0-9_-]+)/i); if (sessionMatch) { logEntry.sessionID = sessionMatch[1]; } this.addLog(logEntry); } }; this.eventSource.onerror = (error) => { console.error('日志流连接错误:', error); this.isConnected = false; // 检查是否仍然登录 if (this.authService.isAuthenticated()) { this.addLog({ id: Date.now().toString(), timestamp: new Date(), level: 'error', message: '日志流连接断开,正在重连...', source: 'log-service' }); // 5秒后重连(仅在登录状态下) setTimeout(() => { if (this.authService.isAuthenticated()) { this.connectToLogStream(sessionId); } }, 5000); } else { this.addLog({ id: Date.now().toString(), timestamp: new Date(), level: 'warn', message: '日志流连接断开(用户未登录)', source: 'log-service' }); } }; } // 断开日志流连接 disconnect() { if (this.eventSource) { this.eventSource.close(); this.eventSource = null; this.isConnected = false; this.addLog({ id: Date.now().toString(), timestamp: new Date(), level: 'info', message: '已断开日志流连接', source: 'log-service' }); } } // 添加日志 private addLog(log: LogEntry) { this.logs.unshift(log); // 新的在前面 if (this.logs.length > 1000) { // 限制日志数量 this.logs.pop(); } this.logsSubject.next([...this.logs]); this.logStreamSubject.next(log); } // 手动添加日志 log(level: 'info' | 'warn' | 'error' | 'debug', message: string, source?: string, sessionId?: string) { const logEntry: LogEntry = { id: Date.now().toString(), timestamp: new Date(), level, message, source: source || 'app', sessionID: sessionId }; this.addLog(logEntry); } // 获取所有日志 getLogs(): LogEntry[] { return [...this.logs]; } // 根据条件过滤日志 getFilteredLogs(filter: { sessionId?: string; level?: string; limit?: number }): LogEntry[] { let filtered = [...this.logs]; if (filter.sessionId) { filtered = filtered.filter(log => log.sessionID === filter.sessionId); } if (filter.level && filter.level !== 'all') { filtered = filtered.filter(log => log.level === filter.level); } if (filter.limit) { filtered = filtered.slice(0, filter.limit); } return filtered; } // 清空日志 clearLogs() { this.logs = []; this.logsSubject.next([]); } // 检查连接状态 isStreamConnected(): boolean { return this.isConnected; } // 切换会话过滤 switchSession(sessionId?: string) { if (this.authService.isAuthenticated()) { this.connectToLogStream(sessionId); } else { console.warn('未登录状态,无法切换会话过滤'); } } ngOnDestroy() { this.subscriptions.unsubscribe(); this.disconnect(); } }