package logger import ( "fmt" "strconv" "strings" "sync" "time" ) // LogEntry 日志条目 type LogEntry struct { Timestamp time.Time `json:"timestamp"` Level string `json:"level"` Message string `json:"message"` Email string `json:"email,omitempty"` Module string `json:"module,omitempty"` } // 日志存储 var ( logs = make([]LogEntry, 0, 1000) logsMu sync.RWMutex listeners = make(map[string]chan LogEntry) listMu sync.RWMutex ) // AddListener 添加日志监听器 func AddListener(id string) chan LogEntry { listMu.Lock() defer listMu.Unlock() ch := make(chan LogEntry, 100) listeners[id] = ch return ch } // RemoveListener 移除日志监听器 func RemoveListener(id string) { listMu.Lock() defer listMu.Unlock() if ch, ok := listeners[id]; ok { close(ch) delete(listeners, id) } } // broadcast 广播日志 func broadcast(entry LogEntry) { listMu.RLock() defer listMu.RUnlock() for _, ch := range listeners { select { case ch <- entry: default: } } } // log 记录日志 func log(level, message, email, module string) { entry := LogEntry{ Timestamp: time.Now(), Level: level, Message: message, Email: email, Module: module, } logsMu.Lock() if len(logs) >= 1000 { logs = logs[100:] } logs = append(logs, entry) logsMu.Unlock() broadcast(entry) // 打印到控制台 (带时间戳和颜色) timestamp := entry.Timestamp.Format("15:04:05") // ANSI 颜色代码 colorReset := "\033[0m" colorGray := "\033[90m" colorGreen := "\033[32m" colorRed := "\033[31m" colorYellow := "\033[33m" colorCyan := "\033[36m" // Team 颜色列表(用于区分不同 Team) teamColors := []string{ "\033[38;5;39m", // 亮蓝 "\033[38;5;208m", // 橙色 "\033[38;5;141m", // 紫色 "\033[38;5;48m", // 青绿 "\033[38;5;197m", // 粉红 "\033[38;5;226m", // 亮黄 "\033[38;5;87m", // 青色 "\033[38;5;156m", // 浅绿 "\033[38;5;219m", // 浅粉 "\033[38;5;117m", // 天蓝 } // 从消息中提取 Team 编号 teamColor := "" if strings.Contains(message, "[Team ") { start := strings.Index(message, "[Team ") if start >= 0 { end := strings.Index(message[start:], "]") if end > 0 { teamStr := message[start+6 : start+end] if teamNum, err := strconv.Atoi(teamStr); err == nil && teamNum > 0 { teamColor = teamColors[(teamNum-1)%len(teamColors)] } } } } prefix := "" color := "" switch level { case "info": prefix = "INFO " color = colorCyan case "success": prefix = "SUCCESS" color = colorGreen case "error": prefix = "ERROR " color = colorRed case "warning": prefix = "WARN " color = colorYellow } // 模块名固定宽度(8字符) moduleStr := module if len(moduleStr) < 8 { moduleStr = moduleStr + strings.Repeat(" ", 8-len(moduleStr)) } else if len(moduleStr) > 8 { moduleStr = moduleStr[:8] } // 如果是 Team 相关日志,消息使用 Team 颜色 msgColor := colorReset if teamColor != "" { msgColor = teamColor } if email != "" { // 截断长邮箱,保持对齐 emailDisplay := email if len(emailDisplay) > 35 { emailDisplay = emailDisplay[:32] + "..." } fmt.Printf("%s%s%s %s[%s]%s [%s] %s%s%s\n", colorGray, timestamp, colorReset, color, prefix, colorReset, moduleStr, msgColor, message, colorReset) } else { fmt.Printf("%s%s%s %s[%s]%s [%s] %s%s%s\n", colorGray, timestamp, colorReset, color, prefix, colorReset, moduleStr, msgColor, message, colorReset) } } // Info 记录信息日志 func Info(message, email, module string) { log("info", message, email, module) } // Success 记录成功日志 func Success(message, email, module string) { log("success", message, email, module) } // Error 记录错误日志 func Error(message, email, module string) { log("error", message, email, module) } // Warning 记录警告日志 func Warning(message, email, module string) { log("warning", message, email, module) } // GetLogs 获取日志 func GetLogs(limit int) []LogEntry { logsMu.RLock() defer logsMu.RUnlock() if limit <= 0 || limit > len(logs) { limit = len(logs) } start := len(logs) - limit if start < 0 { start = 0 } result := make([]LogEntry, limit) copy(result, logs[start:]) return result } // ClearLogs 清空日志 func ClearLogs() { logsMu.Lock() defer logsMu.Unlock() logs = make([]LogEntry, 0, 1000) }