blob: 1e23da1383f155364811541a8e69b953eb6e58bd [file] [log] [blame]
William Kurkianea869482019-04-09 15:16:11 -04001/*
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 (
Girish Gowdra631ef3d2020-06-15 10:45:52 -070044 "context"
William Kurkianea869482019-04-09 15:16:11 -040045 "errors"
46 "fmt"
47 zp "go.uber.org/zap"
48 zc "go.uber.org/zap/zapcore"
49 "path"
50 "runtime"
51 "strings"
52)
53
Rohan Agrawal02f784d2020-02-14 09:34:02 +000054type LogLevel int8
55
William Kurkianea869482019-04-09 15:16:11 -040056const (
57 // DebugLevel logs a message at debug level
Rohan Agrawal02f784d2020-02-14 09:34:02 +000058 DebugLevel = LogLevel(iota)
William Kurkianea869482019-04-09 15:16:11 -040059 // 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
William Kurkianea869482019-04-09 15:16:11 -040065 // 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
Girish Gowdra631ef3d2020-06-15 10:45:52 -070075// Context Aware Logger represents an abstract logging interface. Any logging implementation used
William Kurkianea869482019-04-09 15:16:11 -040076// will need to abide by this interface
Girish Gowdra631ef3d2020-06-15 10:45:52 -070077type CLogger interface {
78 Debug(context.Context, ...interface{})
79 Debugln(context.Context, ...interface{})
80 Debugf(context.Context, string, ...interface{})
81 Debugw(context.Context, string, Fields)
William Kurkianea869482019-04-09 15:16:11 -040082
Girish Gowdra631ef3d2020-06-15 10:45:52 -070083 Info(context.Context, ...interface{})
84 Infoln(context.Context, ...interface{})
85 Infof(context.Context, string, ...interface{})
86 Infow(context.Context, string, Fields)
William Kurkianea869482019-04-09 15:16:11 -040087
Girish Gowdra631ef3d2020-06-15 10:45:52 -070088 Warn(context.Context, ...interface{})
89 Warnln(context.Context, ...interface{})
90 Warnf(context.Context, string, ...interface{})
91 Warnw(context.Context, string, Fields)
William Kurkianea869482019-04-09 15:16:11 -040092
Girish Gowdra631ef3d2020-06-15 10:45:52 -070093 Error(context.Context, ...interface{})
94 Errorln(context.Context, ...interface{})
95 Errorf(context.Context, string, ...interface{})
96 Errorw(context.Context, string, Fields)
William Kurkianea869482019-04-09 15:16:11 -040097
Girish Gowdra631ef3d2020-06-15 10:45:52 -070098 Fatal(context.Context, ...interface{})
99 Fatalln(context.Context, ...interface{})
100 Fatalf(context.Context, string, ...interface{})
101 Fatalw(context.Context, string, Fields)
William Kurkianea869482019-04-09 15:16:11 -0400102
Girish Gowdra631ef3d2020-06-15 10:45:52 -0700103 With(Fields) CLogger
William Kurkianea869482019-04-09 15:16:11 -0400104
105 // The following are added to be able to use this logger as a gRPC LoggerV2 if needed
106 //
Girish Gowdra631ef3d2020-06-15 10:45:52 -0700107 Warning(context.Context, ...interface{})
108 Warningln(context.Context, ...interface{})
109 Warningf(context.Context, string, ...interface{})
William Kurkianea869482019-04-09 15:16:11 -0400110
111 // V reports whether verbosity level l is at least the requested verbose level.
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000112 V(l LogLevel) bool
Esin Karamanccb714b2019-11-29 15:02:06 +0000113
114 //Returns the log level of this specific logger
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000115 GetLogLevel() LogLevel
William Kurkianea869482019-04-09 15:16:11 -0400116}
117
118// Fields is used as key-value pairs for structured logging
119type Fields map[string]interface{}
120
Girish Gowdra631ef3d2020-06-15 10:45:52 -0700121var defaultLogger *clogger
William Kurkianea869482019-04-09 15:16:11 -0400122var cfg zp.Config
123
Girish Gowdra631ef3d2020-06-15 10:45:52 -0700124var loggers map[string]*clogger
William Kurkianea869482019-04-09 15:16:11 -0400125var cfgs map[string]zp.Config
126
Girish Gowdra631ef3d2020-06-15 10:45:52 -0700127type clogger struct {
Esin Karamanccb714b2019-11-29 15:02:06 +0000128 log *zp.SugaredLogger
129 parent *zp.Logger
130 packageName string
William Kurkianea869482019-04-09 15:16:11 -0400131}
132
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000133func logLevelToAtomicLevel(l LogLevel) zp.AtomicLevel {
William Kurkianea869482019-04-09 15:16:11 -0400134 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)
William Kurkianea869482019-04-09 15:16:11 -0400143 case FatalLevel:
144 return zp.NewAtomicLevelAt(zc.FatalLevel)
145 }
146 return zp.NewAtomicLevelAt(zc.ErrorLevel)
147}
148
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000149func logLevelToLevel(l LogLevel) zc.Level {
William Kurkianea869482019-04-09 15:16:11 -0400150 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
William Kurkianea869482019-04-09 15:16:11 -0400159 case FatalLevel:
160 return zc.FatalLevel
161 }
162 return zc.ErrorLevel
163}
164
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000165func levelToLogLevel(l zc.Level) LogLevel {
William Kurkianea869482019-04-09 15:16:11 -0400166 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
Esin Karamanccb714b2019-11-29 15:02:06 +0000175 case zc.FatalLevel:
176 return FatalLevel
177 }
178 return ErrorLevel
179}
180
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000181func StringToLogLevel(l string) (LogLevel, error) {
182 switch strings.ToUpper(l) {
Esin Karamanccb714b2019-11-29 15:02:06 +0000183 case "DEBUG":
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000184 return DebugLevel, nil
Esin Karamanccb714b2019-11-29 15:02:06 +0000185 case "INFO":
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000186 return InfoLevel, nil
Esin Karamanccb714b2019-11-29 15:02:06 +0000187 case "WARN":
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000188 return WarnLevel, nil
Esin Karamanccb714b2019-11-29 15:02:06 +0000189 case "ERROR":
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000190 return ErrorLevel, nil
Esin Karamanccb714b2019-11-29 15:02:06 +0000191 case "FATAL":
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000192 return FatalLevel, nil
William Kurkianea869482019-04-09 15:16:11 -0400193 }
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000194 return 0, errors.New("Given LogLevel is invalid : " + l)
William Kurkianea869482019-04-09 15:16:11 -0400195}
196
Scott Bakere701b862020-02-20 16:19:16 -0800197func 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
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000213func getDefaultConfig(outputType string, level LogLevel, defaultFields Fields) zp.Config {
William Kurkianea869482019-04-09 15:16:11 -0400214 return zp.Config{
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000215 Level: logLevelToAtomicLevel(level),
William Kurkianea869482019-04-09 15:16:11 -0400216 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",
divyadesaid26f6b12020-03-19 06:30:28 +0000225 CallerKey: "caller",
William Kurkianea869482019-04-09 15:16:11 -0400226 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
Scott Bakered4a8e72020-04-17 11:10:20 -0700236func ConstructZapConfig(outputType string, level LogLevel, fields Fields) zp.Config {
237 return getDefaultConfig(outputType, level, fields)
238}
239
William Kurkianea869482019-04-09 15:16:11 -0400240// SetLogger needs to be invoked before the logger API can be invoked. This function
241// initialize the default logger (zap's sugaredlogger)
Girish Gowdra631ef3d2020-06-15 10:45:52 -0700242func SetDefaultLogger(outputType string, level LogLevel, defaultFields Fields) (CLogger, error) {
William Kurkianea869482019-04-09 15:16:11 -0400243 // Build a custom config using zap
244 cfg = getDefaultConfig(outputType, level, defaultFields)
245
divyadesaid26f6b12020-03-19 06:30:28 +0000246 l, err := cfg.Build(zp.AddCallerSkip(1))
William Kurkianea869482019-04-09 15:16:11 -0400247 if err != nil {
248 return nil, err
249 }
250
Girish Gowdra631ef3d2020-06-15 10:45:52 -0700251 defaultLogger = &clogger{
William Kurkianea869482019-04-09 15:16:11 -0400252 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.
Girish Gowdra631ef3d2020-06-15 10:45:52 -0700268func RegisterPackage(outputType string, level LogLevel, defaultFields Fields, pkgNames ...string) (CLogger, error) {
William Kurkianea869482019-04-09 15:16:11 -0400269 if cfgs == nil {
270 cfgs = make(map[string]zp.Config)
271 }
272 if loggers == nil {
Girish Gowdra631ef3d2020-06-15 10:45:52 -0700273 loggers = make(map[string]*clogger)
William Kurkianea869482019-04-09 15:16:11 -0400274 }
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
divyadesaid26f6b12020-03-19 06:30:28 +0000291 l, err := cfgs[pkgName].Build(zp.AddCallerSkip(1))
William Kurkianea869482019-04-09 15:16:11 -0400292 if err != nil {
293 return nil, err
294 }
295
Girish Gowdra631ef3d2020-06-15 10:45:52 -0700296 loggers[pkgName] = &clogger{
Esin Karamanccb714b2019-11-29 15:02:06 +0000297 log: l.Sugar(),
298 parent: l,
299 packageName: pkgName,
William Kurkianea869482019-04-09 15:16:11 -0400300 }
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 }
divyadesaid26f6b12020-03-19 06:30:28 +0000313 l, err := cfg.Build(zp.AddCallerSkip(1))
William Kurkianea869482019-04-09 15:16:11 -0400314 if err != nil {
315 return err
316 }
317
divyadesaid26f6b12020-03-19 06:30:28 +0000318 // Update the existing zap logger instance
319 loggers[pkgName].log = l.Sugar()
320 loggers[pkgName].parent = l
William Kurkianea869482019-04-09 15:16:11 -0400321 }
322 return nil
323}
324
kdarapub26b4502019-10-05 03:02:33 +0530325// 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
divyadesaid26f6b12020-03-19 06:30:28 +0000336// UpdateLogger updates the logger associated with a caller's package with supplied defaultFields
337func UpdateLogger(defaultFields Fields) error {
William Kurkianea869482019-04-09 15:16:11 -0400338 pkgName, _, _, _ := getCallerInfo()
339 if _, exist := loggers[pkgName]; !exist {
divyadesaid26f6b12020-03-19 06:30:28 +0000340 return fmt.Errorf("package-%s-not-registered", pkgName)
William Kurkianea869482019-04-09 15:16:11 -0400341 }
342
343 // Build a new logger
344 if _, exist := cfgs[pkgName]; !exist {
divyadesaid26f6b12020-03-19 06:30:28 +0000345 return fmt.Errorf("config-%s-not-registered", pkgName)
William Kurkianea869482019-04-09 15:16:11 -0400346 }
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 }
divyadesaid26f6b12020-03-19 06:30:28 +0000355 l, err := cfg.Build(zp.AddCallerSkip(1))
William Kurkianea869482019-04-09 15:16:11 -0400356 if err != nil {
divyadesaid26f6b12020-03-19 06:30:28 +0000357 return err
William Kurkianea869482019-04-09 15:16:11 -0400358 }
359
divyadesaid26f6b12020-03-19 06:30:28 +0000360 // Update the existing zap logger instance
361 loggers[pkgName].log = l.Sugar()
362 loggers[pkgName].parent = l
363
364 return nil
William Kurkianea869482019-04-09 15:16:11 -0400365}
366
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000367func setLevel(cfg zp.Config, level LogLevel) {
William Kurkianea869482019-04-09 15:16:11 -0400368 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)
William Kurkianea869482019-04-09 15:16:11 -0400377 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
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000386func SetPackageLogLevel(packageName string, level LogLevel) {
William Kurkianea869482019-04-09 15:16:11 -0400387 // 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
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000394func SetAllLogLevel(level LogLevel) {
William Kurkianea869482019-04-09 15:16:11 -0400395 // 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.
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000402func GetPackageLogLevel(packageName ...string) (LogLevel, error) {
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400403 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 {
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000410 return levelToLogLevel(cfg.Level.Level()), nil
William Kurkianea869482019-04-09 15:16:11 -0400411 }
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000412 return 0, fmt.Errorf("unknown-package-%s", name)
William Kurkianea869482019-04-09 15:16:11 -0400413}
414
kdarapub26b4502019-10-05 03:02:33 +0530415//GetDefaultLogLevel gets the log level used for packages that don't have specific loggers
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000416func GetDefaultLogLevel() LogLevel {
417 return levelToLogLevel(cfg.Level.Level())
kdarapub26b4502019-10-05 03:02:33 +0530418}
419
William Kurkianea869482019-04-09 15:16:11 -0400420//SetLogLevel sets the log level for the logger corresponding to the caller's package
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000421func SetLogLevel(level LogLevel) error {
William Kurkianea869482019-04-09 15:16:11 -0400422 pkgName, _, _, _ := getCallerInfo()
423 if _, exist := cfgs[pkgName]; !exist {
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000424 return fmt.Errorf("unregistered-package-%s", pkgName)
William Kurkianea869482019-04-09 15:16:11 -0400425 }
426 cfg := cfgs[pkgName]
427 setLevel(cfg, level)
428 return nil
429}
430
kdarapub26b4502019-10-05 03:02:33 +0530431//SetDefaultLogLevel sets the log level used for packages that don't have specific loggers
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000432func SetDefaultLogLevel(level LogLevel) {
kdarapub26b4502019-10-05 03:02:33 +0530433 setLevel(cfg, level)
434}
435
William Kurkianea869482019-04-09 15:16:11 -0400436// 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
William Kurkianea869482019-04-09 15:16:11 -0400506// With returns a logger initialized with the key-value pairs
Girish Gowdra631ef3d2020-06-15 10:45:52 -0700507func (l clogger) With(keysAndValues Fields) CLogger {
508 return clogger{log: l.log.With(serializeMap(keysAndValues)...), parent: l.parent}
William Kurkianea869482019-04-09 15:16:11 -0400509}
510
511// Debug logs a message at level Debug on the standard logger.
Girish Gowdra631ef3d2020-06-15 10:45:52 -0700512func (l clogger) Debug(ctx context.Context, args ...interface{}) {
513 l.log.With(ExtractContextAttributes(ctx)...).Debug(args...)
William Kurkianea869482019-04-09 15:16:11 -0400514}
515
516// Debugln logs a message at level Debug on the standard logger with a line feed. Default in any case.
Girish Gowdra631ef3d2020-06-15 10:45:52 -0700517func (l clogger) Debugln(ctx context.Context, args ...interface{}) {
518 l.log.With(ExtractContextAttributes(ctx)...).Debug(args...)
William Kurkianea869482019-04-09 15:16:11 -0400519}
520
521// Debugw logs a message at level Debug on the standard logger.
Girish Gowdra631ef3d2020-06-15 10:45:52 -0700522func (l clogger) Debugf(ctx context.Context, format string, args ...interface{}) {
523 l.log.With(ExtractContextAttributes(ctx)...).Debugf(format, args...)
William Kurkianea869482019-04-09 15:16:11 -0400524}
525
526// Debugw logs a message with some additional context. The variadic key-value
527// pairs are treated as they are in With.
Girish Gowdra631ef3d2020-06-15 10:45:52 -0700528func (l clogger) Debugw(ctx context.Context, msg string, keysAndValues Fields) {
Neha Sharmacc656962020-04-14 14:26:11 +0000529 if l.V(DebugLevel) {
Girish Gowdra631ef3d2020-06-15 10:45:52 -0700530 l.log.With(ExtractContextAttributes(ctx)...).Debugw(msg, serializeMap(keysAndValues)...)
Neha Sharmacc656962020-04-14 14:26:11 +0000531 }
William Kurkianea869482019-04-09 15:16:11 -0400532}
533
534// Info logs a message at level Info on the standard logger.
Girish Gowdra631ef3d2020-06-15 10:45:52 -0700535func (l clogger) Info(ctx context.Context, args ...interface{}) {
536 l.log.With(ExtractContextAttributes(ctx)...).Info(args...)
William Kurkianea869482019-04-09 15:16:11 -0400537}
538
539// Infoln logs a message at level Info on the standard logger with a line feed. Default in any case.
Girish Gowdra631ef3d2020-06-15 10:45:52 -0700540func (l clogger) Infoln(ctx context.Context, args ...interface{}) {
541 l.log.With(ExtractContextAttributes(ctx)...).Info(args...)
William Kurkianea869482019-04-09 15:16:11 -0400542 //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.
Girish Gowdra631ef3d2020-06-15 10:45:52 -0700547func (l clogger) Infof(ctx context.Context, format string, args ...interface{}) {
548 l.log.With(ExtractContextAttributes(ctx)...).Infof(format, args...)
William Kurkianea869482019-04-09 15:16:11 -0400549}
550
551// Infow logs a message with some additional context. The variadic key-value
552// pairs are treated as they are in With.
Girish Gowdra631ef3d2020-06-15 10:45:52 -0700553func (l clogger) Infow(ctx context.Context, msg string, keysAndValues Fields) {
Neha Sharmacc656962020-04-14 14:26:11 +0000554 if l.V(InfoLevel) {
Girish Gowdra631ef3d2020-06-15 10:45:52 -0700555 l.log.With(ExtractContextAttributes(ctx)...).Infow(msg, serializeMap(keysAndValues)...)
Neha Sharmacc656962020-04-14 14:26:11 +0000556 }
William Kurkianea869482019-04-09 15:16:11 -0400557}
558
559// Warn logs a message at level Warn on the standard logger.
Girish Gowdra631ef3d2020-06-15 10:45:52 -0700560func (l clogger) Warn(ctx context.Context, args ...interface{}) {
561 l.log.With(ExtractContextAttributes(ctx)...).Warn(args...)
William Kurkianea869482019-04-09 15:16:11 -0400562}
563
564// Warnln logs a message at level Warn on the standard logger with a line feed. Default in any case.
Girish Gowdra631ef3d2020-06-15 10:45:52 -0700565func (l clogger) Warnln(ctx context.Context, args ...interface{}) {
566 l.log.With(ExtractContextAttributes(ctx)...).Warn(args...)
William Kurkianea869482019-04-09 15:16:11 -0400567}
568
569// Warnf logs a message at level Warn on the standard logger.
Girish Gowdra631ef3d2020-06-15 10:45:52 -0700570func (l clogger) Warnf(ctx context.Context, format string, args ...interface{}) {
571 l.log.With(ExtractContextAttributes(ctx)...).Warnf(format, args...)
William Kurkianea869482019-04-09 15:16:11 -0400572}
573
574// Warnw logs a message with some additional context. The variadic key-value
575// pairs are treated as they are in With.
Girish Gowdra631ef3d2020-06-15 10:45:52 -0700576func (l clogger) Warnw(ctx context.Context, msg string, keysAndValues Fields) {
Neha Sharmacc656962020-04-14 14:26:11 +0000577 if l.V(WarnLevel) {
Girish Gowdra631ef3d2020-06-15 10:45:52 -0700578 l.log.With(ExtractContextAttributes(ctx)...).Warnw(msg, serializeMap(keysAndValues)...)
Neha Sharmacc656962020-04-14 14:26:11 +0000579 }
William Kurkianea869482019-04-09 15:16:11 -0400580}
581
582// Error logs a message at level Error on the standard logger.
Girish Gowdra631ef3d2020-06-15 10:45:52 -0700583func (l clogger) Error(ctx context.Context, args ...interface{}) {
584 l.log.With(ExtractContextAttributes(ctx)...).Error(args...)
William Kurkianea869482019-04-09 15:16:11 -0400585}
586
587// Errorln logs a message at level Error on the standard logger with a line feed. Default in any case.
Girish Gowdra631ef3d2020-06-15 10:45:52 -0700588func (l clogger) Errorln(ctx context.Context, args ...interface{}) {
589 l.log.With(ExtractContextAttributes(ctx)...).Error(args...)
William Kurkianea869482019-04-09 15:16:11 -0400590}
591
592// Errorf logs a message at level Error on the standard logger.
Girish Gowdra631ef3d2020-06-15 10:45:52 -0700593func (l clogger) Errorf(ctx context.Context, format string, args ...interface{}) {
594 l.log.With(ExtractContextAttributes(ctx)...).Errorf(format, args...)
William Kurkianea869482019-04-09 15:16:11 -0400595}
596
597// Errorw logs a message with some additional context. The variadic key-value
598// pairs are treated as they are in With.
Girish Gowdra631ef3d2020-06-15 10:45:52 -0700599func (l clogger) Errorw(ctx context.Context, msg string, keysAndValues Fields) {
Neha Sharmacc656962020-04-14 14:26:11 +0000600 if l.V(ErrorLevel) {
Girish Gowdra631ef3d2020-06-15 10:45:52 -0700601 l.log.With(ExtractContextAttributes(ctx)...).Errorw(msg, serializeMap(keysAndValues)...)
Neha Sharmacc656962020-04-14 14:26:11 +0000602 }
William Kurkianea869482019-04-09 15:16:11 -0400603}
604
605// Fatal logs a message at level Fatal on the standard logger.
Girish Gowdra631ef3d2020-06-15 10:45:52 -0700606func (l clogger) Fatal(ctx context.Context, args ...interface{}) {
607 l.log.With(ExtractContextAttributes(ctx)...).Fatal(args...)
William Kurkianea869482019-04-09 15:16:11 -0400608}
609
610// Fatalln logs a message at level Fatal on the standard logger with a line feed. Default in any case.
Girish Gowdra631ef3d2020-06-15 10:45:52 -0700611func (l clogger) Fatalln(ctx context.Context, args ...interface{}) {
612 l.log.With(ExtractContextAttributes(ctx)...).Fatal(args...)
William Kurkianea869482019-04-09 15:16:11 -0400613}
614
615// Fatalf logs a message at level Fatal on the standard logger.
Girish Gowdra631ef3d2020-06-15 10:45:52 -0700616func (l clogger) Fatalf(ctx context.Context, format string, args ...interface{}) {
617 l.log.With(ExtractContextAttributes(ctx)...).Fatalf(format, args...)
William Kurkianea869482019-04-09 15:16:11 -0400618}
619
620// Fatalw logs a message with some additional context. The variadic key-value
621// pairs are treated as they are in With.
Girish Gowdra631ef3d2020-06-15 10:45:52 -0700622func (l clogger) Fatalw(ctx context.Context, msg string, keysAndValues Fields) {
Neha Sharmacc656962020-04-14 14:26:11 +0000623 if l.V(FatalLevel) {
Girish Gowdra631ef3d2020-06-15 10:45:52 -0700624 l.log.With(ExtractContextAttributes(ctx)...).Fatalw(msg, serializeMap(keysAndValues)...)
Neha Sharmacc656962020-04-14 14:26:11 +0000625 }
William Kurkianea869482019-04-09 15:16:11 -0400626}
627
628// Warning logs a message at level Warn on the standard logger.
Girish Gowdra631ef3d2020-06-15 10:45:52 -0700629func (l clogger) Warning(ctx context.Context, args ...interface{}) {
630 l.log.With(ExtractContextAttributes(ctx)...).Warn(args...)
William Kurkianea869482019-04-09 15:16:11 -0400631}
632
633// Warningln logs a message at level Warn on the standard logger with a line feed. Default in any case.
Girish Gowdra631ef3d2020-06-15 10:45:52 -0700634func (l clogger) Warningln(ctx context.Context, args ...interface{}) {
635 l.log.With(ExtractContextAttributes(ctx)...).Warn(args...)
William Kurkianea869482019-04-09 15:16:11 -0400636}
637
638// Warningf logs a message at level Warn on the standard logger.
Girish Gowdra631ef3d2020-06-15 10:45:52 -0700639func (l clogger) Warningf(ctx context.Context, format string, args ...interface{}) {
640 l.log.With(ExtractContextAttributes(ctx)...).Warnf(format, args...)
William Kurkianea869482019-04-09 15:16:11 -0400641}
642
643// V reports whether verbosity level l is at least the requested verbose level.
Girish Gowdra631ef3d2020-06-15 10:45:52 -0700644func (l clogger) V(level LogLevel) bool {
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000645 return l.parent.Core().Enabled(logLevelToLevel(level))
William Kurkianea869482019-04-09 15:16:11 -0400646}
647
Esin Karamanccb714b2019-11-29 15:02:06 +0000648// GetLogLevel returns the current level of the logger
Girish Gowdra631ef3d2020-06-15 10:45:52 -0700649func (l clogger) GetLogLevel() LogLevel {
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000650 return levelToLogLevel(cfgs[l.packageName].Level.Level())
Esin Karamanccb714b2019-11-29 15:02:06 +0000651}