blob: 026c6c0bad8f87f32ac118ab353d434c51a802d5 [file] [log] [blame]
Scott Baker2c1c4822019-10-16 11:02:41 -07001/*
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 (
44 "errors"
45 "fmt"
46 zp "go.uber.org/zap"
47 zc "go.uber.org/zap/zapcore"
48 "path"
49 "runtime"
50 "strings"
51)
52
53const (
54 // DebugLevel logs a message at debug level
55 DebugLevel = iota
56 // InfoLevel logs a message at info level
57 InfoLevel
58 // WarnLevel logs a message at warning level
59 WarnLevel
60 // ErrorLevel logs a message at error level
61 ErrorLevel
Scott Baker2c1c4822019-10-16 11:02:41 -070062 // FatalLevel logs a message, then calls os.Exit(1).
63 FatalLevel
64)
65
66// CONSOLE formats the log for the console, mostly used during development
67const CONSOLE = "console"
68
69// JSON formats the log using json format, mostly used by an automated logging system consumption
70const JSON = "json"
71
72// Logger represents an abstract logging interface. Any logging implementation used
73// will need to abide by this interface
74type Logger interface {
75 Debug(...interface{})
76 Debugln(...interface{})
77 Debugf(string, ...interface{})
78 Debugw(string, Fields)
79
80 Info(...interface{})
81 Infoln(...interface{})
82 Infof(string, ...interface{})
83 Infow(string, Fields)
84
85 Warn(...interface{})
86 Warnln(...interface{})
87 Warnf(string, ...interface{})
88 Warnw(string, Fields)
89
90 Error(...interface{})
91 Errorln(...interface{})
92 Errorf(string, ...interface{})
93 Errorw(string, Fields)
94
95 Fatal(...interface{})
96 Fatalln(...interface{})
97 Fatalf(string, ...interface{})
98 Fatalw(string, Fields)
99
100 With(Fields) Logger
101
102 // The following are added to be able to use this logger as a gRPC LoggerV2 if needed
103 //
104 Warning(...interface{})
105 Warningln(...interface{})
106 Warningf(string, ...interface{})
107
108 // V reports whether verbosity level l is at least the requested verbose level.
109 V(l int) bool
110}
111
112// Fields is used as key-value pairs for structured logging
113type Fields map[string]interface{}
114
115var defaultLogger *logger
116var cfg zp.Config
117
118var loggers map[string]*logger
119var cfgs map[string]zp.Config
120
121type logger struct {
122 log *zp.SugaredLogger
123 parent *zp.Logger
124}
125
126func intToAtomicLevel(l int) zp.AtomicLevel {
127 switch l {
128 case DebugLevel:
129 return zp.NewAtomicLevelAt(zc.DebugLevel)
130 case InfoLevel:
131 return zp.NewAtomicLevelAt(zc.InfoLevel)
132 case WarnLevel:
133 return zp.NewAtomicLevelAt(zc.WarnLevel)
134 case ErrorLevel:
135 return zp.NewAtomicLevelAt(zc.ErrorLevel)
Scott Baker2c1c4822019-10-16 11:02:41 -0700136 case FatalLevel:
137 return zp.NewAtomicLevelAt(zc.FatalLevel)
138 }
139 return zp.NewAtomicLevelAt(zc.ErrorLevel)
140}
141
142func intToLevel(l int) zc.Level {
143 switch l {
144 case DebugLevel:
145 return zc.DebugLevel
146 case InfoLevel:
147 return zc.InfoLevel
148 case WarnLevel:
149 return zc.WarnLevel
150 case ErrorLevel:
151 return zc.ErrorLevel
Scott Baker2c1c4822019-10-16 11:02:41 -0700152 case FatalLevel:
153 return zc.FatalLevel
154 }
155 return zc.ErrorLevel
156}
157
158func levelToInt(l zc.Level) int {
159 switch l {
160 case zc.DebugLevel:
161 return DebugLevel
162 case zc.InfoLevel:
163 return InfoLevel
164 case zc.WarnLevel:
165 return WarnLevel
166 case zc.ErrorLevel:
167 return ErrorLevel
Rohan Agrawal6a99a452020-01-14 07:58:25 +0000168 case zc.FatalLevel:
169 return FatalLevel
170 }
171 return ErrorLevel
172}
173
174func StringToInt(l string) int {
175 switch l {
176 case "DEBUG":
177 return DebugLevel
178 case "INFO":
179 return InfoLevel
180 case "WARN":
181 return WarnLevel
182 case "ERROR":
183 return ErrorLevel
184 case "FATAL":
Scott Baker2c1c4822019-10-16 11:02:41 -0700185 return FatalLevel
186 }
187 return ErrorLevel
188}
189
190func getDefaultConfig(outputType string, level int, defaultFields Fields) zp.Config {
191 return zp.Config{
192 Level: intToAtomicLevel(level),
193 Encoding: outputType,
194 Development: true,
195 OutputPaths: []string{"stdout"},
196 ErrorOutputPaths: []string{"stderr"},
197 InitialFields: defaultFields,
198 EncoderConfig: zc.EncoderConfig{
199 LevelKey: "level",
200 MessageKey: "msg",
201 TimeKey: "ts",
202 StacktraceKey: "stacktrace",
203 LineEnding: zc.DefaultLineEnding,
204 EncodeLevel: zc.LowercaseLevelEncoder,
205 EncodeTime: zc.ISO8601TimeEncoder,
206 EncodeDuration: zc.SecondsDurationEncoder,
207 EncodeCaller: zc.ShortCallerEncoder,
208 },
209 }
210}
211
212// SetLogger needs to be invoked before the logger API can be invoked. This function
213// initialize the default logger (zap's sugaredlogger)
214func SetDefaultLogger(outputType string, level int, defaultFields Fields) (Logger, error) {
215 // Build a custom config using zap
216 cfg = getDefaultConfig(outputType, level, defaultFields)
217
218 l, err := cfg.Build()
219 if err != nil {
220 return nil, err
221 }
222
223 defaultLogger = &logger{
224 log: l.Sugar(),
225 parent: l,
226 }
227
228 return defaultLogger, nil
229}
230
231// AddPackage registers a package to the log map. Each package gets its own logger which allows
232// its config (loglevel) to be changed dynamically without interacting with the other packages.
233// outputType is JSON, level is the lowest level log to output with this logger and defaultFields is a map of
234// key-value pairs to always add to the output.
235// Note: AddPackage also returns a reference to the actual logger. If a calling package uses this reference directly
236//instead of using the publicly available functions in this log package then a number of functionalities will not
237// be available to it, notably log tracing with filename.functionname.linenumber annotation.
238//
239// pkgNames parameter should be used for testing only as this function detects the caller's package.
240func AddPackage(outputType string, level int, defaultFields Fields, pkgNames ...string) (Logger, error) {
241 if cfgs == nil {
242 cfgs = make(map[string]zp.Config)
243 }
244 if loggers == nil {
245 loggers = make(map[string]*logger)
246 }
247
248 var pkgName string
249 for _, name := range pkgNames {
250 pkgName = name
251 break
252 }
253 if pkgName == "" {
254 pkgName, _, _, _ = getCallerInfo()
255 }
256
257 if _, exist := loggers[pkgName]; exist {
258 return loggers[pkgName], nil
259 }
260
261 cfgs[pkgName] = getDefaultConfig(outputType, level, defaultFields)
262
263 l, err := cfgs[pkgName].Build()
264 if err != nil {
265 return nil, err
266 }
267
268 loggers[pkgName] = &logger{
269 log: l.Sugar(),
270 parent: l,
271 }
272 return loggers[pkgName], nil
273}
274
275//UpdateAllLoggers create new loggers for all registered pacakges with the defaultFields.
276func UpdateAllLoggers(defaultFields Fields) error {
277 for pkgName, cfg := range cfgs {
278 for k, v := range defaultFields {
279 if cfg.InitialFields == nil {
280 cfg.InitialFields = make(map[string]interface{})
281 }
282 cfg.InitialFields[k] = v
283 }
284 l, err := cfg.Build()
285 if err != nil {
286 return err
287 }
288
289 loggers[pkgName] = &logger{
290 log: l.Sugar(),
291 parent: l,
292 }
293 }
294 return nil
295}
296
297// Return a list of all packages that have individually-configured loggers
298func GetPackageNames() []string {
299 i := 0
300 keys := make([]string, len(loggers))
301 for k := range loggers {
302 keys[i] = k
303 i++
304 }
305 return keys
306}
307
308// UpdateLogger deletes the logger associated with a caller's package and creates a new logger with the
309// defaultFields. If a calling package is holding on to a Logger reference obtained from AddPackage invocation, then
310// that package needs to invoke UpdateLogger if it needs to make changes to the default fields and obtain a new logger
311// reference
312func UpdateLogger(defaultFields Fields) (Logger, error) {
313 pkgName, _, _, _ := getCallerInfo()
314 if _, exist := loggers[pkgName]; !exist {
315 return nil, errors.New(fmt.Sprintf("package-%s-not-registered", pkgName))
316 }
317
318 // Build a new logger
319 if _, exist := cfgs[pkgName]; !exist {
320 return nil, errors.New(fmt.Sprintf("config-%s-not-registered", pkgName))
321 }
322
323 cfg := cfgs[pkgName]
324 for k, v := range defaultFields {
325 if cfg.InitialFields == nil {
326 cfg.InitialFields = make(map[string]interface{})
327 }
328 cfg.InitialFields[k] = v
329 }
330 l, err := cfg.Build()
331 if err != nil {
332 return nil, err
333 }
334
335 // Set the logger
336 loggers[pkgName] = &logger{
337 log: l.Sugar(),
338 parent: l,
339 }
340 return loggers[pkgName], nil
341}
342
343func setLevel(cfg zp.Config, level int) {
344 switch level {
345 case DebugLevel:
346 cfg.Level.SetLevel(zc.DebugLevel)
347 case InfoLevel:
348 cfg.Level.SetLevel(zc.InfoLevel)
349 case WarnLevel:
350 cfg.Level.SetLevel(zc.WarnLevel)
351 case ErrorLevel:
352 cfg.Level.SetLevel(zc.ErrorLevel)
Scott Baker2c1c4822019-10-16 11:02:41 -0700353 case FatalLevel:
354 cfg.Level.SetLevel(zc.FatalLevel)
355 default:
356 cfg.Level.SetLevel(zc.ErrorLevel)
357 }
358}
359
360//SetPackageLogLevel dynamically sets the log level of a given package to level. This is typically invoked at an
361// application level during debugging
362func SetPackageLogLevel(packageName string, level int) {
363 // Get proper config
364 if cfg, ok := cfgs[packageName]; ok {
365 setLevel(cfg, level)
366 }
367}
368
369//SetAllLogLevel sets the log level of all registered packages to level
370func SetAllLogLevel(level int) {
371 // Get proper config
372 for _, cfg := range cfgs {
373 setLevel(cfg, level)
374 }
375}
376
377//GetPackageLogLevel returns the current log level of a package.
378func GetPackageLogLevel(packageName ...string) (int, error) {
379 var name string
380 if len(packageName) == 1 {
381 name = packageName[0]
382 } else {
383 name, _, _, _ = getCallerInfo()
384 }
385 if cfg, ok := cfgs[name]; ok {
386 return levelToInt(cfg.Level.Level()), nil
387 }
388 return 0, errors.New(fmt.Sprintf("unknown-package-%s", name))
389}
390
391//GetDefaultLogLevel gets the log level used for packages that don't have specific loggers
392func GetDefaultLogLevel() int {
393 return levelToInt(cfg.Level.Level())
394}
395
396//SetLogLevel sets the log level for the logger corresponding to the caller's package
397func SetLogLevel(level int) error {
398 pkgName, _, _, _ := getCallerInfo()
399 if _, exist := cfgs[pkgName]; !exist {
400 return errors.New(fmt.Sprintf("unregistered-package-%s", pkgName))
401 }
402 cfg := cfgs[pkgName]
403 setLevel(cfg, level)
404 return nil
405}
406
407//SetDefaultLogLevel sets the log level used for packages that don't have specific loggers
408func SetDefaultLogLevel(level int) {
409 setLevel(cfg, level)
410}
411
412// CleanUp flushed any buffered log entries. Applications should take care to call
413// CleanUp before exiting.
414func CleanUp() error {
415 for _, logger := range loggers {
416 if logger != nil {
417 if logger.parent != nil {
418 if err := logger.parent.Sync(); err != nil {
419 return err
420 }
421 }
422 }
423 }
424 if defaultLogger != nil {
425 if defaultLogger.parent != nil {
426 if err := defaultLogger.parent.Sync(); err != nil {
427 return err
428 }
429 }
430 }
431 return nil
432}
433
434func getCallerInfo() (string, string, string, int) {
435 // Since the caller of a log function is one stack frame before (in terms of stack higher level) the log.go
436 // filename, then first look for the last log.go filename and then grab the caller info one level higher.
437 maxLevel := 3
438 skiplevel := 3 // Level with the most empirical success to see the last log.go stack frame.
439 pc := make([]uintptr, maxLevel)
440 n := runtime.Callers(skiplevel, pc)
441 packageName := ""
442 funcName := ""
443 fileName := ""
444 var line int
445 if n == 0 {
446 return packageName, fileName, funcName, line
447 }
448 frames := runtime.CallersFrames(pc[:n])
449 var frame runtime.Frame
450 var foundFrame runtime.Frame
451 more := true
452 for more {
453 frame, more = frames.Next()
454 _, fileName = path.Split(frame.File)
455 if fileName != "log.go" {
456 foundFrame = frame // First frame after log.go in the frame stack
457 break
458 }
459 }
460 parts := strings.Split(foundFrame.Function, ".")
461 pl := len(parts)
462 if pl >= 2 {
463 funcName = parts[pl-1]
464 if parts[pl-2][0] == '(' {
465 packageName = strings.Join(parts[0:pl-2], ".")
466 } else {
467 packageName = strings.Join(parts[0:pl-1], ".")
468 }
469 }
470
471 if strings.HasSuffix(packageName, ".init") {
472 packageName = strings.TrimSuffix(packageName, ".init")
473 }
474
475 if strings.HasSuffix(fileName, ".go") {
476 fileName = strings.TrimSuffix(fileName, ".go")
477 }
478
479 return packageName, fileName, funcName, foundFrame.Line
480}
481
482func getPackageLevelSugaredLogger() *zp.SugaredLogger {
483 pkgName, fileName, funcName, line := getCallerInfo()
484 if _, exist := loggers[pkgName]; exist {
485 return loggers[pkgName].log.With("caller", fmt.Sprintf("%s.%s:%d", fileName, funcName, line))
486 }
487 return defaultLogger.log.With("caller", fmt.Sprintf("%s.%s:%d", fileName, funcName, line))
488}
489
490func getPackageLevelLogger() Logger {
491 pkgName, _, _, _ := getCallerInfo()
492 if _, exist := loggers[pkgName]; exist {
493 return loggers[pkgName]
494 }
495 return defaultLogger
496}
497
498func serializeMap(fields Fields) []interface{} {
499 data := make([]interface{}, len(fields)*2)
500 i := 0
501 for k, v := range fields {
502 data[i] = k
503 data[i+1] = v
504 i = i + 2
505 }
506 return data
507}
508
509// With returns a logger initialized with the key-value pairs
510func (l logger) With(keysAndValues Fields) Logger {
511 return logger{log: l.log.With(serializeMap(keysAndValues)...), parent: l.parent}
512}
513
514// Debug logs a message at level Debug on the standard logger.
515func (l logger) Debug(args ...interface{}) {
516 l.log.Debug(args...)
517}
518
519// Debugln logs a message at level Debug on the standard logger with a line feed. Default in any case.
520func (l logger) Debugln(args ...interface{}) {
521 l.log.Debug(args...)
522}
523
524// Debugw logs a message at level Debug on the standard logger.
525func (l logger) Debugf(format string, args ...interface{}) {
526 l.log.Debugf(format, args...)
527}
528
529// Debugw logs a message with some additional context. The variadic key-value
530// pairs are treated as they are in With.
531func (l logger) Debugw(msg string, keysAndValues Fields) {
532 l.log.Debugw(msg, serializeMap(keysAndValues)...)
533}
534
535// Info logs a message at level Info on the standard logger.
536func (l logger) Info(args ...interface{}) {
537 l.log.Info(args...)
538}
539
540// Infoln logs a message at level Info on the standard logger with a line feed. Default in any case.
541func (l logger) Infoln(args ...interface{}) {
542 l.log.Info(args...)
543 //msg := fmt.Sprintln(args...)
544 //l.sourced().Info(msg[:len(msg)-1])
545}
546
547// Infof logs a message at level Info on the standard logger.
548func (l logger) Infof(format string, args ...interface{}) {
549 l.log.Infof(format, args...)
550}
551
552// Infow logs a message with some additional context. The variadic key-value
553// pairs are treated as they are in With.
554func (l logger) Infow(msg string, keysAndValues Fields) {
555 l.log.Infow(msg, serializeMap(keysAndValues)...)
556}
557
558// Warn logs a message at level Warn on the standard logger.
559func (l logger) Warn(args ...interface{}) {
560 l.log.Warn(args...)
561}
562
563// Warnln logs a message at level Warn on the standard logger with a line feed. Default in any case.
564func (l logger) Warnln(args ...interface{}) {
565 l.log.Warn(args...)
566}
567
568// Warnf logs a message at level Warn on the standard logger.
569func (l logger) Warnf(format string, args ...interface{}) {
570 l.log.Warnf(format, args...)
571}
572
573// Warnw logs a message with some additional context. The variadic key-value
574// pairs are treated as they are in With.
575func (l logger) Warnw(msg string, keysAndValues Fields) {
576 l.log.Warnw(msg, serializeMap(keysAndValues)...)
577}
578
579// Error logs a message at level Error on the standard logger.
580func (l logger) Error(args ...interface{}) {
581 l.log.Error(args...)
582}
583
584// Errorln logs a message at level Error on the standard logger with a line feed. Default in any case.
585func (l logger) Errorln(args ...interface{}) {
586 l.log.Error(args...)
587}
588
589// Errorf logs a message at level Error on the standard logger.
590func (l logger) Errorf(format string, args ...interface{}) {
591 l.log.Errorf(format, args...)
592}
593
594// Errorw logs a message with some additional context. The variadic key-value
595// pairs are treated as they are in With.
596func (l logger) Errorw(msg string, keysAndValues Fields) {
597 l.log.Errorw(msg, serializeMap(keysAndValues)...)
598}
599
600// Fatal logs a message at level Fatal on the standard logger.
601func (l logger) Fatal(args ...interface{}) {
602 l.log.Fatal(args...)
603}
604
605// Fatalln logs a message at level Fatal on the standard logger with a line feed. Default in any case.
606func (l logger) Fatalln(args ...interface{}) {
607 l.log.Fatal(args...)
608}
609
610// Fatalf logs a message at level Fatal on the standard logger.
611func (l logger) Fatalf(format string, args ...interface{}) {
612 l.log.Fatalf(format, args...)
613}
614
615// Fatalw logs a message with some additional context. The variadic key-value
616// pairs are treated as they are in With.
617func (l logger) Fatalw(msg string, keysAndValues Fields) {
618 l.log.Fatalw(msg, serializeMap(keysAndValues)...)
619}
620
621// Warning logs a message at level Warn on the standard logger.
622func (l logger) Warning(args ...interface{}) {
623 l.log.Warn(args...)
624}
625
626// Warningln logs a message at level Warn on the standard logger with a line feed. Default in any case.
627func (l logger) Warningln(args ...interface{}) {
628 l.log.Warn(args...)
629}
630
631// Warningf logs a message at level Warn on the standard logger.
632func (l logger) Warningf(format string, args ...interface{}) {
633 l.log.Warnf(format, args...)
634}
635
636// V reports whether verbosity level l is at least the requested verbose level.
637func (l logger) V(level int) bool {
638 return l.parent.Core().Enabled(intToLevel(level))
639}
640
641// With returns a logger initialized with the key-value pairs
642func With(keysAndValues Fields) Logger {
643 return logger{log: getPackageLevelSugaredLogger().With(serializeMap(keysAndValues)...), parent: defaultLogger.parent}
644}
645
646// Debug logs a message at level Debug on the standard logger.
647func Debug(args ...interface{}) {
648 getPackageLevelSugaredLogger().Debug(args...)
649}
650
651// Debugln logs a message at level Debug on the standard logger.
652func Debugln(args ...interface{}) {
653 getPackageLevelSugaredLogger().Debug(args...)
654}
655
656// Debugf logs a message at level Debug on the standard logger.
657func Debugf(format string, args ...interface{}) {
658 getPackageLevelSugaredLogger().Debugf(format, args...)
659}
660
661// Debugw logs a message with some additional context. The variadic key-value
662// pairs are treated as they are in With.
663func Debugw(msg string, keysAndValues Fields) {
664 getPackageLevelSugaredLogger().Debugw(msg, serializeMap(keysAndValues)...)
665}
666
667// Info logs a message at level Info on the standard logger.
668func Info(args ...interface{}) {
669 getPackageLevelSugaredLogger().Info(args...)
670}
671
672// Infoln logs a message at level Info on the standard logger.
673func Infoln(args ...interface{}) {
674 getPackageLevelSugaredLogger().Info(args...)
675}
676
677// Infof logs a message at level Info on the standard logger.
678func Infof(format string, args ...interface{}) {
679 getPackageLevelSugaredLogger().Infof(format, args...)
680}
681
682//Infow logs a message with some additional context. The variadic key-value
683//pairs are treated as they are in With.
684func Infow(msg string, keysAndValues Fields) {
685 getPackageLevelSugaredLogger().Infow(msg, serializeMap(keysAndValues)...)
686}
687
688// Warn logs a message at level Warn on the standard logger.
689func Warn(args ...interface{}) {
690 getPackageLevelSugaredLogger().Warn(args...)
691}
692
693// Warnln logs a message at level Warn on the standard logger.
694func Warnln(args ...interface{}) {
695 getPackageLevelSugaredLogger().Warn(args...)
696}
697
698// Warnf logs a message at level Warn on the standard logger.
699func Warnf(format string, args ...interface{}) {
700 getPackageLevelSugaredLogger().Warnf(format, args...)
701}
702
703// Warnw logs a message with some additional context. The variadic key-value
704// pairs are treated as they are in With.
705func Warnw(msg string, keysAndValues Fields) {
706 getPackageLevelSugaredLogger().Warnw(msg, serializeMap(keysAndValues)...)
707}
708
709// Error logs a message at level Error on the standard logger.
710func Error(args ...interface{}) {
711 getPackageLevelSugaredLogger().Error(args...)
712}
713
714// Errorln logs a message at level Error on the standard logger.
715func Errorln(args ...interface{}) {
716 getPackageLevelSugaredLogger().Error(args...)
717}
718
719// Errorf logs a message at level Error on the standard logger.
720func Errorf(format string, args ...interface{}) {
721 getPackageLevelSugaredLogger().Errorf(format, args...)
722}
723
724// Errorw logs a message with some additional context. The variadic key-value
725// pairs are treated as they are in With.
726func Errorw(msg string, keysAndValues Fields) {
727 getPackageLevelSugaredLogger().Errorw(msg, serializeMap(keysAndValues)...)
728}
729
730// Fatal logs a message at level Fatal on the standard logger.
731func Fatal(args ...interface{}) {
732 getPackageLevelSugaredLogger().Fatal(args...)
733}
734
735// Fatalln logs a message at level Fatal on the standard logger.
736func Fatalln(args ...interface{}) {
737 getPackageLevelSugaredLogger().Fatal(args...)
738}
739
740// Fatalf logs a message at level Fatal on the standard logger.
741func Fatalf(format string, args ...interface{}) {
742 getPackageLevelSugaredLogger().Fatalf(format, args...)
743}
744
745// Fatalw logs a message with some additional context. The variadic key-value
746// pairs are treated as they are in With.
747func Fatalw(msg string, keysAndValues Fields) {
748 getPackageLevelSugaredLogger().Fatalw(msg, serializeMap(keysAndValues)...)
749}
750
751// Warning logs a message at level Warn on the standard logger.
752func Warning(args ...interface{}) {
753 getPackageLevelSugaredLogger().Warn(args...)
754}
755
756// Warningln logs a message at level Warn on the standard logger.
757func Warningln(args ...interface{}) {
758 getPackageLevelSugaredLogger().Warn(args...)
759}
760
761// Warningf logs a message at level Warn on the standard logger.
762func Warningf(format string, args ...interface{}) {
763 getPackageLevelSugaredLogger().Warnf(format, args...)
764}
765
766// V reports whether verbosity level l is at least the requested verbose level.
767func V(level int) bool {
768 return getPackageLevelLogger().V(level)
769}