Files
codexautopool/backend/internal/logger/logger.go

212 lines
4.3 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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)
}