package logger import ( "fmt" "io" "strings" "time" "gitlab.com/uafrica/go-utils/errors" ) type Logger interface { Fatalf(format string, args ...interface{}) Fatal(args ...interface{}) Errorf(format string, args ...interface{}) Error(args ...interface{}) Warnf(format string, args ...interface{}) Warn(args ...interface{}) Infof(format string, args ...interface{}) Info(args ...interface{}) Debugf(format string, args ...interface{}) Debug(args ...interface{}) Tracef(format string, args ...interface{}) Trace(args ...interface{}) WithFields(data map[string]interface{}) logger } type logger struct { level Level writer io.Writer data map[string]interface{} IFormatter } func (l logger) WithFields(data map[string]interface{}) logger { newLogger := logger{ level: l.level, writer: l.writer, data: map[string]interface{}{}, IFormatter: l.IFormatter, } for n, v := range l.data { newLogger.data[n] = v } for n, v := range data { newLogger.data[n] = v } return newLogger } func (l logger) Fatalf(format string, args ...interface{}) { l.WithFields(map[string]interface{}{"call_stack": errors.Stack(3)}).log(LevelFatal, 1, fmt.Sprintf(format, args...)) } func (l logger) Fatal(args ...interface{}) { l.WithFields(map[string]interface{}{"call_stack": errors.Stack(3)}).log(LevelFatal, 1, fmt.Sprint(args...)) } func (l logger) Errorf(format string, args ...interface{}) { l.log(LevelError, 1, fmt.Sprintf(format, args...)) } func (l logger) Error(args ...interface{}) { l.log(LevelError, 1, fmt.Sprint(args...)) } func (l logger) Warnf(format string, args ...interface{}) { l.log(LevelWarn, 1, fmt.Sprintf(format, args...)) } func (l logger) Warn(args ...interface{}) { l.log(LevelWarn, 1, fmt.Sprint(args...)) } func (l logger) Infof(format string, args ...interface{}) { l.log(LevelInfo, 1, fmt.Sprintf(format, args...)) } func (l logger) Info(args ...interface{}) { l.log(LevelInfo, 1, fmt.Sprint(args...)) } func (l logger) Debugf(format string, args ...interface{}) { l.log(LevelDebug, 1, fmt.Sprintf(format, args...)) } func (l logger) Debug(args ...interface{}) { l.log(LevelDebug, 1, fmt.Sprint(args...)) } func (l logger) Tracef(format string, args ...interface{}) { l.log(LevelTrace, 1, fmt.Sprintf(format, args...)) } func (l logger) Trace(args ...interface{}) { l.log(LevelTrace, 1, fmt.Sprint(args...)) } func (l logger) log(level Level, skip int, msg string) { if level <= l.level && l.writer != nil { entry := Entry{ Timestamp: time.Now(), Level: level, Caller: errors.GetCaller(skip + 2).Info(), Data: l.data, Message: strings.ReplaceAll(msg, "\n", ";"), } l.writer.Write(l.Format(entry)) } } type Entry struct { Timestamp time.Time `json:"time"` Level Level `json:"level"` Caller errors.CallerInfo `json:"caller"` Data map[string]interface{} `json:"data"` Message string `json:"message"` }