Files
dygou_go/internal/logger/log_store.go
T
2026-06-24 19:11:02 +08:00

93 lines
2.0 KiB
Go

package logger
import (
"strings"
"sync"
"time"
"douyu_go/internal/constants"
"douyu_go/internal/types"
)
// MemoryLogStore 内存日志缓冲,实现 io.Writer 接口。
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),
}
}
// Write 实现 io.Writer,把标准 log 输出转存为内存日志。
func (s *MemoryLogStore) Write(p []byte) (int, error) {
text := strings.TrimRight(string(p), "\r\n")
if text == "" {
return len(p), nil
}
s.mu.Lock()
defer s.mu.Unlock()
for _, line := range strings.Split(text, "\n") {
line = strings.TrimRight(line, "\r")
if strings.TrimSpace(line) == "" {
continue
}
category, level := ParseLogMeta(line)
if level == "" {
level = DetectLogLevel(line)
}
s.nextID++
s.entries = append(s.entries, types.LogEntry{
ID: s.nextID,
Time: time.Now().In(constants.CST).Format("2006-01-02 15:04:05.000"),
Level: level,
Category: category,
Message: line,
})
if len(s.entries) > s.max {
copy(s.entries, s.entries[len(s.entries)-s.max:])
s.entries = s.entries[:s.max]
}
}
return len(p), nil
}
// 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
}