Files
dygou_go/internal/logger/log_store.go
T
yml2213 b72a58fd57 重构: 日志系统结构化,消除字符串反解析
旧链路:LogEvent→log.Print→logFileWriter→MemoryLogStore.Write
再用 ParseLogLine 字符串切割把分类/级别/账号反解析回来,格式一调就崩。

新链路:LogEvent 直构 LogEntry(Time/Level/Category/Account 直接填值),
经 sink 分发到内存(同步)/文件(异步)/终端。Message 仍用 formatLogLine
渲染保持文件文本格式与前端清理逻辑兼容。

- MemoryLogStore 新增 Append(entry) 替代 Write 的字符串解析路径
- 删除 logFileWriter,新增 sink 统一管理三路输出
- 删除 log.SetOutput/log.Print 依赖
- 保留 ParseLogLine/DetectLogLevel/formatLogLine(AsyncLogWriter 丢弃
  统计与测试仍用),但 log_store 不再调用
- 新增 TestStructuredLogging 覆盖 LogEvent→sink→Append 链路与 minLevel 过滤
2026-07-29 12:52:26 +08:00

71 lines
1.5 KiB
Go

package logger
import (
"sync"
"douyu_go/internal/types"
)
// MemoryLogStore 内存日志缓冲,供前端增量拉取。
type MemoryLogStore struct {
mu sync.RWMutex
nextID int64
max int
filePath string
entries []types.LogEntry
}
// NewMemoryLogStore 创建内存日志缓冲,最多保留 max 条最新日志。
func NewMemoryLogStore(max int) *MemoryLogStore {
if max <= 0 {
max = 500
}
return &MemoryLogStore{
max: max,
entries: make([]types.LogEntry, 0, max),
}
}
// Append 追加一条结构化日志,由内部分配自增 ID。
// 超过容量时丢弃最旧的条目,保留最近的 max 条。
func (s *MemoryLogStore) Append(entry types.LogEntry) types.LogEntry {
s.mu.Lock()
defer s.mu.Unlock()
s.nextID++
entry.ID = s.nextID
s.entries = append(s.entries, entry)
if len(s.entries) > s.max {
copy(s.entries, s.entries[len(s.entries)-s.max:])
s.entries = s.entries[:s.max]
}
return entry
}
// SetFilePath 保存当前日志文件路径。
func (s *MemoryLogStore) SetFilePath(path string) {
s.mu.Lock()
defer s.mu.Unlock()
s.filePath = path
}
// Since 返回 ID 大于 since 的日志。
func (s *MemoryLogStore) Since(since int64) []types.LogEntry {
s.mu.RLock()
defer s.mu.RUnlock()
out := make([]types.LogEntry, 0, len(s.entries))
for _, entry := range s.entries {
if entry.ID > since {
out = append(out, entry)
}
}
return out
}
// FilePath 返回当前日志文件路径。
func (s *MemoryLogStore) FilePath() string {
s.mu.RLock()
defer s.mu.RUnlock()
return s.filePath
}