blob: 1e23da1383f155364811541a8e69b953eb6e58bd [file] [log] [blame]
Holger Hildebrandtfa074992020-03-27 15:42:06 +00001/*
2 * Copyright 2018-present Open Networking Foundation
3
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7
8 * http://www.apache.org/licenses/LICENSE-2.0
9
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17//Package log provides a structured Logger interface implemented using zap logger. It provides the following capabilities:
18//1. Package level logging - a go package can register itself (AddPackage) and have a logger created for that package.
19//2. Dynamic log level change - for all registered packages (SetAllLogLevel)
20//3. Dynamic log level change - for a given package (SetPackageLogLevel)
21//4. Provides a default logger for unregistered packages
22//5. Allow key-value pairs to be added to a logger(UpdateLogger) or all loggers (UpdateAllLoggers) at run time
23//6. Add to the log output the location where the log was invoked (filename.functionname.linenumber)
24//
25// Using package-level logging (recommended approach). In the examples below, log refers to this log package.
26// 1. In the appropriate package add the following in the init section of the package. The log level can be changed
27// and any number of default fields can be added as well. The log level specifies the lowest log level that will be
28// in the output while the fields will be automatically added to all log printouts.
29//
30// log.AddPackage(mylog.JSON, log.WarnLevel, log.Fields{"anyFieldName": "any value"})
31//
32//2. In the calling package, just invoke any of the publicly available functions of the logger. Here is an example
33// to write an Info log with additional fields:
34//
35//log.Infow("An example", mylog.Fields{"myStringOutput": "output", "myIntOutput": 2})
36//
37//3. To dynamically change the log level, you can use 1)SetLogLevel from inside your package or 2) SetPackageLogLevel
38// from anywhere or 3) SetAllLogLevel from anywhere.
39//
40
41package log
42
43import (
mpagenkoaf801632020-07-03 10:00:42 +000044 "context"
Holger Hildebrandtfa074992020-03-27 15:42:06 +000045 "errors"
46 "fmt"
47 zp "go.uber.org/zap"
48 zc "go.uber.org/zap/zapcore"
49 "path"
50 "runtime"
51 "strings"
52)
53
Matteo Scandolo2e6f1e32020-04-15 11:28:45 -070054type LogLevel int8
55
Holger Hildebrandtfa074992020-03-27 15:42:06 +000056const (
57 // DebugLevel logs a message at debug level
Matteo Scandolo2e6f1e32020-04-15 11:28:45 -070058 DebugLevel = LogLevel(iota)
Holger Hildebrandtfa074992020-03-27 15:42:06 +000059 // InfoLevel logs a message at info level
60 InfoLevel
61 // WarnLevel logs a message at warning level
62 WarnLevel
63 // ErrorLevel logs a message at error level
64 ErrorLevel
65 // FatalLevel logs a message, then calls os.Exit(1).
66 FatalLevel
67)
68
69// CONSOLE formats the log for the console, mostly used during development
70const CONSOLE = "console"
71
72// JSON formats the log using json format, mostly used by an automated logging system consumption
73const JSON = "json"
74
mpagenkoaf801632020-07-03 10:00:42 +000075// Context Aware Logger represents an abstract logging interface. Any logging implementation used
Holger Hildebrandtfa074992020-03-27 15:42:06 +000076// will need to abide by this interface
mpagenkoaf801632020-07-03 10:00:42 +000077type CLogger interface {
78 Debug(context.Context, ...interface{})
79 Debugln(context.Context, ...interface{})
80 Debugf(context.Context, string, ...interface{})
81 Debugw(context.Context, string, Fields)
Holger Hildebrandtfa074992020-03-27 15:42:06 +000082
mpagenkoaf801632020-07-03 10:00:42 +000083 Info(context.Context, ...interface{})
84 Infoln(context.Context, ...interface{})
85 Infof(context.Context, string, ...interface{})
86 Infow(context.Context, string, Fields)
Holger Hildebrandtfa074992020-03-27 15:42:06 +000087
mpagenkoaf801632020-07-03 10:00:42 +000088 Warn(context.Context, ...interface{})
89 Warnln(context.Context, ...interface{})
90 Warnf(context.Context, string, ...interface{})
91 Warnw(context.Context, string, Fields)
Holger Hildebrandtfa074992020-03-27 15:42:06 +000092
mpagenkoaf801632020-07-03 10:00:42 +000093 Error(context.Context, ...interface{})
94 Errorln(context.Context, ...interface{})
95 Errorf(context.Context, string, ...interface{})
96 Errorw(context.Context, string, Fields)
Holger Hildebrandtfa074992020-03-27 15:42:06 +000097
mpagenkoaf801632020-07-03 10:00:42 +000098 Fatal(context.Context, ...interface{})
99 Fatalln(context.Context, ...interface{})
100 Fatalf(context.Context, string, ...interface{})
101 Fatalw(context.Context, string, Fields)
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000102
mpagenkoaf801632020-07-03 10:00:42 +0000103 With(Fields) CLogger
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000104
105 // The following are added to be able to use this logger as a gRPC LoggerV2 if needed
106 //
mpagenkoaf801632020-07-03 10:00:42 +0000107 Warning(context.Context, ...interface{})
108 Warningln(context.Context, ...interface{})
109 Warningf(context.Context, string, ...interface{})
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000110
111 // V reports whether verbosity level l is at least the requested verbose level.
Matteo Scandolo2e6f1e32020-04-15 11:28:45 -0700112 V(l LogLevel) bool
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000113
114 //Returns the log level of this specific logger
Matteo Scandolo2e6f1e32020-04-15 11:28:45 -0700115 GetLogLevel() LogLevel
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000116}
117
118// Fields is used as key-value pairs for structured logging
119type Fields map[string]interface{}
120
mpagenkoaf801632020-07-03 10:00:42 +0000121var defaultLogger *clogger
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000122var cfg zp.Config
123
mpagenkoaf801632020-07-03 10:00:42 +0000124var loggers map[string]*clogger
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000125var cfgs map[string]zp.Config
126
mpagenkoaf801632020-07-03 10:00:42 +0000127type clogger struct {
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000128 log *zp.SugaredLogger
129 parent *zp.Logger
130 packageName string
131}
132
Matteo Scandolo2e6f1e32020-04-15 11:28:45 -0700133func logLevelToAtomicLevel(l LogLevel) zp.AtomicLevel {
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000134 switch l {
135 case DebugLevel:
136 return zp.NewAtomicLevelAt(zc.DebugLevel)
137 case InfoLevel:
138 return zp.NewAtomicLevelAt(zc.InfoLevel)
139 case WarnLevel:
140 return zp.NewAtomicLevelAt(zc.WarnLevel)
141 case ErrorLevel:
142 return zp.NewAtomicLevelAt(zc.ErrorLevel)
143 case FatalLevel:
144 return zp.NewAtomicLevelAt(zc.FatalLevel)
145 }
146 return zp.NewAtomicLevelAt(zc.ErrorLevel)
147}
148
Matteo Scandolo2e6f1e32020-04-15 11:28:45 -0700149func logLevelToLevel(l LogLevel) zc.Level {
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000150 switch l {
151 case DebugLevel:
152 return zc.DebugLevel
153 case InfoLevel:
154 return zc.InfoLevel
155 case WarnLevel:
156 return zc.WarnLevel
157 case ErrorLevel:
158 return zc.ErrorLevel
159 case FatalLevel:
160 return zc.FatalLevel
161 }
162 return zc.ErrorLevel
163}
164
Matteo Scandolo2e6f1e32020-04-15 11:28:45 -0700165func levelToLogLevel(l zc.Level) LogLevel {
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000166 switch l {
167 case zc.DebugLevel:
168 return DebugLevel
169 case zc.InfoLevel:
170 return InfoLevel
171 case zc.WarnLevel:
172 return WarnLevel
173 case zc.ErrorLevel:
174 return ErrorLevel
175 case zc.FatalLevel:
176 return FatalLevel
177 }
178 return ErrorLevel
179}
180
Matteo Scandolo2e6f1e32020-04-15 11:28:45 -0700181func StringToLogLevel(l string) (LogLevel, error) {
182 switch strings.ToUpper(l) {
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000183 case "DEBUG":
Matteo Scandolo2e6f1e32020-04-15 11:28:45 -0700184 return DebugLevel, nil
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000185 case "INFO":
Matteo Scandolo2e6f1e32020-04-15 11:28:45 -0700186 return InfoLevel, nil
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000187 case "WARN":
Matteo Scandolo2e6f1e32020-04-15 11:28:45 -0700188 return WarnLevel, nil
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000189 case "ERROR":
Matteo Scandolo2e6f1e32020-04-15 11:28:45 -0700190 return ErrorLevel, nil
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000191 case "FATAL":
Matteo Scandolo2e6f1e32020-04-15 11:28:45 -0700192 return FatalLevel, nil
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000193 }
Matteo Scandolo2e6f1e32020-04-15 11:28:45 -0700194 return 0, errors.New("Given LogLevel is invalid : " + l)
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000195}
196
Matteo Scandolo2e6f1e32020-04-15 11:28:45 -0700197func LogLevelToString(l LogLevel) (string, error) {
198 switch l {
199 case DebugLevel:
200 return "DEBUG", nil
201 case InfoLevel:
202 return "INFO", nil
203 case WarnLevel:
204 return "WARN", nil
205 case ErrorLevel:
206 return "ERROR", nil
207 case FatalLevel:
208 return "FATAL", nil
209 }
210 return "", errors.New("Given LogLevel is invalid " + string(l))
211}
212
213func getDefaultConfig(outputType string, level LogLevel, defaultFields Fields) zp.Config {
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000214 return zp.Config{
Matteo Scandolo2e6f1e32020-04-15 11:28:45 -0700215 Level: logLevelToAtomicLevel(level),
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000216 Encoding: outputType,
217 Development: true,
218 OutputPaths: []string{"stdout"},
219 ErrorOutputPaths: []string{"stderr"},
220 InitialFields: defaultFields,
221 EncoderConfig: zc.EncoderConfig{
222 LevelKey: "level",
223 MessageKey: "msg",
224 TimeKey: "ts",
Matteo Scandolo2e6f1e32020-04-15 11:28:45 -0700225 CallerKey: "caller",
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000226 StacktraceKey: "stacktrace",
227 LineEnding: zc.DefaultLineEnding,
228 EncodeLevel: zc.LowercaseLevelEncoder,
229 EncodeTime: zc.ISO8601TimeEncoder,
230 EncodeDuration: zc.SecondsDurationEncoder,
231 EncodeCaller: zc.ShortCallerEncoder,
232 },
233 }
234}
235
Matteo Scandolod132c0e2020-04-24 17:06:25 -0700236func ConstructZapConfig(outputType string, level LogLevel, fields Fields) zp.Config {
237 return getDefaultConfig(outputType, level, fields)
238}
239
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000240// SetLogger needs to be invoked before the logger API can be invoked. This function
241// initialize the default logger (zap's sugaredlogger)
mpagenkoaf801632020-07-03 10:00:42 +0000242func SetDefaultLogger(outputType string, level LogLevel, defaultFields Fields) (CLogger, error) {
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000243 // Build a custom config using zap
244 cfg = getDefaultConfig(outputType, level, defaultFields)
245
Matteo Scandolo2e6f1e32020-04-15 11:28:45 -0700246 l, err := cfg.Build(zp.AddCallerSkip(1))
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000247 if err != nil {
248 return nil, err
249 }
250
mpagenkoaf801632020-07-03 10:00:42 +0000251 defaultLogger = &clogger{
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000252 log: l.Sugar(),
253 parent: l,
254 }
255
256 return defaultLogger, nil
257}
258
259// AddPackage registers a package to the log map. Each package gets its own logger which allows
260// its config (loglevel) to be changed dynamically without interacting with the other packages.
261// outputType is JSON, level is the lowest level log to output with this logger and defaultFields is a map of
262// key-value pairs to always add to the output.
263// Note: AddPackage also returns a reference to the actual logger. If a calling package uses this reference directly
264//instead of using the publicly available functions in this log package then a number of functionalities will not
265// be available to it, notably log tracing with filename.functionname.linenumber annotation.
266//
267// pkgNames parameter should be used for testing only as this function detects the caller's package.
mpagenkoaf801632020-07-03 10:00:42 +0000268func RegisterPackage(outputType string, level LogLevel, defaultFields Fields, pkgNames ...string) (CLogger, error) {
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000269 if cfgs == nil {
270 cfgs = make(map[string]zp.Config)
271 }
272 if loggers == nil {
mpagenkoaf801632020-07-03 10:00:42 +0000273 loggers = make(map[string]*clogger)
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000274 }
275
276 var pkgName string
277 for _, name := range pkgNames {
278 pkgName = name
279 break
280 }
281 if pkgName == "" {
282 pkgName, _, _, _ = getCallerInfo()
283 }
284
285 if _, exist := loggers[pkgName]; exist {
286 return loggers[pkgName], nil
287 }
288
289 cfgs[pkgName] = getDefaultConfig(outputType, level, defaultFields)
290
Matteo Scandolo2e6f1e32020-04-15 11:28:45 -0700291 l, err := cfgs[pkgName].Build(zp.AddCallerSkip(1))
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000292 if err != nil {
293 return nil, err
294 }
295
mpagenkoaf801632020-07-03 10:00:42 +0000296 loggers[pkgName] = &clogger{
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000297 log: l.Sugar(),
298 parent: l,
299 packageName: pkgName,
300 }
301 return loggers[pkgName], nil
302}
303
304//UpdateAllLoggers create new loggers for all registered pacakges with the defaultFields.
305func UpdateAllLoggers(defaultFields Fields) error {
306 for pkgName, cfg := range cfgs {
307 for k, v := range defaultFields {
308 if cfg.InitialFields == nil {
309 cfg.InitialFields = make(map[string]interface{})
310 }
311 cfg.InitialFields[k] = v
312 }
Matteo Scandolo2e6f1e32020-04-15 11:28:45 -0700313 l, err := cfg.Build(zp.AddCallerSkip(1))
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000314 if err != nil {
315 return err
316 }
317
Matteo Scandolo2e6f1e32020-04-15 11:28:45 -0700318 // Update the existing zap logger instance
319 loggers[pkgName].log = l.Sugar()
320 loggers[pkgName].parent = l
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000321 }
322 return nil
323}
324
325// Return a list of all packages that have individually-configured loggers
326func GetPackageNames() []string {
327 i := 0
328 keys := make([]string, len(loggers))
329 for k := range loggers {
330 keys[i] = k
331 i++
332 }
333 return keys
334}
335
Matteo Scandolo2e6f1e32020-04-15 11:28:45 -0700336// UpdateLogger updates the logger associated with a caller's package with supplied defaultFields
337func UpdateLogger(defaultFields Fields) error {
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000338 pkgName, _, _, _ := getCallerInfo()
339 if _, exist := loggers[pkgName]; !exist {
Matteo Scandolo2e6f1e32020-04-15 11:28:45 -0700340 return fmt.Errorf("package-%s-not-registered", pkgName)
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000341 }
342
343 // Build a new logger
344 if _, exist := cfgs[pkgName]; !exist {
Matteo Scandolo2e6f1e32020-04-15 11:28:45 -0700345 return fmt.Errorf("config-%s-not-registered", pkgName)
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000346 }
347
348 cfg := cfgs[pkgName]
349 for k, v := range defaultFields {
350 if cfg.InitialFields == nil {
351 cfg.InitialFields = make(map[string]interface{})
352 }
353 cfg.InitialFields[k] = v
354 }
Matteo Scandolo2e6f1e32020-04-15 11:28:45 -0700355 l, err := cfg.Build(zp.AddCallerSkip(1))
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000356 if err != nil {
Matteo Scandolo2e6f1e32020-04-15 11:28:45 -0700357 return err
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000358 }
359
Matteo Scandolo2e6f1e32020-04-15 11:28:45 -0700360 // Update the existing zap logger instance
361 loggers[pkgName].log = l.Sugar()
362 loggers[pkgName].parent = l
363
364 return nil
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000365}
366
Matteo Scandolo2e6f1e32020-04-15 11:28:45 -0700367func setLevel(cfg zp.Config, level LogLevel) {
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000368 switch level {
369 case DebugLevel:
370 cfg.Level.SetLevel(zc.DebugLevel)
371 case InfoLevel:
372 cfg.Level.SetLevel(zc.InfoLevel)
373 case WarnLevel:
374 cfg.Level.SetLevel(zc.WarnLevel)
375 case ErrorLevel:
376 cfg.Level.SetLevel(zc.ErrorLevel)
377 case FatalLevel:
378 cfg.Level.SetLevel(zc.FatalLevel)
379 default:
380 cfg.Level.SetLevel(zc.ErrorLevel)
381 }
382}
383
384//SetPackageLogLevel dynamically sets the log level of a given package to level. This is typically invoked at an
385// application level during debugging
Matteo Scandolo2e6f1e32020-04-15 11:28:45 -0700386func SetPackageLogLevel(packageName string, level LogLevel) {
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000387 // Get proper config
388 if cfg, ok := cfgs[packageName]; ok {
389 setLevel(cfg, level)
390 }
391}
392
393//SetAllLogLevel sets the log level of all registered packages to level
Matteo Scandolo2e6f1e32020-04-15 11:28:45 -0700394func SetAllLogLevel(level LogLevel) {
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000395 // Get proper config
396 for _, cfg := range cfgs {
397 setLevel(cfg, level)
398 }
399}
400
401//GetPackageLogLevel returns the current log level of a package.
Matteo Scandolo2e6f1e32020-04-15 11:28:45 -0700402func GetPackageLogLevel(packageName ...string) (LogLevel, error) {
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000403 var name string
404 if len(packageName) == 1 {
405 name = packageName[0]
406 } else {
407 name, _, _, _ = getCallerInfo()
408 }
409 if cfg, ok := cfgs[name]; ok {
Matteo Scandolo2e6f1e32020-04-15 11:28:45 -0700410 return levelToLogLevel(cfg.Level.Level()), nil
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000411 }
Matteo Scandolo2e6f1e32020-04-15 11:28:45 -0700412 return 0, fmt.Errorf("unknown-package-%s", name)
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000413}
414
415//GetDefaultLogLevel gets the log level used for packages that don't have specific loggers
Matteo Scandolo2e6f1e32020-04-15 11:28:45 -0700416func GetDefaultLogLevel() LogLevel {
417 return levelToLogLevel(cfg.Level.Level())
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000418}
419
420//SetLogLevel sets the log level for the logger corresponding to the caller's package
Matteo Scandolo2e6f1e32020-04-15 11:28:45 -0700421func SetLogLevel(level LogLevel) error {
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000422 pkgName, _, _, _ := getCallerInfo()
423 if _, exist := cfgs[pkgName]; !exist {
Matteo Scandolo2e6f1e32020-04-15 11:28:45 -0700424 return fmt.Errorf("unregistered-package-%s", pkgName)
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000425 }
426 cfg := cfgs[pkgName]
427 setLevel(cfg, level)
428 return nil
429}
430
431//SetDefaultLogLevel sets the log level used for packages that don't have specific loggers
Matteo Scandolo2e6f1e32020-04-15 11:28:45 -0700432func SetDefaultLogLevel(level LogLevel) {
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000433 setLevel(cfg, level)
434}
435
436// CleanUp flushed any buffered log entries. Applications should take care to call
437// CleanUp before exiting.
438func CleanUp() error {
439 for _, logger := range loggers {
440 if logger != nil {
441 if logger.parent != nil {
442 if err := logger.parent.Sync(); err != nil {
443 return err
444 }
445 }
446 }
447 }
448 if defaultLogger != nil {
449 if defaultLogger.parent != nil {
450 if err := defaultLogger.parent.Sync(); err != nil {
451 return err
452 }
453 }
454 }
455 return nil
456}
457
458func getCallerInfo() (string, string, string, int) {
459 // Since the caller of a log function is one stack frame before (in terms of stack higher level) the log.go
460 // filename, then first look for the last log.go filename and then grab the caller info one level higher.
461 maxLevel := 3
462 skiplevel := 3 // Level with the most empirical success to see the last log.go stack frame.
463 pc := make([]uintptr, maxLevel)
464 n := runtime.Callers(skiplevel, pc)
465 packageName := ""
466 funcName := ""
467 fileName := ""
468 var line int
469 if n == 0 {
470 return packageName, fileName, funcName, line
471 }
472 frames := runtime.CallersFrames(pc[:n])
473 var frame runtime.Frame
474 var foundFrame runtime.Frame
475 more := true
476 for more {
477 frame, more = frames.Next()
478 _, fileName = path.Split(frame.File)
479 if fileName != "log.go" {
480 foundFrame = frame // First frame after log.go in the frame stack
481 break
482 }
483 }
484 parts := strings.Split(foundFrame.Function, ".")
485 pl := len(parts)
486 if pl >= 2 {
487 funcName = parts[pl-1]
488 if parts[pl-2][0] == '(' {
489 packageName = strings.Join(parts[0:pl-2], ".")
490 } else {
491 packageName = strings.Join(parts[0:pl-1], ".")
492 }
493 }
494
495 if strings.HasSuffix(packageName, ".init") {
496 packageName = strings.TrimSuffix(packageName, ".init")
497 }
498
499 if strings.HasSuffix(fileName, ".go") {
500 fileName = strings.TrimSuffix(fileName, ".go")
501 }
502
503 return packageName, fileName, funcName, foundFrame.Line
504}
505
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000506// With returns a logger initialized with the key-value pairs
mpagenkoaf801632020-07-03 10:00:42 +0000507func (l clogger) With(keysAndValues Fields) CLogger {
508 return clogger{log: l.log.With(serializeMap(keysAndValues)...), parent: l.parent}
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000509}
510
511// Debug logs a message at level Debug on the standard logger.
mpagenkoaf801632020-07-03 10:00:42 +0000512func (l clogger) Debug(ctx context.Context, args ...interface{}) {
513 l.log.With(ExtractContextAttributes(ctx)...).Debug(args...)
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000514}
515
516// Debugln logs a message at level Debug on the standard logger with a line feed. Default in any case.
mpagenkoaf801632020-07-03 10:00:42 +0000517func (l clogger) Debugln(ctx context.Context, args ...interface{}) {
518 l.log.With(ExtractContextAttributes(ctx)...).Debug(args...)
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000519}
520
521// Debugw logs a message at level Debug on the standard logger.
mpagenkoaf801632020-07-03 10:00:42 +0000522func (l clogger) Debugf(ctx context.Context, format string, args ...interface{}) {
523 l.log.With(ExtractContextAttributes(ctx)...).Debugf(format, args...)
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000524}
525
526// Debugw logs a message with some additional context. The variadic key-value
527// pairs are treated as they are in With.
mpagenkoaf801632020-07-03 10:00:42 +0000528func (l clogger) Debugw(ctx context.Context, msg string, keysAndValues Fields) {
529 if l.V(DebugLevel) {
530 l.log.With(ExtractContextAttributes(ctx)...).Debugw(msg, serializeMap(keysAndValues)...)
531 }
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000532}
533
534// Info logs a message at level Info on the standard logger.
mpagenkoaf801632020-07-03 10:00:42 +0000535func (l clogger) Info(ctx context.Context, args ...interface{}) {
536 l.log.With(ExtractContextAttributes(ctx)...).Info(args...)
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000537}
538
539// Infoln logs a message at level Info on the standard logger with a line feed. Default in any case.
mpagenkoaf801632020-07-03 10:00:42 +0000540func (l clogger) Infoln(ctx context.Context, args ...interface{}) {
541 l.log.With(ExtractContextAttributes(ctx)...).Info(args...)
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000542 //msg := fmt.Sprintln(args...)
543 //l.sourced().Info(msg[:len(msg)-1])
544}
545
546// Infof logs a message at level Info on the standard logger.
mpagenkoaf801632020-07-03 10:00:42 +0000547func (l clogger) Infof(ctx context.Context, format string, args ...interface{}) {
548 l.log.With(ExtractContextAttributes(ctx)...).Infof(format, args...)
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000549}
550
551// Infow logs a message with some additional context. The variadic key-value
552// pairs are treated as they are in With.
mpagenkoaf801632020-07-03 10:00:42 +0000553func (l clogger) Infow(ctx context.Context, msg string, keysAndValues Fields) {
554 if l.V(InfoLevel) {
555 l.log.With(ExtractContextAttributes(ctx)...).Infow(msg, serializeMap(keysAndValues)...)
556 }
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000557}
558
559// Warn logs a message at level Warn on the standard logger.
mpagenkoaf801632020-07-03 10:00:42 +0000560func (l clogger) Warn(ctx context.Context, args ...interface{}) {
561 l.log.With(ExtractContextAttributes(ctx)...).Warn(args...)
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000562}
563
564// Warnln logs a message at level Warn on the standard logger with a line feed. Default in any case.
mpagenkoaf801632020-07-03 10:00:42 +0000565func (l clogger) Warnln(ctx context.Context, args ...interface{}) {
566 l.log.With(ExtractContextAttributes(ctx)...).Warn(args...)
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000567}
568
569// Warnf logs a message at level Warn on the standard logger.
mpagenkoaf801632020-07-03 10:00:42 +0000570func (l clogger) Warnf(ctx context.Context, format string, args ...interface{}) {
571 l.log.With(ExtractContextAttributes(ctx)...).Warnf(format, args...)
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000572}
573
574// Warnw logs a message with some additional context. The variadic key-value
575// pairs are treated as they are in With.
mpagenkoaf801632020-07-03 10:00:42 +0000576func (l clogger) Warnw(ctx context.Context, msg string, keysAndValues Fields) {
577 if l.V(WarnLevel) {
578 l.log.With(ExtractContextAttributes(ctx)...).Warnw(msg, serializeMap(keysAndValues)...)
579 }
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000580}
581
582// Error logs a message at level Error on the standard logger.
mpagenkoaf801632020-07-03 10:00:42 +0000583func (l clogger) Error(ctx context.Context, args ...interface{}) {
584 l.log.With(ExtractContextAttributes(ctx)...).Error(args...)
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000585}
586
587// Errorln logs a message at level Error on the standard logger with a line feed. Default in any case.
mpagenkoaf801632020-07-03 10:00:42 +0000588func (l clogger) Errorln(ctx context.Context, args ...interface{}) {
589 l.log.With(ExtractContextAttributes(ctx)...).Error(args...)
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000590}
591
592// Errorf logs a message at level Error on the standard logger.
mpagenkoaf801632020-07-03 10:00:42 +0000593func (l clogger) Errorf(ctx context.Context, format string, args ...interface{}) {
594 l.log.With(ExtractContextAttributes(ctx)...).Errorf(format, args...)
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000595}
596
597// Errorw logs a message with some additional context. The variadic key-value
598// pairs are treated as they are in With.
mpagenkoaf801632020-07-03 10:00:42 +0000599func (l clogger) Errorw(ctx context.Context, msg string, keysAndValues Fields) {
600 if l.V(ErrorLevel) {
601 l.log.With(ExtractContextAttributes(ctx)...).Errorw(msg, serializeMap(keysAndValues)...)
602 }
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000603}
604
605// Fatal logs a message at level Fatal on the standard logger.
mpagenkoaf801632020-07-03 10:00:42 +0000606func (l clogger) Fatal(ctx context.Context, args ...interface{}) {
607 l.log.With(ExtractContextAttributes(ctx)...).Fatal(args...)
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000608}
609
610// Fatalln logs a message at level Fatal on the standard logger with a line feed. Default in any case.
mpagenkoaf801632020-07-03 10:00:42 +0000611func (l clogger) Fatalln(ctx context.Context, args ...interface{}) {
612 l.log.With(ExtractContextAttributes(ctx)...).Fatal(args...)
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000613}
614
615// Fatalf logs a message at level Fatal on the standard logger.
mpagenkoaf801632020-07-03 10:00:42 +0000616func (l clogger) Fatalf(ctx context.Context, format string, args ...interface{}) {
617 l.log.With(ExtractContextAttributes(ctx)...).Fatalf(format, args...)
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000618}
619
620// Fatalw logs a message with some additional context. The variadic key-value
621// pairs are treated as they are in With.
mpagenkoaf801632020-07-03 10:00:42 +0000622func (l clogger) Fatalw(ctx context.Context, msg string, keysAndValues Fields) {
623 if l.V(FatalLevel) {
624 l.log.With(ExtractContextAttributes(ctx)...).Fatalw(msg, serializeMap(keysAndValues)...)
625 }
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000626}
627
628// Warning logs a message at level Warn on the standard logger.
mpagenkoaf801632020-07-03 10:00:42 +0000629func (l clogger) Warning(ctx context.Context, args ...interface{}) {
630 l.log.With(ExtractContextAttributes(ctx)...).Warn(args...)
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000631}
632
633// Warningln logs a message at level Warn on the standard logger with a line feed. Default in any case.
mpagenkoaf801632020-07-03 10:00:42 +0000634func (l clogger) Warningln(ctx context.Context, args ...interface{}) {
635 l.log.With(ExtractContextAttributes(ctx)...).Warn(args...)
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000636}
637
638// Warningf logs a message at level Warn on the standard logger.
mpagenkoaf801632020-07-03 10:00:42 +0000639func (l clogger) Warningf(ctx context.Context, format string, args ...interface{}) {
640 l.log.With(ExtractContextAttributes(ctx)...).Warnf(format, args...)
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000641}
642
643// V reports whether verbosity level l is at least the requested verbose level.
mpagenkoaf801632020-07-03 10:00:42 +0000644func (l clogger) V(level LogLevel) bool {
Matteo Scandolo2e6f1e32020-04-15 11:28:45 -0700645 return l.parent.Core().Enabled(logLevelToLevel(level))
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000646}
647
648// GetLogLevel returns the current level of the logger
mpagenkoaf801632020-07-03 10:00:42 +0000649func (l clogger) GetLogLevel() LogLevel {
Matteo Scandolo2e6f1e32020-04-15 11:28:45 -0700650 return levelToLogLevel(cfgs[l.packageName].Level.Level())
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000651}