first commit
This commit is contained in:
89
internal/log/logger.go
Normal file
89
internal/log/logger.go
Normal file
@@ -0,0 +1,89 @@
|
||||
// Файл: internal/log/logger.go
|
||||
// Назначение: Асинхронная, wait-free запись логов в файл с меткой времени
|
||||
// в миллисекундах. Поддержка уровней логирования и ротации.
|
||||
|
||||
package log
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
)
|
||||
|
||||
type LogLevel int32
|
||||
|
||||
const (
|
||||
DebugLevel LogLevel = iota
|
||||
InfoLevel
|
||||
WarnLevel
|
||||
ErrorLevel
|
||||
)
|
||||
|
||||
type Logger struct {
|
||||
file *os.File
|
||||
level atomic.Int32
|
||||
writeChan chan string
|
||||
done chan struct{}
|
||||
}
|
||||
|
||||
func NewLogger(filename string, levelStr string) (*Logger, error) {
|
||||
file, err := os.OpenFile(filename, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
level := InfoLevel
|
||||
switch levelStr {
|
||||
case "debug":
|
||||
level = DebugLevel
|
||||
case "warn":
|
||||
level = WarnLevel
|
||||
case "error":
|
||||
level = ErrorLevel
|
||||
}
|
||||
|
||||
l := &Logger{
|
||||
file: file,
|
||||
writeChan: make(chan string, 10000),
|
||||
done: make(chan struct{}),
|
||||
}
|
||||
l.level.Store(int32(level))
|
||||
|
||||
// Запуск wait-free writer
|
||||
go l.writerLoop()
|
||||
|
||||
return l, nil
|
||||
}
|
||||
|
||||
func (l *Logger) writerLoop() {
|
||||
for msg := range l.writeChan {
|
||||
l.file.WriteString(msg + "\n")
|
||||
}
|
||||
close(l.done)
|
||||
}
|
||||
|
||||
func (l *Logger) log(level LogLevel, levelStr, msg string) {
|
||||
if level < LogLevel(l.level.Load()) {
|
||||
return
|
||||
}
|
||||
now := time.Now()
|
||||
timestamp := now.Format("2006-01-02 15:04:05") + fmt.Sprintf(".%03d", now.Nanosecond()/1e6)
|
||||
logMsg := fmt.Sprintf("[%s] %s: %s", timestamp, levelStr, msg)
|
||||
select {
|
||||
case l.writeChan <- logMsg:
|
||||
default:
|
||||
// Неблокирующая запись, старый лог теряется - wait-free
|
||||
}
|
||||
}
|
||||
|
||||
func (l *Logger) Debug(msg string) { l.log(DebugLevel, "DEBUG", msg) }
|
||||
func (l *Logger) Info(msg string) { l.log(InfoLevel, "INFO", msg) }
|
||||
func (l *Logger) Warn(msg string) { l.log(WarnLevel, "WARN", msg) }
|
||||
func (l *Logger) Error(msg string) { l.log(ErrorLevel, "ERROR", msg) }
|
||||
|
||||
func (l *Logger) Close() {
|
||||
close(l.writeChan)
|
||||
<-l.done
|
||||
l.file.Close()
|
||||
}
|
||||
Reference in New Issue
Block a user