blob: 3ebdd3aaff314dc80d205cf531b5ff1fd6138bcd [file] [log] [blame]
khenaidoobf6e7bb2018-08-14 22:27:29 -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 */
khenaidoo7da372d2018-09-21 16:03:09 -040016
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
khenaidoocfee5f42018-07-19 22:47:38 -040041package log
42
43import (
khenaidoo7da372d2018-09-21 16:03:09 -040044 "errors"
khenaidoo5c11af72018-07-20 17:21:05 -040045 "fmt"
khenaidoocfee5f42018-07-19 22:47:38 -040046 zp "go.uber.org/zap"
47 zc "go.uber.org/zap/zapcore"
khenaidoob9203542018-09-17 22:56:37 -040048 "path"
khenaidoocfee5f42018-07-19 22:47:38 -040049 "runtime"
50 "strings"
khenaidoocfee5f42018-07-19 22:47:38 -040051)
52
Rohan Agrawal7f72f0c2020-01-14 12:05:51 +000053type LogLevel int8
54
khenaidoocfee5f42018-07-19 22:47:38 -040055const (
56 // DebugLevel logs a message at debug level
Rohan Agrawal7f72f0c2020-01-14 12:05:51 +000057 DebugLevel = LogLevel(iota)
khenaidoocfee5f42018-07-19 22:47:38 -040058 // InfoLevel logs a message at info level
59 InfoLevel
60 // WarnLevel logs a message at warning level
61 WarnLevel
62 // ErrorLevel logs a message at error level
63 ErrorLevel
khenaidoocfee5f42018-07-19 22:47:38 -040064 // FatalLevel logs a message, then calls os.Exit(1).
65 FatalLevel
66)
67
68// CONSOLE formats the log for the console, mostly used during development
69const CONSOLE = "console"
khenaidoo5c11af72018-07-20 17:21:05 -040070
khenaidoocfee5f42018-07-19 22:47:38 -040071// JSON formats the log using json format, mostly used by an automated logging system consumption
72const JSON = "json"
73
74// Logger represents an abstract logging interface. Any logging implementation used
75// will need to abide by this interface
76type Logger interface {
77 Debug(...interface{})
78 Debugln(...interface{})
79 Debugf(string, ...interface{})
80 Debugw(string, Fields)
81
82 Info(...interface{})
83 Infoln(...interface{})
84 Infof(string, ...interface{})
85 Infow(string, Fields)
86
87 Warn(...interface{})
88 Warnln(...interface{})
89 Warnf(string, ...interface{})
90 Warnw(string, Fields)
91
92 Error(...interface{})
93 Errorln(...interface{})
94 Errorf(string, ...interface{})
95 Errorw(string, Fields)
96
97 Fatal(...interface{})
98 Fatalln(...interface{})
99 Fatalf(string, ...interface{})
100 Fatalw(string, Fields)
101
102 With(Fields) Logger
khenaidoo7da372d2018-09-21 16:03:09 -0400103
104 // The following are added to be able to use this logger as a gRPC LoggerV2 if needed
105 //
106 Warning(...interface{})
107 Warningln(...interface{})
108 Warningf(string, ...interface{})
109
110 // V reports whether verbosity level l is at least the requested verbose level.
Rohan Agrawal7f72f0c2020-01-14 12:05:51 +0000111 V(l LogLevel) bool
serkant.uluderya2ae470f2020-01-21 11:13:09 -0800112
113 //Returns the log level of this specific logger
Rohan Agrawal7f72f0c2020-01-14 12:05:51 +0000114 GetLogLevel() LogLevel
khenaidoocfee5f42018-07-19 22:47:38 -0400115}
116
khenaidoo7da372d2018-09-21 16:03:09 -0400117// Fields is used as key-value pairs for structured logging
khenaidoocfee5f42018-07-19 22:47:38 -0400118type Fields map[string]interface{}
119
120var defaultLogger *logger
khenaidoob9203542018-09-17 22:56:37 -0400121var cfg zp.Config
122
123var loggers map[string]*logger
124var cfgs map[string]zp.Config
khenaidoocfee5f42018-07-19 22:47:38 -0400125
126type logger struct {
serkant.uluderya2ae470f2020-01-21 11:13:09 -0800127 log *zp.SugaredLogger
128 parent *zp.Logger
129 packageName string
khenaidoocfee5f42018-07-19 22:47:38 -0400130}
131
Rohan Agrawal7f72f0c2020-01-14 12:05:51 +0000132func logLevelToAtomicLevel(l LogLevel) zp.AtomicLevel {
khenaidoocfee5f42018-07-19 22:47:38 -0400133 switch l {
134 case DebugLevel:
135 return zp.NewAtomicLevelAt(zc.DebugLevel)
136 case InfoLevel:
137 return zp.NewAtomicLevelAt(zc.InfoLevel)
138 case WarnLevel:
139 return zp.NewAtomicLevelAt(zc.WarnLevel)
140 case ErrorLevel:
141 return zp.NewAtomicLevelAt(zc.ErrorLevel)
khenaidoocfee5f42018-07-19 22:47:38 -0400142 case FatalLevel:
143 return zp.NewAtomicLevelAt(zc.FatalLevel)
144 }
145 return zp.NewAtomicLevelAt(zc.ErrorLevel)
146}
147
Rohan Agrawal7f72f0c2020-01-14 12:05:51 +0000148func logLevelToLevel(l LogLevel) zc.Level {
khenaidoo7da372d2018-09-21 16:03:09 -0400149 switch l {
150 case DebugLevel:
151 return zc.DebugLevel
152 case InfoLevel:
khenaidoo6f2fbe32019-01-18 16:16:50 -0500153 return zc.InfoLevel
khenaidoo7da372d2018-09-21 16:03:09 -0400154 case WarnLevel:
155 return zc.WarnLevel
156 case ErrorLevel:
157 return zc.ErrorLevel
khenaidoo7da372d2018-09-21 16:03:09 -0400158 case FatalLevel:
159 return zc.FatalLevel
160 }
161 return zc.ErrorLevel
162}
163
Rohan Agrawal7f72f0c2020-01-14 12:05:51 +0000164func levelToLogLevel(l zc.Level) LogLevel {
khenaidoo6f2fbe32019-01-18 16:16:50 -0500165 switch l {
166 case zc.DebugLevel:
167 return DebugLevel
168 case zc.InfoLevel:
169 return InfoLevel
170 case zc.WarnLevel:
171 return WarnLevel
172 case zc.ErrorLevel:
173 return ErrorLevel
serkant.uluderya2ae470f2020-01-21 11:13:09 -0800174 case zc.FatalLevel:
175 return FatalLevel
176 }
177 return ErrorLevel
178}
179
Rohan Agrawal7f72f0c2020-01-14 12:05:51 +0000180func StringToLogLevel(l string) (LogLevel, error) {
181 switch strings.ToUpper(l) {
serkant.uluderya2ae470f2020-01-21 11:13:09 -0800182 case "DEBUG":
Rohan Agrawal7f72f0c2020-01-14 12:05:51 +0000183 return DebugLevel, nil
serkant.uluderya2ae470f2020-01-21 11:13:09 -0800184 case "INFO":
Rohan Agrawal7f72f0c2020-01-14 12:05:51 +0000185 return InfoLevel, nil
serkant.uluderya2ae470f2020-01-21 11:13:09 -0800186 case "WARN":
Rohan Agrawal7f72f0c2020-01-14 12:05:51 +0000187 return WarnLevel, nil
serkant.uluderya2ae470f2020-01-21 11:13:09 -0800188 case "ERROR":
Rohan Agrawal7f72f0c2020-01-14 12:05:51 +0000189 return ErrorLevel, nil
serkant.uluderya2ae470f2020-01-21 11:13:09 -0800190 case "FATAL":
Rohan Agrawal7f72f0c2020-01-14 12:05:51 +0000191 return FatalLevel, nil
khenaidoo6f2fbe32019-01-18 16:16:50 -0500192 }
Rohan Agrawal7f72f0c2020-01-14 12:05:51 +0000193 return 0, errors.New("Given LogLevel is invalid : " + l)
khenaidoo6f2fbe32019-01-18 16:16:50 -0500194}
195
Scott Baker0e78ba22020-02-24 17:58:47 -0800196func LogLevelToString(l LogLevel) (string, error) {
197 switch l {
198 case DebugLevel:
199 return "DEBUG", nil
200 case InfoLevel:
201 return "INFO", nil
202 case WarnLevel:
203 return "WARN", nil
204 case ErrorLevel:
205 return "ERROR", nil
206 case FatalLevel:
207 return "FATAL", nil
208 }
209 return "", errors.New("Given LogLevel is invalid " + string(l))
210}
211
Rohan Agrawal7f72f0c2020-01-14 12:05:51 +0000212func getDefaultConfig(outputType string, level LogLevel, defaultFields Fields) zp.Config {
khenaidoocfee5f42018-07-19 22:47:38 -0400213 return zp.Config{
Rohan Agrawal7f72f0c2020-01-14 12:05:51 +0000214 Level: logLevelToAtomicLevel(level),
khenaidoocfee5f42018-07-19 22:47:38 -0400215 Encoding: outputType,
216 Development: true,
217 OutputPaths: []string{"stdout"},
218 ErrorOutputPaths: []string{"stderr"},
219 InitialFields: defaultFields,
220 EncoderConfig: zc.EncoderConfig{
221 LevelKey: "level",
222 MessageKey: "msg",
223 TimeKey: "ts",
224 StacktraceKey: "stacktrace",
225 LineEnding: zc.DefaultLineEnding,
226 EncodeLevel: zc.LowercaseLevelEncoder,
227 EncodeTime: zc.ISO8601TimeEncoder,
228 EncodeDuration: zc.SecondsDurationEncoder,
229 EncodeCaller: zc.ShortCallerEncoder,
230 },
231 }
232}
233
234// SetLogger needs to be invoked before the logger API can be invoked. This function
235// initialize the default logger (zap's sugaredlogger)
Rohan Agrawal7f72f0c2020-01-14 12:05:51 +0000236func SetDefaultLogger(outputType string, level LogLevel, defaultFields Fields) (Logger, error) {
khenaidoocfee5f42018-07-19 22:47:38 -0400237 // Build a custom config using zap
khenaidood4d922e2018-08-03 22:35:16 -0400238 cfg = getDefaultConfig(outputType, level, defaultFields)
khenaidoocfee5f42018-07-19 22:47:38 -0400239
240 l, err := cfg.Build()
241 if err != nil {
242 return nil, err
243 }
244
245 defaultLogger = &logger{
246 log: l.Sugar(),
247 parent: l,
248 }
249
250 return defaultLogger, nil
251}
252
khenaidoo7da372d2018-09-21 16:03:09 -0400253// AddPackage registers a package to the log map. Each package gets its own logger which allows
254// its config (loglevel) to be changed dynamically without interacting with the other packages.
255// outputType is JSON, level is the lowest level log to output with this logger and defaultFields is a map of
256// key-value pairs to always add to the output.
257// Note: AddPackage also returns a reference to the actual logger. If a calling package uses this reference directly
258//instead of using the publicly available functions in this log package then a number of functionalities will not
259// be available to it, notably log tracing with filename.functionname.linenumber annotation.
260//
khenaidoo6f2fbe32019-01-18 16:16:50 -0500261// pkgNames parameter should be used for testing only as this function detects the caller's package.
Rohan Agrawal7f72f0c2020-01-14 12:05:51 +0000262func AddPackage(outputType string, level LogLevel, defaultFields Fields, pkgNames ...string) (Logger, error) {
khenaidoob9203542018-09-17 22:56:37 -0400263 if cfgs == nil {
264 cfgs = make(map[string]zp.Config)
265 }
266 if loggers == nil {
267 loggers = make(map[string]*logger)
268 }
khenaidoo6f2fbe32019-01-18 16:16:50 -0500269
270 var pkgName string
271 for _, name := range pkgNames {
272 pkgName = name
273 break
274 }
275 if pkgName == "" {
276 pkgName, _, _, _ = getCallerInfo()
277 }
khenaidoob9203542018-09-17 22:56:37 -0400278
khenaidoo7da372d2018-09-21 16:03:09 -0400279 if _, exist := loggers[pkgName]; exist {
280 return loggers[pkgName], nil
khenaidoob9203542018-09-17 22:56:37 -0400281 }
khenaidoo7da372d2018-09-21 16:03:09 -0400282
khenaidoob9203542018-09-17 22:56:37 -0400283 cfgs[pkgName] = getDefaultConfig(outputType, level, defaultFields)
284
285 l, err := cfgs[pkgName].Build()
286 if err != nil {
khenaidoo7da372d2018-09-21 16:03:09 -0400287 return nil, err
khenaidoob9203542018-09-17 22:56:37 -0400288 }
289
290 loggers[pkgName] = &logger{
serkant.uluderya2ae470f2020-01-21 11:13:09 -0800291 log: l.Sugar(),
292 parent: l,
293 packageName: pkgName,
khenaidoob9203542018-09-17 22:56:37 -0400294 }
khenaidoo7da372d2018-09-21 16:03:09 -0400295 return loggers[pkgName], nil
khenaidoob9203542018-09-17 22:56:37 -0400296}
297
khenaidoo7da372d2018-09-21 16:03:09 -0400298//UpdateAllLoggers create new loggers for all registered pacakges with the defaultFields.
khenaidoob9203542018-09-17 22:56:37 -0400299func UpdateAllLoggers(defaultFields Fields) error {
300 for pkgName, cfg := range cfgs {
301 for k, v := range defaultFields {
302 if cfg.InitialFields == nil {
303 cfg.InitialFields = make(map[string]interface{})
304 }
305 cfg.InitialFields[k] = v
306 }
307 l, err := cfg.Build()
308 if err != nil {
309 return err
310 }
311
312 loggers[pkgName] = &logger{
serkant.uluderya2ae470f2020-01-21 11:13:09 -0800313 log: l.Sugar(),
314 parent: l,
315 packageName: pkgName,
khenaidoob9203542018-09-17 22:56:37 -0400316 }
317 }
318 return nil
319}
320
Scott Baker5f401472019-08-22 08:32:26 -0700321// Return a list of all packages that have individually-configured loggers
322func GetPackageNames() []string {
323 i := 0
324 keys := make([]string, len(loggers))
325 for k := range loggers {
326 keys[i] = k
327 i++
328 }
329 return keys
330}
331
khenaidoo7da372d2018-09-21 16:03:09 -0400332// UpdateLogger deletes the logger associated with a caller's package and creates a new logger with the
333// defaultFields. If a calling package is holding on to a Logger reference obtained from AddPackage invocation, then
334// that package needs to invoke UpdateLogger if it needs to make changes to the default fields and obtain a new logger
335// reference
336func UpdateLogger(defaultFields Fields) (Logger, error) {
337 pkgName, _, _, _ := getCallerInfo()
338 if _, exist := loggers[pkgName]; !exist {
Rohan Agrawal7f72f0c2020-01-14 12:05:51 +0000339 return nil, fmt.Errorf("package-%s-not-registered", pkgName)
khenaidoo7da372d2018-09-21 16:03:09 -0400340 }
khenaidoob9203542018-09-17 22:56:37 -0400341
khenaidoo7da372d2018-09-21 16:03:09 -0400342 // Build a new logger
343 if _, exist := cfgs[pkgName]; !exist {
Rohan Agrawal7f72f0c2020-01-14 12:05:51 +0000344 return nil, fmt.Errorf("config-%s-not-registered", pkgName)
khenaidoo7da372d2018-09-21 16:03:09 -0400345 }
346
347 cfg := cfgs[pkgName]
348 for k, v := range defaultFields {
349 if cfg.InitialFields == nil {
350 cfg.InitialFields = make(map[string]interface{})
351 }
352 cfg.InitialFields[k] = v
353 }
354 l, err := cfg.Build()
355 if err != nil {
356 return nil, err
357 }
358
359 // Set the logger
360 loggers[pkgName] = &logger{
serkant.uluderya2ae470f2020-01-21 11:13:09 -0800361 log: l.Sugar(),
362 parent: l,
363 packageName: pkgName,
khenaidoo7da372d2018-09-21 16:03:09 -0400364 }
365 return loggers[pkgName], nil
366}
367
Rohan Agrawal7f72f0c2020-01-14 12:05:51 +0000368func setLevel(cfg zp.Config, level LogLevel) {
khenaidoo7da372d2018-09-21 16:03:09 -0400369 switch level {
370 case DebugLevel:
371 cfg.Level.SetLevel(zc.DebugLevel)
372 case InfoLevel:
373 cfg.Level.SetLevel(zc.InfoLevel)
374 case WarnLevel:
375 cfg.Level.SetLevel(zc.WarnLevel)
376 case ErrorLevel:
377 cfg.Level.SetLevel(zc.ErrorLevel)
khenaidoo7da372d2018-09-21 16:03:09 -0400378 case FatalLevel:
379 cfg.Level.SetLevel(zc.FatalLevel)
380 default:
381 cfg.Level.SetLevel(zc.ErrorLevel)
382 }
khenaidoo6f2fbe32019-01-18 16:16:50 -0500383}
384
385//SetPackageLogLevel dynamically sets the log level of a given package to level. This is typically invoked at an
386// application level during debugging
Rohan Agrawal7f72f0c2020-01-14 12:05:51 +0000387func SetPackageLogLevel(packageName string, level LogLevel) {
khenaidoo6f2fbe32019-01-18 16:16:50 -0500388 // Get proper config
389 if cfg, ok := cfgs[packageName]; ok {
390 setLevel(cfg, level)
391 }
392}
393
394//SetAllLogLevel sets the log level of all registered packages to level
Rohan Agrawal7f72f0c2020-01-14 12:05:51 +0000395func SetAllLogLevel(level LogLevel) {
khenaidoo6f2fbe32019-01-18 16:16:50 -0500396 // Get proper config
397 for _, cfg := range cfgs {
398 setLevel(cfg, level)
399 }
400}
401
402//GetPackageLogLevel returns the current log level of a package.
Rohan Agrawal7f72f0c2020-01-14 12:05:51 +0000403func GetPackageLogLevel(packageName ...string) (LogLevel, error) {
khenaidoo910204f2019-04-08 17:56:40 -0400404 var name string
405 if len(packageName) == 1 {
406 name = packageName[0]
407 } else {
408 name, _, _, _ = getCallerInfo()
409 }
410 if cfg, ok := cfgs[name]; ok {
Rohan Agrawal7f72f0c2020-01-14 12:05:51 +0000411 return levelToLogLevel(cfg.Level.Level()), nil
khenaidoo6f2fbe32019-01-18 16:16:50 -0500412 }
Rohan Agrawal7f72f0c2020-01-14 12:05:51 +0000413 return 0, fmt.Errorf("unknown-package-%s", name)
khenaidoo6f2fbe32019-01-18 16:16:50 -0500414}
415
Scott Baker5f401472019-08-22 08:32:26 -0700416//GetDefaultLogLevel gets the log level used for packages that don't have specific loggers
Rohan Agrawal7f72f0c2020-01-14 12:05:51 +0000417func GetDefaultLogLevel() LogLevel {
418 return levelToLogLevel(cfg.Level.Level())
Scott Baker5f401472019-08-22 08:32:26 -0700419}
420
khenaidoo6f2fbe32019-01-18 16:16:50 -0500421//SetLogLevel sets the log level for the logger corresponding to the caller's package
Rohan Agrawal7f72f0c2020-01-14 12:05:51 +0000422func SetLogLevel(level LogLevel) error {
khenaidoo6f2fbe32019-01-18 16:16:50 -0500423 pkgName, _, _, _ := getCallerInfo()
424 if _, exist := cfgs[pkgName]; !exist {
Rohan Agrawal7f72f0c2020-01-14 12:05:51 +0000425 return fmt.Errorf("unregistered-package-%s", pkgName)
khenaidoo6f2fbe32019-01-18 16:16:50 -0500426 }
427 cfg := cfgs[pkgName]
428 setLevel(cfg, level)
khenaidoo7da372d2018-09-21 16:03:09 -0400429 return nil
430}
431
Scott Baker5f401472019-08-22 08:32:26 -0700432//SetDefaultLogLevel sets the log level used for packages that don't have specific loggers
Rohan Agrawal7f72f0c2020-01-14 12:05:51 +0000433func SetDefaultLogLevel(level LogLevel) {
Scott Baker5f401472019-08-22 08:32:26 -0700434 setLevel(cfg, level)
435}
436
khenaidoocfee5f42018-07-19 22:47:38 -0400437// CleanUp flushed any buffered log entries. Applications should take care to call
438// CleanUp before exiting.
439func CleanUp() error {
khenaidoob9203542018-09-17 22:56:37 -0400440 for _, logger := range loggers {
441 if logger != nil {
442 if logger.parent != nil {
443 if err := logger.parent.Sync(); err != nil {
444 return err
445 }
446 }
447 }
448 }
khenaidoocfee5f42018-07-19 22:47:38 -0400449 if defaultLogger != nil {
450 if defaultLogger.parent != nil {
451 if err := defaultLogger.parent.Sync(); err != nil {
452 return err
453 }
454 }
455 }
456 return nil
457}
458
khenaidoo7da372d2018-09-21 16:03:09 -0400459func getCallerInfo() (string, string, string, int) {
khenaidoo2c6f1672018-09-20 23:14:41 -0400460 // Since the caller of a log function is one stack frame before (in terms of stack higher level) the log.go
461 // filename, then first look for the last log.go filename and then grab the caller info one level higher.
462 maxLevel := 3
khenaidoo7da372d2018-09-21 16:03:09 -0400463 skiplevel := 3 // Level with the most empirical success to see the last log.go stack frame.
khenaidoo2c6f1672018-09-20 23:14:41 -0400464 pc := make([]uintptr, maxLevel)
465 n := runtime.Callers(skiplevel, pc)
khenaidoob9203542018-09-17 22:56:37 -0400466 packageName := ""
khenaidoo2c6f1672018-09-20 23:14:41 -0400467 funcName := ""
468 fileName := ""
469 var line int
470 if n == 0 {
471 return packageName, fileName, funcName, line
472 }
473 frames := runtime.CallersFrames(pc[:n])
474 var frame runtime.Frame
475 var foundFrame runtime.Frame
476 more := true
477 for more {
478 frame, more = frames.Next()
479 _, fileName = path.Split(frame.File)
480 if fileName != "log.go" {
481 foundFrame = frame // First frame after log.go in the frame stack
482 break
483 }
484 }
485 parts := strings.Split(foundFrame.Function, ".")
486 pl := len(parts)
487 if pl >= 2 {
488 funcName = parts[pl-1]
489 if parts[pl-2][0] == '(' {
490 packageName = strings.Join(parts[0:pl-2], ".")
491 } else {
492 packageName = strings.Join(parts[0:pl-1], ".")
493 }
khenaidoocfee5f42018-07-19 22:47:38 -0400494 }
495
khenaidoo2c6f1672018-09-20 23:14:41 -0400496 if strings.HasSuffix(packageName, ".init") {
khenaidoo7da372d2018-09-21 16:03:09 -0400497 packageName = strings.TrimSuffix(packageName, ".init")
khenaidoob9203542018-09-17 22:56:37 -0400498 }
499
500 if strings.HasSuffix(fileName, ".go") {
khenaidoo7da372d2018-09-21 16:03:09 -0400501 fileName = strings.TrimSuffix(fileName, ".go")
khenaidoob9203542018-09-17 22:56:37 -0400502 }
khenaidoo2c6f1672018-09-20 23:14:41 -0400503
504 return packageName, fileName, funcName, foundFrame.Line
khenaidoob9203542018-09-17 22:56:37 -0400505}
506
khenaidoo7da372d2018-09-21 16:03:09 -0400507func getPackageLevelSugaredLogger() *zp.SugaredLogger {
khenaidoob9203542018-09-17 22:56:37 -0400508 pkgName, fileName, funcName, line := getCallerInfo()
509 if _, exist := loggers[pkgName]; exist {
510 return loggers[pkgName].log.With("caller", fmt.Sprintf("%s.%s:%d", fileName, funcName, line))
511 }
512 return defaultLogger.log.With("caller", fmt.Sprintf("%s.%s:%d", fileName, funcName, line))
513}
khenaidoocfee5f42018-07-19 22:47:38 -0400514
khenaidoo7da372d2018-09-21 16:03:09 -0400515func getPackageLevelLogger() Logger {
516 pkgName, _, _, _ := getCallerInfo()
517 if _, exist := loggers[pkgName]; exist {
518 return loggers[pkgName]
519 }
520 return defaultLogger
521}
522
khenaidoocfee5f42018-07-19 22:47:38 -0400523func serializeMap(fields Fields) []interface{} {
524 data := make([]interface{}, len(fields)*2)
525 i := 0
526 for k, v := range fields {
527 data[i] = k
528 data[i+1] = v
529 i = i + 2
530 }
531 return data
532}
533
534// With returns a logger initialized with the key-value pairs
535func (l logger) With(keysAndValues Fields) Logger {
536 return logger{log: l.log.With(serializeMap(keysAndValues)...), parent: l.parent}
537}
538
539// Debug logs a message at level Debug on the standard logger.
540func (l logger) Debug(args ...interface{}) {
541 l.log.Debug(args...)
542}
543
544// Debugln logs a message at level Debug on the standard logger with a line feed. Default in any case.
545func (l logger) Debugln(args ...interface{}) {
546 l.log.Debug(args...)
547}
548
549// Debugw logs a message at level Debug on the standard logger.
550func (l logger) Debugf(format string, args ...interface{}) {
551 l.log.Debugf(format, args...)
552}
553
554// Debugw logs a message with some additional context. The variadic key-value
555// pairs are treated as they are in With.
556func (l logger) Debugw(msg string, keysAndValues Fields) {
557 l.log.Debugw(msg, serializeMap(keysAndValues)...)
558}
559
560// Info logs a message at level Info on the standard logger.
561func (l logger) Info(args ...interface{}) {
562 l.log.Info(args...)
563}
564
565// Infoln logs a message at level Info on the standard logger with a line feed. Default in any case.
566func (l logger) Infoln(args ...interface{}) {
567 l.log.Info(args...)
568 //msg := fmt.Sprintln(args...)
569 //l.sourced().Info(msg[:len(msg)-1])
570}
571
572// Infof logs a message at level Info on the standard logger.
573func (l logger) Infof(format string, args ...interface{}) {
574 l.log.Infof(format, args...)
575}
576
577// Infow logs a message with some additional context. The variadic key-value
578// pairs are treated as they are in With.
579func (l logger) Infow(msg string, keysAndValues Fields) {
580 l.log.Infow(msg, serializeMap(keysAndValues)...)
581}
582
583// Warn logs a message at level Warn on the standard logger.
584func (l logger) Warn(args ...interface{}) {
585 l.log.Warn(args...)
586}
587
588// Warnln logs a message at level Warn on the standard logger with a line feed. Default in any case.
589func (l logger) Warnln(args ...interface{}) {
590 l.log.Warn(args...)
591}
592
593// Warnf logs a message at level Warn on the standard logger.
594func (l logger) Warnf(format string, args ...interface{}) {
595 l.log.Warnf(format, args...)
596}
597
598// Warnw logs a message with some additional context. The variadic key-value
599// pairs are treated as they are in With.
600func (l logger) Warnw(msg string, keysAndValues Fields) {
601 l.log.Warnw(msg, serializeMap(keysAndValues)...)
602}
603
604// Error logs a message at level Error on the standard logger.
605func (l logger) Error(args ...interface{}) {
606 l.log.Error(args...)
607}
608
609// Errorln logs a message at level Error on the standard logger with a line feed. Default in any case.
610func (l logger) Errorln(args ...interface{}) {
611 l.log.Error(args...)
612}
613
614// Errorf logs a message at level Error on the standard logger.
615func (l logger) Errorf(format string, args ...interface{}) {
616 l.log.Errorf(format, args...)
617}
618
619// Errorw logs a message with some additional context. The variadic key-value
620// pairs are treated as they are in With.
621func (l logger) Errorw(msg string, keysAndValues Fields) {
622 l.log.Errorw(msg, serializeMap(keysAndValues)...)
623}
624
625// Fatal logs a message at level Fatal on the standard logger.
626func (l logger) Fatal(args ...interface{}) {
627 l.log.Fatal(args...)
628}
629
630// Fatalln logs a message at level Fatal on the standard logger with a line feed. Default in any case.
631func (l logger) Fatalln(args ...interface{}) {
632 l.log.Fatal(args...)
633}
634
635// Fatalf logs a message at level Fatal on the standard logger.
636func (l logger) Fatalf(format string, args ...interface{}) {
637 l.log.Fatalf(format, args...)
638}
639
640// Fatalw logs a message with some additional context. The variadic key-value
641// pairs are treated as they are in With.
642func (l logger) Fatalw(msg string, keysAndValues Fields) {
643 l.log.Fatalw(msg, serializeMap(keysAndValues)...)
644}
645
khenaidoo7da372d2018-09-21 16:03:09 -0400646// Warning logs a message at level Warn on the standard logger.
647func (l logger) Warning(args ...interface{}) {
648 l.log.Warn(args...)
649}
650
651// Warningln logs a message at level Warn on the standard logger with a line feed. Default in any case.
652func (l logger) Warningln(args ...interface{}) {
653 l.log.Warn(args...)
654}
655
656// Warningf logs a message at level Warn on the standard logger.
657func (l logger) Warningf(format string, args ...interface{}) {
658 l.log.Warnf(format, args...)
659}
660
661// V reports whether verbosity level l is at least the requested verbose level.
Rohan Agrawal7f72f0c2020-01-14 12:05:51 +0000662func (l logger) V(level LogLevel) bool {
663 return l.parent.Core().Enabled(logLevelToLevel(level))
khenaidoo7da372d2018-09-21 16:03:09 -0400664}
665
serkant.uluderya2ae470f2020-01-21 11:13:09 -0800666// GetLogLevel returns the current level of the logger
Rohan Agrawal7f72f0c2020-01-14 12:05:51 +0000667func (l logger) GetLogLevel() LogLevel {
668 return levelToLogLevel(cfgs[l.packageName].Level.Level())
serkant.uluderya2ae470f2020-01-21 11:13:09 -0800669}
670
khenaidoocfee5f42018-07-19 22:47:38 -0400671// With returns a logger initialized with the key-value pairs
672func With(keysAndValues Fields) Logger {
khenaidoo7da372d2018-09-21 16:03:09 -0400673 return logger{log: getPackageLevelSugaredLogger().With(serializeMap(keysAndValues)...), parent: defaultLogger.parent}
khenaidoocfee5f42018-07-19 22:47:38 -0400674}
675
676// Debug logs a message at level Debug on the standard logger.
677func Debug(args ...interface{}) {
khenaidoo7da372d2018-09-21 16:03:09 -0400678 getPackageLevelSugaredLogger().Debug(args...)
khenaidoocfee5f42018-07-19 22:47:38 -0400679}
680
681// Debugln logs a message at level Debug on the standard logger.
682func Debugln(args ...interface{}) {
khenaidoo7da372d2018-09-21 16:03:09 -0400683 getPackageLevelSugaredLogger().Debug(args...)
khenaidoocfee5f42018-07-19 22:47:38 -0400684}
685
686// Debugf logs a message at level Debug on the standard logger.
687func Debugf(format string, args ...interface{}) {
khenaidoo7da372d2018-09-21 16:03:09 -0400688 getPackageLevelSugaredLogger().Debugf(format, args...)
khenaidoocfee5f42018-07-19 22:47:38 -0400689}
690
691// Debugw logs a message with some additional context. The variadic key-value
692// pairs are treated as they are in With.
693func Debugw(msg string, keysAndValues Fields) {
khenaidoo7da372d2018-09-21 16:03:09 -0400694 getPackageLevelSugaredLogger().Debugw(msg, serializeMap(keysAndValues)...)
khenaidoocfee5f42018-07-19 22:47:38 -0400695}
696
697// Info logs a message at level Info on the standard logger.
698func Info(args ...interface{}) {
khenaidoo7da372d2018-09-21 16:03:09 -0400699 getPackageLevelSugaredLogger().Info(args...)
khenaidoocfee5f42018-07-19 22:47:38 -0400700}
701
702// Infoln logs a message at level Info on the standard logger.
703func Infoln(args ...interface{}) {
khenaidoo7da372d2018-09-21 16:03:09 -0400704 getPackageLevelSugaredLogger().Info(args...)
khenaidoocfee5f42018-07-19 22:47:38 -0400705}
706
707// Infof logs a message at level Info on the standard logger.
708func Infof(format string, args ...interface{}) {
khenaidoo7da372d2018-09-21 16:03:09 -0400709 getPackageLevelSugaredLogger().Infof(format, args...)
khenaidoocfee5f42018-07-19 22:47:38 -0400710}
711
712//Infow logs a message with some additional context. The variadic key-value
713//pairs are treated as they are in With.
714func Infow(msg string, keysAndValues Fields) {
khenaidoo7da372d2018-09-21 16:03:09 -0400715 getPackageLevelSugaredLogger().Infow(msg, serializeMap(keysAndValues)...)
khenaidoocfee5f42018-07-19 22:47:38 -0400716}
717
718// Warn logs a message at level Warn on the standard logger.
719func Warn(args ...interface{}) {
khenaidoo7da372d2018-09-21 16:03:09 -0400720 getPackageLevelSugaredLogger().Warn(args...)
khenaidoocfee5f42018-07-19 22:47:38 -0400721}
722
723// Warnln logs a message at level Warn on the standard logger.
724func Warnln(args ...interface{}) {
khenaidoo7da372d2018-09-21 16:03:09 -0400725 getPackageLevelSugaredLogger().Warn(args...)
khenaidoocfee5f42018-07-19 22:47:38 -0400726}
727
728// Warnf logs a message at level Warn on the standard logger.
729func Warnf(format string, args ...interface{}) {
khenaidoo7da372d2018-09-21 16:03:09 -0400730 getPackageLevelSugaredLogger().Warnf(format, args...)
khenaidoocfee5f42018-07-19 22:47:38 -0400731}
732
733// Warnw logs a message with some additional context. The variadic key-value
734// pairs are treated as they are in With.
735func Warnw(msg string, keysAndValues Fields) {
khenaidoo7da372d2018-09-21 16:03:09 -0400736 getPackageLevelSugaredLogger().Warnw(msg, serializeMap(keysAndValues)...)
khenaidoocfee5f42018-07-19 22:47:38 -0400737}
738
739// Error logs a message at level Error on the standard logger.
740func Error(args ...interface{}) {
khenaidoo7da372d2018-09-21 16:03:09 -0400741 getPackageLevelSugaredLogger().Error(args...)
khenaidoocfee5f42018-07-19 22:47:38 -0400742}
743
744// Errorln logs a message at level Error on the standard logger.
745func Errorln(args ...interface{}) {
khenaidoo7da372d2018-09-21 16:03:09 -0400746 getPackageLevelSugaredLogger().Error(args...)
khenaidoocfee5f42018-07-19 22:47:38 -0400747}
748
749// Errorf logs a message at level Error on the standard logger.
750func Errorf(format string, args ...interface{}) {
khenaidoo7da372d2018-09-21 16:03:09 -0400751 getPackageLevelSugaredLogger().Errorf(format, args...)
khenaidoocfee5f42018-07-19 22:47:38 -0400752}
753
754// Errorw logs a message with some additional context. The variadic key-value
755// pairs are treated as they are in With.
756func Errorw(msg string, keysAndValues Fields) {
khenaidoo7da372d2018-09-21 16:03:09 -0400757 getPackageLevelSugaredLogger().Errorw(msg, serializeMap(keysAndValues)...)
khenaidoocfee5f42018-07-19 22:47:38 -0400758}
759
760// Fatal logs a message at level Fatal on the standard logger.
761func Fatal(args ...interface{}) {
khenaidoo7da372d2018-09-21 16:03:09 -0400762 getPackageLevelSugaredLogger().Fatal(args...)
khenaidoocfee5f42018-07-19 22:47:38 -0400763}
764
765// Fatalln logs a message at level Fatal on the standard logger.
766func Fatalln(args ...interface{}) {
khenaidoo7da372d2018-09-21 16:03:09 -0400767 getPackageLevelSugaredLogger().Fatal(args...)
khenaidoocfee5f42018-07-19 22:47:38 -0400768}
769
770// Fatalf logs a message at level Fatal on the standard logger.
771func Fatalf(format string, args ...interface{}) {
khenaidoo7da372d2018-09-21 16:03:09 -0400772 getPackageLevelSugaredLogger().Fatalf(format, args...)
khenaidoocfee5f42018-07-19 22:47:38 -0400773}
774
775// Fatalw logs a message with some additional context. The variadic key-value
776// pairs are treated as they are in With.
777func Fatalw(msg string, keysAndValues Fields) {
khenaidoo7da372d2018-09-21 16:03:09 -0400778 getPackageLevelSugaredLogger().Fatalw(msg, serializeMap(keysAndValues)...)
779}
780
781// Warning logs a message at level Warn on the standard logger.
782func Warning(args ...interface{}) {
783 getPackageLevelSugaredLogger().Warn(args...)
784}
785
786// Warningln logs a message at level Warn on the standard logger.
787func Warningln(args ...interface{}) {
788 getPackageLevelSugaredLogger().Warn(args...)
789}
790
791// Warningf logs a message at level Warn on the standard logger.
792func Warningf(format string, args ...interface{}) {
793 getPackageLevelSugaredLogger().Warnf(format, args...)
794}
795
796// V reports whether verbosity level l is at least the requested verbose level.
Rohan Agrawal7f72f0c2020-01-14 12:05:51 +0000797func V(level LogLevel) bool {
khenaidoo7da372d2018-09-21 16:03:09 -0400798 return getPackageLevelLogger().V(level)
khenaidoocfee5f42018-07-19 22:47:38 -0400799}
serkant.uluderya2ae470f2020-01-21 11:13:09 -0800800
801//GetLogLevel returns the log level of the invoking package
Rohan Agrawal7f72f0c2020-01-14 12:05:51 +0000802func GetLogLevel() LogLevel {
serkant.uluderya2ae470f2020-01-21 11:13:09 -0800803 return getPackageLevelLogger().GetLogLevel()
804}