first commit

This commit is contained in:
2026-04-08 21:43:35 +03:00
commit be7a1a3ea2
33 changed files with 9609 additions and 0 deletions

89
internal/log/logger.go Normal file
View 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()
}