github.com/wfusion/gofusion@v1.1.14/common/infra/asynq/pkg/log/log.go (about) 1 // Copyright 2020 Kentaro Hibino. All rights reserved. 2 // Use of this source code is governed by a MIT license 3 // that can be found in the LICENSE file. 4 5 // Package log exports logging related types and functions. 6 package log 7 8 import ( 9 "fmt" 10 "io" 11 stdlog "log" 12 "os" 13 "sync" 14 ) 15 16 // Base supports logging at various log levels. 17 type Base interface { 18 // Debug logs a message at Debug level. 19 Debug(args ...any) 20 21 // Info logs a message at Info level. 22 Info(args ...any) 23 24 // Warn logs a message at Warning level. 25 Warn(args ...any) 26 27 // Error logs a message at Error level. 28 Error(args ...any) 29 30 // Fatal logs a message at Fatal level 31 // and process will exit with status set to 1. 32 Fatal(args ...any) 33 } 34 35 // baseLogger is a wrapper object around log.Logger from the standard library. 36 // It supports logging at various log levels. 37 type baseLogger struct { 38 *stdlog.Logger 39 } 40 41 // Debug logs a message at Debug level. 42 func (l *baseLogger) Debug(args ...any) { 43 l.prefixPrint("DEBUG: ", args...) 44 } 45 46 // Info logs a message at Info level. 47 func (l *baseLogger) Info(args ...any) { 48 l.prefixPrint("INFO: ", args...) 49 } 50 51 // Warn logs a message at Warning level. 52 func (l *baseLogger) Warn(args ...any) { 53 l.prefixPrint("WARN: ", args...) 54 } 55 56 // Error logs a message at Error level. 57 func (l *baseLogger) Error(args ...any) { 58 l.prefixPrint("ERROR: ", args...) 59 } 60 61 // Fatal logs a message at Fatal level 62 // and process will exit with status set to 1. 63 func (l *baseLogger) Fatal(args ...any) { 64 l.prefixPrint("FATAL: ", args...) 65 os.Exit(1) 66 } 67 68 func (l *baseLogger) prefixPrint(prefix string, args ...any) { 69 args = append([]any{prefix}, args...) 70 l.Print(args...) 71 } 72 73 // newBase creates and returns a new instance of baseLogger. 74 func newBase(out io.Writer) *baseLogger { 75 prefix := fmt.Sprintf("asynq: pid=%d ", os.Getpid()) 76 return &baseLogger{ 77 stdlog.New(out, prefix, stdlog.Ldate|stdlog.Ltime|stdlog.Lmicroseconds|stdlog.LUTC), 78 } 79 } 80 81 // NewLogger creates and returns a new instance of Logger. 82 // Log level is set to DebugLevel by default. 83 func NewLogger(base Base) *Logger { 84 if base == nil { 85 base = newBase(os.Stderr) 86 } 87 return &Logger{base: base, level: DebugLevel} 88 } 89 90 // Logger logs message to io.Writer at various log levels. 91 type Logger struct { 92 base Base 93 94 mu sync.Mutex 95 // Minimum log level for this logger. 96 // Message with level lower than this level won't be outputted. 97 level Level 98 } 99 100 // Level represents a log level. 101 type Level int32 102 103 const ( 104 // DebugLevel is the lowest level of logging. 105 // Debug logs are intended for debugging and development purposes. 106 DebugLevel Level = iota 107 108 // InfoLevel is used for general informational log messages. 109 InfoLevel 110 111 // WarnLevel is used for undesired but relatively expected events, 112 // which may indicate a problem. 113 WarnLevel 114 115 // ErrorLevel is used for undesired and unexpected events that 116 // the program can recover from. 117 ErrorLevel 118 119 // FatalLevel is used for undesired and unexpected events that 120 // the program cannot recover from. 121 FatalLevel 122 ) 123 124 // String is part of the fmt.Stringer interface. 125 // 126 // Used for testing and debugging purposes. 127 func (l Level) String() string { 128 switch l { 129 case DebugLevel: 130 return "debug" 131 case InfoLevel: 132 return "info" 133 case WarnLevel: 134 return "warning" 135 case ErrorLevel: 136 return "error" 137 case FatalLevel: 138 return "fatal" 139 default: 140 return "unknown" 141 } 142 } 143 144 // canLogAt reports whether logger can log at level v. 145 func (l *Logger) canLogAt(v Level) bool { 146 l.mu.Lock() 147 defer l.mu.Unlock() 148 return v >= l.level 149 } 150 151 func (l *Logger) Debug(args ...any) { 152 if !l.canLogAt(DebugLevel) { 153 return 154 } 155 l.base.Debug(args...) 156 } 157 158 func (l *Logger) Info(args ...any) { 159 if !l.canLogAt(InfoLevel) { 160 return 161 } 162 l.base.Info(args...) 163 } 164 165 func (l *Logger) Warn(args ...any) { 166 if !l.canLogAt(WarnLevel) { 167 return 168 } 169 l.base.Warn(args...) 170 } 171 172 func (l *Logger) Error(args ...any) { 173 if !l.canLogAt(ErrorLevel) { 174 return 175 } 176 l.base.Error(args...) 177 } 178 179 func (l *Logger) Fatal(args ...any) { 180 if !l.canLogAt(FatalLevel) { 181 return 182 } 183 l.base.Fatal(args...) 184 } 185 186 func (l *Logger) Debugf(format string, args ...any) { 187 l.Debug(fmt.Sprintf(format, args...)) 188 } 189 190 func (l *Logger) Infof(format string, args ...any) { 191 l.Info(fmt.Sprintf(format, args...)) 192 } 193 194 func (l *Logger) Warnf(format string, args ...any) { 195 l.Warn(fmt.Sprintf(format, args...)) 196 } 197 198 func (l *Logger) Errorf(format string, args ...any) { 199 l.Error(fmt.Sprintf(format, args...)) 200 } 201 202 func (l *Logger) Fatalf(format string, args ...any) { 203 l.Fatal(fmt.Sprintf(format, args...)) 204 } 205 206 // SetLevel sets the logger level. 207 // It panics if v is less than DebugLevel or greater than FatalLevel. 208 func (l *Logger) SetLevel(v Level) { 209 l.mu.Lock() 210 defer l.mu.Unlock() 211 if v < DebugLevel || v > FatalLevel { 212 panic("log: invalid log level") 213 } 214 l.level = v 215 }