From 3fd4f1900970d4b109561730887fd0060d79cf60 Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Sun, 1 Sep 2024 23:49:08 +0200 Subject: [PATCH] server: add verbosity level server: remove filename from log (fix #1) --- config/server/config.go | 22 ++++++- logger/logger.go | 114 +++++++++++++++++++++++++++++++++++++ store/database/database.go | 17 +++++- 3 files changed, 150 insertions(+), 3 deletions(-) create mode 100644 logger/logger.go diff --git a/config/server/config.go b/config/server/config.go index fee892f..27cbece 100644 --- a/config/server/config.go +++ b/config/server/config.go @@ -3,11 +3,14 @@ package server import ( "flag" "os" + + "gitnet.fr/deblan/freetube-sync/logger" ) type Config struct { BindAddress string DbPath string + LogLevel int } var config *Config @@ -20,15 +23,30 @@ func GetConfig() *Config { return config } -func (c *Config) Define(bindAddress, dbPath string) { +func (c *Config) Define(bindAddress, dbPath string, logErrorLevel, logWarnLevel, logInfoLevel bool) { c.BindAddress = bindAddress c.DbPath = dbPath + + if logInfoLevel { + c.LogLevel = int(logger.Info) + } else if logErrorLevel { + c.LogLevel = int(logger.Error) + } else if logWarnLevel { + c.LogLevel = int(logger.Warn) + } else if logInfoLevel { + c.LogLevel = int(logger.Info) + } else { + c.LogLevel = int(logger.Silent) + } } func InitConfig() { dbPath := flag.String("d", os.Getenv("HOME")+"/freetube.sqlite", "Path to SQlite database") bindAddress := flag.String("b", ":1323", "Bind address") + logErrorLevel := flag.Bool("v", false, "Log errors") + logWarnLevel := flag.Bool("vv", false, "Log warns") + logInfoLevel := flag.Bool("vvv", false, "Log infos") flag.Parse() - GetConfig().Define(*bindAddress, *dbPath) + GetConfig().Define(*bindAddress, *dbPath, *logErrorLevel, *logWarnLevel, *logInfoLevel) } diff --git a/logger/logger.go b/logger/logger.go new file mode 100644 index 0000000..269c5ec --- /dev/null +++ b/logger/logger.go @@ -0,0 +1,114 @@ +package logger + +import ( + "context" + "errors" + "fmt" + "time" + + lg "gorm.io/gorm/logger" +) + +type LogLevel int + +const ( + Silent LogLevel = iota + 1 + Error + Warn + Info +) + +type logger struct { + lg.Writer + lg.Config + lg.Interface + infoStr, warnStr, errStr string + traceStr, traceErrStr, traceWarnStr string +} + +func New(writer lg.Writer, config lg.Config) lg.Interface { + var ( + infoStr = "%s\n[info] " + warnStr = "%s\n[warn] " + errStr = "%s\n[error] " + traceStr = "[%.3fms] [rows:%v] %s" + traceWarnStr = "%s\n[%.3fms] [rows:%v] %s" + traceErrStr = "%s\n[%.3fms] [rows:%v] %s" + ) + + if config.Colorful { + infoStr = lg.Green + "%s\n" + lg.Reset + lg.Green + "[info] " + lg.Reset + warnStr = lg.BlueBold + "%s\n" + lg.Reset + lg.Magenta + "[warn] " + lg.Reset + errStr = lg.Magenta + "%s\n" + lg.Reset + lg.Red + "[error] " + lg.Reset + traceStr = lg.Yellow + "[%.3fms] " + lg.BlueBold + "[rows:%v]" + lg.Reset + " %s" + traceWarnStr = lg.Green + "%s " + lg.Reset + lg.RedBold + "[%.3fms] " + lg.Yellow + "[rows:%v]" + lg.Magenta + " %s" + lg.Reset + traceErrStr = lg.RedBold + "%s " + lg.Reset + lg.Yellow + "[%.3fms] " + lg.BlueBold + "[rows:%v]" + lg.Reset + " %s" + } + + return &logger{ + Writer: writer, + Config: config, + infoStr: infoStr, + warnStr: warnStr, + errStr: errStr, + traceStr: traceStr, + traceWarnStr: traceWarnStr, + traceErrStr: traceErrStr, + } +} + +func (l *logger) LogMode(level lg.LogLevel) lg.Interface { + newlogger := *l + newlogger.LogLevel = level + return &newlogger +} + +func (l *logger) Info(ctx context.Context, msg string, data ...interface{}) { + if l.LogLevel >= lg.Info { + l.Printf(l.infoStr+msg, data...) + } +} + +func (l *logger) Warn(ctx context.Context, msg string, data ...interface{}) { + if l.LogLevel >= lg.Warn { + l.Printf(l.warnStr+msg, data...) + } +} + +func (l *logger) Error(ctx context.Context, msg string, data ...interface{}) { + if l.LogLevel >= lg.Error { + l.Printf(l.errStr+msg, data...) + } +} + +func (l *logger) Trace(ctx context.Context, begin time.Time, fc func() (string, int64), err error) { + if l.LogLevel <= lg.Silent { + return + } + + elapsed := time.Since(begin) + switch { + case err != nil && l.LogLevel >= lg.Error && (!errors.Is(err, lg.ErrRecordNotFound) || !l.IgnoreRecordNotFoundError): + sql, rows := fc() + if rows == -1 { + l.Printf(l.traceErrStr, err, float64(elapsed.Nanoseconds())/1e6, "-", sql) + } else { + l.Printf(l.traceErrStr, err, float64(elapsed.Nanoseconds())/1e6, rows, sql) + } + case elapsed > l.SlowThreshold && l.SlowThreshold != 0 && l.LogLevel >= lg.Warn: + sql, rows := fc() + slowLog := fmt.Sprintf("SLOW SQL >= %v", l.SlowThreshold) + if rows == -1 { + l.Printf(l.traceWarnStr, slowLog, float64(elapsed.Nanoseconds())/1e6, "-", sql) + } else { + l.Printf(l.traceWarnStr, slowLog, float64(elapsed.Nanoseconds())/1e6, rows, sql) + } + case l.LogLevel == lg.Info: + sql, rows := fc() + if rows == -1 { + l.Printf(l.traceStr, float64(elapsed.Nanoseconds())/1e6, "-", sql) + } else { + l.Printf(l.traceStr, float64(elapsed.Nanoseconds())/1e6, rows, sql) + } + } +} diff --git a/store/database/database.go b/store/database/database.go index 31d953c..8050aed 100644 --- a/store/database/database.go +++ b/store/database/database.go @@ -2,11 +2,15 @@ package database import ( "log" + "os" + "time" config "gitnet.fr/deblan/freetube-sync/config/server" + "gitnet.fr/deblan/freetube-sync/logger" "gitnet.fr/deblan/freetube-sync/model" "gorm.io/driver/sqlite" "gorm.io/gorm" + lg "gorm.io/gorm/logger" ) type Manager struct { @@ -18,7 +22,18 @@ var manager *Manager func GetManager() *Manager { if manager == nil { manager = &Manager{} - db, err := gorm.Open(sqlite.Open(config.GetConfig().DbPath), &gorm.Config{}) + db, err := gorm.Open(sqlite.Open(config.GetConfig().DbPath), &gorm.Config{ + Logger: logger.New( + log.New(os.Stdout, "\r\n", log.LstdFlags), + lg.Config{ + SlowThreshold: time.Second, + LogLevel: lg.LogLevel(config.GetConfig().LogLevel), + IgnoreRecordNotFoundError: true, + ParameterizedQueries: true, + Colorful: true, + }, + ), + }) if err != nil { log.Fatal(err)