初始化2
This commit is contained in:
103
server/utils/log_buffer.go
Normal file
103
server/utils/log_buffer.go
Normal file
@@ -0,0 +1,103 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
// LogEntry 日志条目
|
||||
type LogEntry struct {
|
||||
Time time.Time `json:"time"`
|
||||
Level string `json:"level"`
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
// LogBuffer 环形日志缓冲区
|
||||
type LogBuffer struct {
|
||||
mu sync.RWMutex
|
||||
entries []LogEntry
|
||||
maxSize int
|
||||
writer io.Writer // 原始输出(控制台)
|
||||
}
|
||||
|
||||
var LogBuf = NewLogBuffer(2000)
|
||||
|
||||
func NewLogBuffer(maxSize int) *LogBuffer {
|
||||
return &LogBuffer{
|
||||
entries: make([]LogEntry, 0, maxSize),
|
||||
maxSize: maxSize,
|
||||
writer: os.Stderr,
|
||||
}
|
||||
}
|
||||
|
||||
// Write 实现 io.Writer 接口, 用于 log.SetOutput
|
||||
func (b *LogBuffer) Write(p []byte) (n int, err error) {
|
||||
// 写入原始输出
|
||||
b.writer.Write(p)
|
||||
|
||||
msg := string(p)
|
||||
level := "INFO"
|
||||
switch {
|
||||
case contains(msg, "FAIL") || contains(msg, "Error") || contains(msg, "error"):
|
||||
level = "ERROR"
|
||||
case contains(msg, "WARN") || contains(msg, "warn"):
|
||||
level = "WARN"
|
||||
}
|
||||
|
||||
b.mu.Lock()
|
||||
b.entries = append(b.entries, LogEntry{
|
||||
Time: time.Now(),
|
||||
Level: level,
|
||||
Message: msg,
|
||||
})
|
||||
// 超过上限则截掉前半部分
|
||||
if len(b.entries) > b.maxSize {
|
||||
b.entries = b.entries[len(b.entries)-b.maxSize:]
|
||||
}
|
||||
b.mu.Unlock()
|
||||
|
||||
return len(p), nil
|
||||
}
|
||||
|
||||
// Get 获取最近 n 条日志
|
||||
func (b *LogBuffer) Get(n int) []LogEntry {
|
||||
b.mu.RLock()
|
||||
defer b.mu.RUnlock()
|
||||
|
||||
total := len(b.entries)
|
||||
if n <= 0 || n > total {
|
||||
n = total
|
||||
}
|
||||
result := make([]LogEntry, n)
|
||||
copy(result, b.entries[total-n:])
|
||||
return result
|
||||
}
|
||||
|
||||
// Count 日志总数
|
||||
func (b *LogBuffer) Count() int {
|
||||
b.mu.RLock()
|
||||
defer b.mu.RUnlock()
|
||||
return len(b.entries)
|
||||
}
|
||||
|
||||
func contains(s, sub string) bool {
|
||||
return len(s) >= len(sub) && (s == sub || len(s) > 0 && findSubstring(s, sub))
|
||||
}
|
||||
|
||||
func findSubstring(s, sub string) bool {
|
||||
for i := 0; i <= len(s)-len(sub); i++ {
|
||||
if s[i:i+len(sub)] == sub {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Logf 写入一条格式化日志到缓冲区
|
||||
func Logf(format string, args ...interface{}) {
|
||||
msg := fmt.Sprintf(format, args...)
|
||||
LogBuf.Write([]byte(msg + "\n"))
|
||||
}
|
||||
Reference in New Issue
Block a user