github.com/jxskiss/gopkg@v0.17.3/zlog/level.go (about) 1 package zlog 2 3 import ( 4 "fmt" 5 "strconv" 6 "strings" 7 8 "go.uber.org/atomic" 9 "go.uber.org/zap" 10 "go.uber.org/zap/zapcore" 11 ) 12 13 // A Level is a logging priority. Higher levels are more important. 14 type Level int8 15 16 const ( 17 // TraceLevel logs are the most fine-grained information which helps 18 // developer "tracing" the code and trying to find one part of a 19 // function specifically. Use this level when you need full visibility 20 // of what is happening in your application and inside the third-party 21 // libraries that you use. 22 // 23 // You can expect this logging level to be very verbose. You can use it 24 // for example to annotate each step in the algorithm or each individual 25 // query with parameters in your code. 26 TraceLevel Level = iota - 2 27 28 // DebugLevel logs are less granular compared to TraceLevel, but it is 29 // more than you will need in everyday use. DebugLevel should be used 30 // for information that may be needed for diagnosing issues and 31 // troubleshooting or when running application in development or test 32 // environment for the purpose of making sure everything is running 33 // correctly. 34 // 35 // DebugLevel logs are helpful for diagnosing and troubleshooting to 36 // people more than just developers (e.g. IT, system admins, etc.). 37 DebugLevel 38 39 // InfoLevel logs are generally useful information which indicate that 40 // something happened, the application entered a certain state, etc. 41 // For example, a controller of your authorization API may write a 42 // message at InfoLevel with information on which user requested 43 // authorization if the authorization was successful or not. 44 // 45 // The information logged at InfoLevel should be purely informative 46 // that you don't need to care about under normal circumstances, and 47 // not looking into them on a regular basis shouldn't result in missing 48 // any important information. 49 // 50 // This should be the out-of-box level for most applications in 51 // service production deployment or application release configuration. 52 InfoLevel 53 54 // NoticeLevel logs are important information which should be always 55 // available and shall not be turned off, user should be aware of these 56 // events when they look into the system or application. 57 // (Such as service start/stop/restart, reconnecting to database, switching 58 // from a primary server to a backup server, retrying an operation, etc.) 59 // 60 // NoticeLevel is not implemented currently. 61 NoticeLevel 62 63 // WarnLevel logs indicate that something unexpected happened in the 64 // system or application, a problem, or a situation that might 65 // potentially cause application oddities, but the code can continue 66 // to work. For example, unexpected disconnection from server, being 67 // close to quota, suspicious web attach, temporarily heartbeat missing, 68 // or a parsing error that resulted in a certain document not being 69 // correctly processed. 70 // 71 // Warning messages may need human review, but generally that don't need 72 // immediately intervention. 73 WarnLevel 74 75 // ErrorLevel logs indicate that the application hit issues preventing 76 // one or more functionalities from properly functioning, they may be 77 // fatal to an operation, but not fatal to the entire service or 78 // application (e.g. can't open a required file, missing data, 79 // temporarily failure from database or downstream service, etc.), 80 // the application should continue running. 81 // 82 // These messages definitely need investigation and intervention from 83 // user (developer, system administrator, or direct user), continuous 84 // errors may cause serious problems, (e.g. service outage, lost of 85 // income, or customer complaints, etc.). 86 ErrorLevel 87 88 // CriticalLevel logs indicate that the system or application encountered 89 // critical condition preventing it to function properly, the system 90 // or application is in a very unhealthy state. 91 // 92 // Intervention actions must be taken immediately, which means you should 93 // go to get a system administrator or developer out of bed quickly. 94 // 95 // CriticalLevel is not implemented currently. 96 CriticalLevel 97 98 // DPanicLevel logs are particularly important errors. 99 // In development mode the logger panics after writing the message. 100 DPanicLevel 101 102 // PanicLevel logs indicate that the application encountered unrecoverable 103 // errors that it should abort immediately. 104 // 105 // The logger writes the message, then panics the application. 106 PanicLevel 107 108 // FatalLevel logs indicate that the application encountered unrecoverable 109 // errors that it should abort immediately. 110 // 111 // The logger writes the message, then calls os.Exit to abort the application. 112 FatalLevel 113 ) 114 115 const ( 116 TracePrefix = "[TRACE] " 117 DebugPrefix = "[DEBUG] " 118 InfoPrefix = "[INFO] " 119 NoticePrefix = "[NOTICE] " 120 WarnPrefix = "[WARN] " 121 ErrorPrefix = "[ERROR] " 122 CriticalPrefix = "[CRITICAL] " 123 PanicPrefix = "[PANIC] " 124 FatalPrefix = "[FATAL] " 125 ) 126 127 const levelPrefixMinLen = 6 128 129 var mapZapLevels = [...]zapcore.Level{ 130 zap.InfoLevel, 131 zap.InfoLevel, 132 zap.WarnLevel, 133 zap.ErrorLevel, 134 zap.ErrorLevel, 135 zap.DPanicLevel, 136 zap.PanicLevel, 137 zap.FatalLevel, 138 } 139 140 func (l Level) toZapLevel() zapcore.Level { 141 if l < 0 { 142 return zapcore.Level(l) 143 } 144 return mapZapLevels[l] 145 } 146 147 func (l Level) String() string { 148 switch l { 149 case TraceLevel: 150 return "trace" 151 case DebugLevel: 152 return "debug" 153 case InfoLevel: 154 return "info" 155 case NoticeLevel: 156 return "notice" 157 case WarnLevel: 158 return "warn" 159 case ErrorLevel: 160 return "error" 161 case CriticalLevel: 162 return "critical" 163 case DPanicLevel: 164 return "dpanic" 165 case PanicLevel: 166 return "panic" 167 case FatalLevel: 168 return "fatal" 169 default: 170 return strconv.FormatInt(int64(l), 10) 171 } 172 } 173 174 func (l Level) CapitalString() string { 175 switch l { 176 case TraceLevel: 177 return "TRACE" 178 case DebugLevel: 179 return "DEBUG" 180 case InfoLevel: 181 return "INFO" 182 case NoticeLevel: 183 return "NOTICE" 184 case WarnLevel: 185 return "WARN" 186 case ErrorLevel: 187 return "ERROR" 188 case CriticalLevel: 189 return "CRITICAL" 190 case DPanicLevel: 191 return "DPANIC" 192 case PanicLevel: 193 return "PANIC" 194 case FatalLevel: 195 return "FATAL" 196 default: 197 return strconv.FormatInt(int64(l), 10) 198 } 199 } 200 201 func (l Level) Enabled(lvl zapcore.Level) bool { 202 return lvl >= l.toZapLevel() 203 } 204 205 func (l *Level) unmarshalText(text []byte) bool { 206 switch string(text) { 207 case "trace", "TRACE": 208 *l = TraceLevel 209 case "debug", "DEBUG": 210 *l = DebugLevel 211 case "info", "INFO": 212 *l = InfoLevel 213 case "notice", "NOTICE": 214 *l = NoticeLevel 215 case "warn", "warning", "WARN", "WARNING": 216 *l = WarnLevel 217 case "error", "ERROR": 218 *l = ErrorLevel 219 case "critical", "CRITICAL": 220 *l = CriticalLevel 221 case "dpanic", "DPANIC": 222 *l = DPanicLevel 223 case "panic", "PANIC": 224 *l = PanicLevel 225 case "fatal", "FATAL": 226 *l = FatalLevel 227 default: 228 return false 229 } 230 return true 231 } 232 233 type atomicLevel struct { 234 lvl *atomic.Int32 235 zl zap.AtomicLevel 236 } 237 238 func newAtomicLevel() atomicLevel { 239 return atomicLevel{ 240 lvl: atomic.NewInt32(int32(InfoLevel)), 241 zl: zap.NewAtomicLevel(), 242 } 243 } 244 245 func (l atomicLevel) Level() Level { return Level(l.lvl.Load()) } 246 247 func (l *atomicLevel) SetLevel(lvl Level) { 248 l.lvl.Store(int32(lvl)) 249 l.zl.SetLevel(lvl.toZapLevel()) 250 } 251 252 func (l *atomicLevel) UnmarshalText(text []byte) error { 253 var _lvl Level 254 if !_lvl.unmarshalText(text) { 255 return fmt.Errorf("unrecognized level: %s", text) 256 } 257 l.SetLevel(_lvl) 258 return nil 259 } 260 261 func fromZapLevel(lvl zapcore.Level) Level { 262 switch lvl { 263 case zapcore.DebugLevel: 264 return DebugLevel 265 case zapcore.InfoLevel: 266 return InfoLevel 267 case zapcore.WarnLevel: 268 return WarnLevel 269 case zapcore.ErrorLevel: 270 return ErrorLevel 271 case zapcore.DPanicLevel: 272 return DPanicLevel 273 case zap.PanicLevel: 274 return PanicLevel 275 case zap.FatalLevel: 276 return FatalLevel 277 } 278 if lvl < zapcore.DebugLevel { 279 return TraceLevel 280 } 281 return FatalLevel 282 } 283 284 func detectLevel(message string) (Level, bool) { 285 switch message[1] { 286 case 'T': 287 if strings.HasPrefix(message, TracePrefix) { 288 return TraceLevel, true 289 } 290 case 'D': 291 if strings.HasPrefix(message, DebugPrefix) { 292 return DebugLevel, true 293 } 294 case 'I': 295 if strings.HasPrefix(message, InfoPrefix) { 296 return InfoLevel, true 297 } 298 case 'N': 299 if strings.HasPrefix(message, NoticePrefix) { 300 return NoticeLevel, true 301 } 302 case 'W': 303 if strings.HasPrefix(message, WarnPrefix) { 304 return WarnLevel, true 305 } 306 case 'E': 307 if strings.HasPrefix(message, ErrorPrefix) { 308 return ErrorLevel, true 309 } 310 case 'C': 311 if strings.HasPrefix(message, CriticalPrefix) { 312 return CriticalLevel, true 313 } 314 case 'P': 315 if strings.HasPrefix(message, PanicPrefix) { 316 return PanicLevel, true 317 } 318 case 'F': 319 if strings.HasPrefix(message, FatalPrefix) { 320 return FatalLevel, true 321 } 322 } 323 return 0, false 324 }