diff --git a/colors.go b/colors.go index fbed7d0..3d83d17 100755 --- a/colors.go +++ b/colors.go @@ -21,6 +21,7 @@ var ( colRed = color("\033[1;31m%s\033[0m") colYellow = color("\033[1;33m%s\033[0m") colBlue = color("\033[1;34m%s\033[0m") + colBlueLight = color("\033[0;34m%s\033[0m") colCyan = color("\033[1;36m%s\033[0m") colGreen = color("\033[0;32m%s\033[0m") ) diff --git a/file.go b/file.go index 3c69d0a..db74de8 100644 --- a/file.go +++ b/file.go @@ -23,10 +23,10 @@ type FileLogger struct { // so that an own log file for each day is used. The format of the date is 'YYYYMMDD' AppendDate bool - // Internal dependency used to synchronize the access the log file - fileSync sync.RWMutex + // Internal dependency used to synchronize the access to the log file + fileSync *sync.RWMutex // Additional file sync that is used during writing to the log file - fileSyncWrite sync.RWMutex + fileSyncWrite *sync.RWMutex logger *log.Logger file *os.File @@ -38,20 +38,24 @@ type FileLogger struct { // CloseFile closes the file that is currently used for logging messages to // a file func (l *FileLogger) CloseFile() { - l.fileSync.Lock() - if l.file != nil { + l.fileSync.Lock() l.file.Close() l.file = nil l.logger = nil + l.fileSync.Unlock() } - - l.fileSync.Unlock() } // openFile tries to open the file that is configured inside the loggers fild -// "LogFilePath" +// "LogFilePath" and initializes the mutex func (l *FileLogger) openFile() { + // Initialize new mutex + if l.fileSync == nil { + l.fileSync = &sync.RWMutex{} + l.fileSyncWrite = &sync.RWMutex{} + } + l.fileSync.Lock() path := l.getFilePath() diff --git a/logger.go b/logger.go index 31058af..05854c6 100755 --- a/logger.go +++ b/logger.go @@ -37,6 +37,11 @@ type Logger struct { // have to set this value to one FuncCallIncrement int + // Prefix is applied as a prefix for all log messages. + // It's positioned after all other information: + // [INFO ] 2024-04-10 19:00:00 (file:1)PREFIX - Message + Prefix string + // Configuration options for logging into a file File *FileLogger @@ -78,11 +83,30 @@ func NewLoggerWithFile(logger *Logger, file *Logger) *Logger { logger.File.file = file.File.file logger.File.Path = file.File.Path logger.File.logger = file.File.logger + logger.File.fileSync = file.File.fileSync + logger.File.fileSyncWrite = file.File.fileSyncWrite logger.setup(true) return logger } +// CloneLogger creates a copy of the provided logger with it's +// file reference. +// All configuration options are cloned from "logger" to the new one +func CloneLogger(logger *Logger) *Logger { + // Copy by dereference the pointer + copyIn := *logger + copy := ©In + fileIn := *copy.File + file := &fileIn + + copy.File = file + copy.consoleLogger = nil + copy.consoleLoggerErr = nil + + return NewLoggerWithFile(copy, logger) +} + // Log logs a message with the given level. As additional parameters you can specify // replace values for the message. See "fmt.printf()" for more infos. func (l *Logger) Log(level Level, message string, parameters ...any) { @@ -104,7 +128,7 @@ func (l *Logger) log(level Level, message string, parameters ...any) { printMessage := fmt.Sprintf(message, parameters...) if !l.OnlyPrintMessage { printMessage = "[" + levelName + "] " + time.Now().Local().Format("2006-01-02 15:04:05") + - getSourceMessage(file, line, pc, l) + " - " + printMessage + getSourceMessage(file, line, pc, l) + l.Prefix + " - " + printMessage } // Build the colored message to print @@ -113,8 +137,9 @@ func (l *Logger) log(level Level, message string, parameters ...any) { printMessageColored = l.getColored("["+levelName+"] ", level.getColor()) + l.getColored(time.Now().Local().Format("2006-01-02 15:04:05"), colCyan) + - l.getColored(getSourceMessage(file, line, pc, l), colPurple) + " - " + - printMessageColored + l.getColored(getSourceMessage(file, line, pc, l), colPurple) + + l.getColored(l.Prefix, colBlueLight) + + " - " + printMessageColored } if l.File.Level <= level && l.File.logger != nil { @@ -141,7 +166,7 @@ func (l *Logger) getColored(message string, color func(str string, parameters .. return message } -func getSourceMessage(file string, line int, pc uintptr, l *Logger) string { +func getSourceMessage(file string, line int, _ uintptr, l *Logger) string { if !l.PrintSource { return "" } @@ -151,7 +176,14 @@ func getSourceMessage(file string, line int, pc uintptr, l *Logger) string { return " (" + fileName + ")" } +// setup setups the provided logger. +// This function has to be called before you can use the logger +// struct! func (l *Logger) setup(keepFile bool) { + + // Setup reference for file logger + l.File.rootLogger = l + // log.Ldate|log.Ltime|log.Lshortfile l.consoleLogger = log.New(os.Stdout, "", 0) l.consoleLoggerErr = log.New(os.Stderr, "", 0) @@ -202,7 +234,7 @@ func Fatal(message string, parameters ...any) { dLogger.Log(LevelFatal, message, parameters...) } -// Available methods for each logger per logging level // +// Available methods for each logger per logging level func (l *Logger) Trace(message string, parameters ...any) { l.Log(LevelTrace, message, parameters...) diff --git a/main/main.go b/main/main.go index e0e67f6..cebff9e 100755 --- a/main/main.go +++ b/main/main.go @@ -18,6 +18,7 @@ func main() { Path: "./logs", AppendDate: true, }, + Prefix: " PREFIX", } logger.SetGlobalLogger(l) @@ -43,5 +44,11 @@ func main() { logger.Info("It's a Me, Mario") lOther.Log(logger.LevelError, "And im your brother luigi") + // Create a copy of the logger + lOtherCloned := logger.CloneLogger(lOther) + lOtherCloned.Level = logger.LevelError + lOtherCloned.File.Level = logger.LevelError + lOtherCloned.Error("%s != %s", lOther.File.Level, lOtherCloned.File.Level) + logger.Fatal("Bowser enters the room...") }