107 lines
1.8 KiB
Go
107 lines
1.8 KiB
Go
package logger
|
|
|
|
import (
|
|
"fmt"
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
type Level int
|
|
|
|
const (
|
|
LevelDebug Level = iota
|
|
LevelInfo
|
|
LevelWarn
|
|
LevelError
|
|
)
|
|
|
|
func (l Level) String() string {
|
|
switch l {
|
|
case LevelDebug:
|
|
return "DEBUG"
|
|
case LevelInfo:
|
|
return "INFO"
|
|
case LevelWarn:
|
|
return "WARN"
|
|
case LevelError:
|
|
return "ERROR"
|
|
default:
|
|
return "UNKNOWN"
|
|
}
|
|
}
|
|
|
|
type Entry struct {
|
|
Time time.Time
|
|
Level Level
|
|
Category string
|
|
Message string
|
|
}
|
|
|
|
type RingBuffer struct {
|
|
mu sync.RWMutex
|
|
entries []Entry
|
|
head int
|
|
count int
|
|
size int
|
|
}
|
|
|
|
func NewRingBuffer(size int) *RingBuffer {
|
|
return &RingBuffer{
|
|
entries: make([]Entry, size),
|
|
size: size,
|
|
}
|
|
}
|
|
|
|
func (b *RingBuffer) Add(e Entry) {
|
|
b.mu.Lock()
|
|
defer b.mu.Unlock()
|
|
|
|
b.entries[b.head] = e
|
|
b.head = (b.head + 1) % b.size
|
|
if b.count < b.size {
|
|
b.count++
|
|
}
|
|
}
|
|
|
|
func (b *RingBuffer) Snapshot() []Entry {
|
|
b.mu.RLock()
|
|
defer b.mu.RUnlock()
|
|
|
|
result := make([]Entry, b.count)
|
|
for i := 0; i < b.count; i++ {
|
|
idx := (b.head - b.count + i + b.size) % b.size
|
|
result[i] = b.entries[idx]
|
|
}
|
|
return result
|
|
}
|
|
|
|
// Global logger instance
|
|
var (
|
|
GlobalBuffer = NewRingBuffer(1000)
|
|
)
|
|
|
|
func logf(level Level, category string, format string, v ...interface{}) {
|
|
msg := fmt.Sprintf(format, v...)
|
|
GlobalBuffer.Add(Entry{
|
|
Time: time.Now(),
|
|
Level: level,
|
|
Category: category,
|
|
Message: msg,
|
|
})
|
|
}
|
|
|
|
func Debug(category string, format string, v ...interface{}) {
|
|
logf(LevelDebug, category, format, v...)
|
|
}
|
|
|
|
func Info(category string, format string, v ...interface{}) {
|
|
logf(LevelInfo, category, format, v...)
|
|
}
|
|
|
|
func Warn(category string, format string, v ...interface{}) {
|
|
logf(LevelWarn, category, format, v...)
|
|
}
|
|
|
|
func Error(category string, format string, v ...interface{}) {
|
|
logf(LevelError, category, format, v...)
|
|
}
|