github.com/polarismesh/polaris@v1.17.8/common/log/scope.go (about) 1 /** 2 * Tencent is pleased to support the open source community by making Polaris available. 3 * 4 * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. 5 * 6 * Licensed under the BSD 3-Clause License (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at 9 * 10 * https://opensource.org/licenses/BSD-3-Clause 11 * 12 * Unless required by applicable law or agreed to in writing, software distributed 13 * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 14 * CONDITIONS OF ANY KIND, either express or implied. See the License for the 15 * specific language governing permissions and limitations under the License. 16 */ 17 18 package log 19 20 import ( 21 "fmt" 22 "runtime" 23 "strings" 24 "sync" 25 "time" 26 27 "go.uber.org/zap" 28 "go.uber.org/zap/zapcore" 29 ) 30 31 // Scope let's you log data for an area of code, enabling the user full control over 32 // the level of logging output produced. 33 type Scope struct { 34 // immutable, set at creation 35 name string 36 nameToEmit string 37 description string 38 callerSkip int 39 40 // set by the Configure method and adjustable dynamically 41 outputLevel Level 42 stackTraceLevel Level 43 logCallers bool 44 pt *patchTable 45 } 46 47 var ( 48 scopes = map[string]*Scope{} 49 lock sync.RWMutex 50 ) 51 52 // RegisterScope registers a new logging scope. If the same name is used multiple times 53 // for a single process, the same Scope struct is returned. 54 // 55 // Scope names cannot include colons, commas, or periods. 56 func RegisterScope(name string, description string, callerSkip int) *Scope { 57 if strings.ContainsAny(name, ":,.") { 58 panic(fmt.Sprintf("scope name %s is invalid, it cannot contain colons, commas, or periods", name)) 59 } 60 61 lock.Lock() 62 defer lock.Unlock() 63 64 s, ok := scopes[name] 65 if !ok { 66 s = &Scope{ 67 name: name, 68 description: description, 69 callerSkip: callerSkip, 70 } 71 s.SetOutputLevel(InfoLevel) 72 s.SetStackTraceLevel(NoneLevel) 73 s.SetDisableLogCaller(true) 74 if name != DefaultLoggerName { 75 s.nameToEmit = name 76 } 77 78 scopes[name] = s 79 } 80 81 return s 82 } 83 84 // FindScope returns a previously registered scope, or nil if the named scope wasn't previously registered 85 func FindScope(scope string) *Scope { 86 lock.RLock() 87 defer lock.RUnlock() 88 89 s := scopes[scope] 90 return s 91 } 92 93 func GetScopeOrDefaultByName(name string) *Scope { 94 lock.RLock() 95 defer lock.RUnlock() 96 s := scopes[name] 97 if s == nil { 98 s = scopes[DefaultLoggerName] 99 } 100 return s 101 } 102 103 func GetScopeByName(name, defaultName string) *Scope { 104 lock.RLock() 105 defer lock.RUnlock() 106 s := scopes[name] 107 if s == nil { 108 s = scopes[defaultName] 109 if s == nil { 110 s = scopes[DefaultLoggerName] 111 } 112 } 113 return s 114 } 115 116 // Scopes returns a snapshot of the currently defined set of scopes 117 func Scopes() map[string]*Scope { 118 lock.RLock() 119 defer lock.RUnlock() 120 121 s := make(map[string]*Scope, len(scopes)) 122 for k, v := range scopes { 123 s[k] = v 124 } 125 126 return s 127 } 128 129 // Fatal outputs a message at fatal level. 130 func (s *Scope) Fatal(msg string, fields ...zapcore.Field) { 131 if s.GetOutputLevel() >= FatalLevel { 132 s.emit(zapcore.FatalLevel, s.GetStackTraceLevel() >= FatalLevel, msg, fields) 133 } 134 } 135 136 // Fatala uses fmt.Sprint to construct and log a message at fatal level. 137 func (s *Scope) Fatala(args ...interface{}) { 138 if s.GetOutputLevel() >= FatalLevel { 139 s.emit(zapcore.FatalLevel, s.GetStackTraceLevel() >= FatalLevel, fmt.Sprint(args...), nil) 140 } 141 } 142 143 // Fatalf uses fmt.Sprintf to construct and log a message at fatal level. 144 func (s *Scope) Fatalf(template string, args ...interface{}) { 145 if s.GetOutputLevel() >= FatalLevel { 146 msg := template 147 if len(args) > 0 { 148 msg = fmt.Sprintf(template, args...) 149 } 150 s.emit(zapcore.FatalLevel, s.GetStackTraceLevel() >= FatalLevel, msg, nil) 151 } 152 } 153 154 // FatalEnabled returns whether output of messages using this scope is currently enabled for fatal-level output. 155 func (s *Scope) FatalEnabled() bool { 156 return s.GetOutputLevel() >= FatalLevel 157 } 158 159 // Error outputs a message at error level. 160 func (s *Scope) Error(msg string, fields ...zapcore.Field) { 161 if s.GetOutputLevel() >= ErrorLevel { 162 s.emit(zapcore.ErrorLevel, s.GetStackTraceLevel() >= ErrorLevel, msg, fields) 163 } 164 } 165 166 // Errora uses fmt.Sprint to construct and log a message at error level. 167 func (s *Scope) Errora(args ...interface{}) { 168 if s.GetOutputLevel() >= ErrorLevel { 169 s.emit(zapcore.ErrorLevel, s.GetStackTraceLevel() >= ErrorLevel, fmt.Sprint(args...), nil) 170 } 171 } 172 173 // Errorf uses fmt.Sprintf to construct and log a message at error level. 174 func (s *Scope) Errorf(template string, args ...interface{}) { 175 if s.GetOutputLevel() >= ErrorLevel { 176 msg := template 177 if len(args) > 0 { 178 msg = fmt.Sprintf(template, args...) 179 } 180 s.emit(zapcore.ErrorLevel, s.GetStackTraceLevel() >= ErrorLevel, msg, nil) 181 } 182 } 183 184 // ErrorEnabled returns whether output of messages using this scope is currently enabled for error-level output. 185 func (s *Scope) ErrorEnabled() bool { 186 return s.GetOutputLevel() >= ErrorLevel 187 } 188 189 // Warn outputs a message at warn level. 190 func (s *Scope) Warn(msg string, fields ...zapcore.Field) { 191 if s.GetOutputLevel() >= WarnLevel { 192 s.emit(zapcore.WarnLevel, s.GetStackTraceLevel() >= ErrorLevel, msg, fields) 193 } 194 } 195 196 // Warna uses fmt.Sprint to construct and log a message at warn level. 197 func (s *Scope) Warna(args ...interface{}) { 198 if s.GetOutputLevel() >= WarnLevel { 199 s.emit(zapcore.WarnLevel, s.GetStackTraceLevel() >= ErrorLevel, fmt.Sprint(args...), nil) 200 } 201 } 202 203 // Warnf uses fmt.Sprintf to construct and log a message at warn level. 204 func (s *Scope) Warnf(template string, args ...interface{}) { 205 if s.GetOutputLevel() >= WarnLevel { 206 msg := template 207 if len(args) > 0 { 208 msg = fmt.Sprintf(template, args...) 209 } 210 s.emit(zapcore.WarnLevel, s.GetStackTraceLevel() >= ErrorLevel, msg, nil) 211 } 212 } 213 214 // WarnEnabled returns whether output of messages using this scope is currently enabled for warn-level output. 215 func (s *Scope) WarnEnabled() bool { 216 return s.GetOutputLevel() >= WarnLevel 217 } 218 219 // Info outputs a message at info level. 220 func (s *Scope) Info(msg string, fields ...zapcore.Field) { 221 if s.GetOutputLevel() >= InfoLevel { 222 s.emit(zapcore.InfoLevel, s.GetStackTraceLevel() >= ErrorLevel, msg, fields) 223 } 224 } 225 226 // Infoa uses fmt.Sprint to construct and log a message at info level. 227 func (s *Scope) Infoa(args ...interface{}) { 228 if s.GetOutputLevel() >= InfoLevel { 229 s.emit(zapcore.InfoLevel, s.GetStackTraceLevel() >= ErrorLevel, fmt.Sprint(args...), nil) 230 } 231 } 232 233 // Infof uses fmt.Sprintf to construct and log a message at info level. 234 func (s *Scope) Infof(template string, args ...interface{}) { 235 if s.GetOutputLevel() >= InfoLevel { 236 msg := template 237 if len(args) > 0 { 238 msg = fmt.Sprintf(template, args...) 239 } 240 s.emit(zapcore.InfoLevel, s.GetStackTraceLevel() >= ErrorLevel, msg, nil) 241 } 242 } 243 244 // InfoEnabled returns whether output of messages using this scope is currently enabled for info-level output. 245 func (s *Scope) InfoEnabled() bool { 246 return s.GetOutputLevel() >= InfoLevel 247 } 248 249 // Debug outputs a message at debug level. 250 func (s *Scope) Debug(msg string, fields ...zapcore.Field) { 251 if s.GetOutputLevel() >= DebugLevel { 252 s.emit(zapcore.DebugLevel, s.GetStackTraceLevel() >= ErrorLevel, msg, fields) 253 } 254 } 255 256 // Debuga uses fmt.Sprint to construct and log a message at debug level. 257 func (s *Scope) Debuga(args ...interface{}) { 258 if s.GetOutputLevel() >= DebugLevel { 259 s.emit(zapcore.DebugLevel, s.GetStackTraceLevel() >= ErrorLevel, fmt.Sprint(args...), nil) 260 } 261 } 262 263 // Debugf uses fmt.Sprintf to construct and log a message at debug level. 264 func (s *Scope) Debugf(template string, args ...interface{}) { 265 if s.GetOutputLevel() >= DebugLevel { 266 msg := template 267 if len(args) > 0 { 268 msg = fmt.Sprintf(template, args...) 269 } 270 s.emit(zapcore.DebugLevel, s.GetStackTraceLevel() >= ErrorLevel, msg, nil) 271 } 272 } 273 274 // DebugEnabled returns whether output of messages using this scope is currently enabled for debug-level output. 275 func (s *Scope) DebugEnabled() bool { 276 return s.GetOutputLevel() >= DebugLevel 277 } 278 279 // Name returns this scope's name. 280 func (s *Scope) Name() string { 281 return s.name 282 } 283 284 // Description returns this scope's description 285 func (s *Scope) Description() string { 286 return s.description 287 } 288 289 func (s *Scope) getPathTable() *patchTable { 290 return s.pt 291 } 292 293 const callerSkipOffset = 2 294 295 func (s *Scope) emit(level zapcore.Level, dumpStack bool, msg string, fields []zapcore.Field) { 296 e := zapcore.Entry{ 297 Message: msg, 298 Level: level, 299 Time: time.Now(), 300 LoggerName: s.nameToEmit, 301 } 302 303 if !s.GetDisableLogCaller() { 304 e.Caller = zapcore.NewEntryCaller(runtime.Caller(s.callerSkip + callerSkipOffset)) 305 } 306 307 if dumpStack { 308 e.Stack = zap.Stack("").String 309 } 310 311 pt := s.getPathTable() 312 if pt != nil && pt.write != nil { 313 if err := pt.write(e, fields); err != nil { 314 _, _ = fmt.Fprintf(pt.errorSink, "%v log write error: %v\n", time.Now(), err) 315 _ = pt.errorSink.Sync() 316 } 317 } 318 } 319 320 // SetOutputLevel adjusts the output level associated with the scope. 321 func (s *Scope) SetOutputLevel(l Level) { 322 s.outputLevel = l 323 } 324 325 // GetOutputLevel returns the output level associated with the scope. 326 func (s *Scope) GetOutputLevel() Level { 327 return s.outputLevel 328 } 329 330 // SetStackTraceLevel adjusts the stack tracing level associated with the scope. 331 func (s *Scope) SetStackTraceLevel(l Level) { 332 s.stackTraceLevel = l 333 } 334 335 // GetStackTraceLevel returns the stack tracing level associated with the scope. 336 func (s *Scope) GetStackTraceLevel() Level { 337 return s.stackTraceLevel 338 } 339 340 // SetDisableLogCaller adjusts the output level associated with the scope. 341 func (s *Scope) SetDisableLogCaller(logCallers bool) { 342 s.logCallers = logCallers 343 } 344 345 // GetDisableLogCaller returns the output level associated with the scope. 346 func (s *Scope) GetDisableLogCaller() bool { 347 return s.logCallers 348 } 349 350 // Sync 调用log的Sync方法 351 func (s *Scope) Sync() error { 352 pt := s.getPathTable() 353 if pt != nil && pt.sync != nil { 354 return pt.sync() 355 } 356 return nil 357 }