feat: better debugger (#13)

- create centralized structured logger with rotation
(https://github.com/versenilvis/IRIS/commit/96ad7c95ef0f7a9957b1bbf70bb6c8da3ce28b2e)
- update core lookup and utils to use new logger
(https://github.com/versenilvis/IRIS/commit/8b74b5a9cdc1828cff8c6d0bdaaccbe31da7a00a)
- add log startup metadata and propagate reload flags
(https://github.com/versenilvis/IRIS/commit/31208aa91a58e9e09abbf5497c314f5c961a58e2)
- add log key interceptions and pty events
(https://github.com/versenilvis/IRIS/commit/91ccb92835dd16ee70bf630fe0f267aad93c9db0)
- add test for logger 221a40c893b75e6215787163cd751a4c1cb6c1d8
- secure reload arguments file path to prevent symlink attacks
(https://github.com/versenilvis/IRIS/pull/13/commits/c3eabfda451230e52cb71f0c2a556687f839bd3f)
- close log file on reinitialization to prevent descriptor leak
(https://github.com/versenilvis/IRIS/pull/13/commits/a57d2c9be107a8c6200cf7046cc85b2f58667dce)
This commit is contained in:
VERSE
2026-07-01 20:09:38 +07:00
committed by GitHub
parent aca3d1670c
commit f37f0681ce
7 changed files with 270 additions and 41 deletions
+116
View File
@@ -0,0 +1,116 @@
package logger
import (
"fmt"
"os"
"path/filepath"
"runtime"
"strings"
"sync"
"time"
)
type Level int
const (
LevelDebug Level = iota
LevelInfo
LevelWarn
LevelError
)
var (
mu sync.Mutex
logFile *os.File
currentLvl = LevelInfo
)
// Init initializes the logger writing to logFilePath
func Init(logFilePath string, debug bool) {
mu.Lock()
defer mu.Unlock()
if logFile != nil {
_ = logFile.Close()
logFile = nil
}
// get log level from env
lvlEnv := strings.ToLower(os.Getenv("IRIS_LOG_LEVEL"))
switch lvlEnv {
case "debug":
currentLvl = LevelDebug
case "info":
currentLvl = LevelInfo
case "warn":
currentLvl = LevelWarn
case "error":
currentLvl = LevelError
default:
if debug {
currentLvl = LevelDebug
} else {
currentLvl = LevelInfo
}
}
// rotate if log file is larger than 5MB
if info, err := os.Stat(logFilePath); err == nil && info.Size() > 5*1024*1024 {
_ = os.Rename(logFilePath, logFilePath+".old")
}
_ = os.MkdirAll(filepath.Dir(logFilePath), 0755)
f, err := os.OpenFile(logFilePath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
if err == nil {
logFile = f
}
}
// Close closes the underlying log file
func Close() {
mu.Lock()
defer mu.Unlock()
if logFile != nil {
_ = logFile.Close()
logFile = nil
}
}
func logmsg(lvl Level, lvlStr string, format string, a ...any) {
mu.Lock()
defer mu.Unlock()
if logFile == nil || lvl < currentLvl {
return
}
// get caller information to append file:line
caller := "unknown:0"
if _, file, line, ok := runtime.Caller(2); ok {
caller = fmt.Sprintf("%s:%d", filepath.Base(file), line)
}
tStr := time.Now().Format("2006-01-02T15:04:05.000Z07:00")
msg := fmt.Sprintf(format, a...)
_, _ = fmt.Fprintf(logFile, "%s [%s] [%s] %s\n", tStr, lvlStr, caller, msg)
}
// Debugf writes a debug log message
func Debugf(format string, a ...any) {
logmsg(LevelDebug, "DEBUG", format, a...)
}
// Infof writes an info log message
func Infof(format string, a ...any) {
logmsg(LevelInfo, "INFO", format, a...)
}
// Warnf writes a warning log message
func Warnf(format string, a ...any) {
logmsg(LevelWarn, "WARN", format, a...)
}
// Errorf writes an error log message
func Errorf(format string, a ...any) {
logmsg(LevelError, "ERROR", format, a...)
}