Source File
sugar.go
Belonging Package
go.uber.org/zap
// Copyright (c) 2016 Uber Technologies, Inc.//// Permission is hereby granted, free of charge, to any person obtaining a copy// of this software and associated documentation files (the "Software"), to deal// in the Software without restriction, including without limitation the rights// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell// copies of the Software, and to permit persons to whom the Software is// furnished to do so, subject to the following conditions://// The above copyright notice and this permission notice shall be included in// all copies or substantial portions of the Software.//// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN// THE SOFTWARE.package zapimport ()const (_oddNumberErrMsg = "Ignored key without a value."_nonStringKeyErrMsg = "Ignored key-value pairs with non-string keys."_multipleErrMsg = "Multiple errors without a key.")// A SugaredLogger wraps the base Logger functionality in a slower, but less// verbose, API. Any Logger can be converted to a SugaredLogger with its Sugar// method.//// Unlike the Logger, the SugaredLogger doesn't insist on structured logging.// For each log level, it exposes four methods://// - methods named after the log level for log.Print-style logging// - methods ending in "w" for loosely-typed structured logging// - methods ending in "f" for log.Printf-style logging// - methods ending in "ln" for log.Println-style logging//// For example, the methods for InfoLevel are://// Info(...any) Print-style logging// Infow(...any) Structured logging (read as "info with")// Infof(string, ...any) Printf-style logging// Infoln(...any) Println-style loggingtype SugaredLogger struct {base *Logger}// Desugar unwraps a SugaredLogger, exposing the original Logger. Desugaring// is quite inexpensive, so it's reasonable for a single application to use// both Loggers and SugaredLoggers, converting between them on the boundaries// of performance-sensitive code.func ( *SugaredLogger) () *Logger {:= .base.clone().callerSkip -= 2return}// Named adds a sub-scope to the logger's name. See Logger.Named for details.func ( *SugaredLogger) ( string) *SugaredLogger {return &SugaredLogger{base: .base.Named()}}// WithOptions clones the current SugaredLogger, applies the supplied Options,// and returns the result. It's safe to use concurrently.func ( *SugaredLogger) ( ...Option) *SugaredLogger {:= .base.clone()for , := range {.apply()}return &SugaredLogger{base: }}// With adds a variadic number of fields to the logging context. It accepts a// mix of strongly-typed Field objects and loosely-typed key-value pairs. When// processing pairs, the first element of the pair is used as the field key// and the second as the field value.//// For example,//// sugaredLogger.With(// "hello", "world",// "failure", errors.New("oh no"),// Stack(),// "count", 42,// "user", User{Name: "alice"},// )//// is the equivalent of//// unsugared.With(// String("hello", "world"),// String("failure", "oh no"),// Stack(),// Int("count", 42),// Object("user", User{Name: "alice"}),// )//// Note that the keys in key-value pairs should be strings. In development,// passing a non-string key panics. In production, the logger is more// forgiving: a separate error is logged, but the key-value pair is skipped// and execution continues. Passing an orphaned key triggers similar behavior:// panics in development and errors in production.func ( *SugaredLogger) ( ...interface{}) *SugaredLogger {return &SugaredLogger{base: .base.With(.sweetenFields()...)}}// WithLazy adds a variadic number of fields to the logging context lazily.// The fields are evaluated only if the logger is further chained with [With]// or is written to with any of the log level methods.// Until that occurs, the logger may retain references to objects inside the fields,// and logging will reflect the state of an object at the time of logging,// not the time of WithLazy().//// Similar to [With], fields added to the child don't affect the parent,// and vice versa. Also, the keys in key-value pairs should be strings. In development,// passing a non-string key panics, while in production it logs an error and skips the pair.// Passing an orphaned key has the same behavior.func ( *SugaredLogger) ( ...interface{}) *SugaredLogger {return &SugaredLogger{base: .base.WithLazy(.sweetenFields()...)}}// Level reports the minimum enabled level for this logger.//// For NopLoggers, this is [zapcore.InvalidLevel].func ( *SugaredLogger) () zapcore.Level {return zapcore.LevelOf(.base.core)}// Log logs the provided arguments at provided level.// Spaces are added between arguments when neither is a string.func ( *SugaredLogger) ( zapcore.Level, ...interface{}) {.log(, "", , nil)}// Debug logs the provided arguments at [DebugLevel].// Spaces are added between arguments when neither is a string.func ( *SugaredLogger) ( ...interface{}) {.log(DebugLevel, "", , nil)}// Info logs the provided arguments at [InfoLevel].// Spaces are added between arguments when neither is a string.func ( *SugaredLogger) ( ...interface{}) {.log(InfoLevel, "", , nil)}// Warn logs the provided arguments at [WarnLevel].// Spaces are added between arguments when neither is a string.func ( *SugaredLogger) ( ...interface{}) {.log(WarnLevel, "", , nil)}// Error logs the provided arguments at [ErrorLevel].// Spaces are added between arguments when neither is a string.func ( *SugaredLogger) ( ...interface{}) {.log(ErrorLevel, "", , nil)}// DPanic logs the provided arguments at [DPanicLevel].// In development, the logger then panics. (See [DPanicLevel] for details.)// Spaces are added between arguments when neither is a string.func ( *SugaredLogger) ( ...interface{}) {.log(DPanicLevel, "", , nil)}// Panic constructs a message with the provided arguments and panics.// Spaces are added between arguments when neither is a string.func ( *SugaredLogger) ( ...interface{}) {.log(PanicLevel, "", , nil)}// Fatal constructs a message with the provided arguments and calls os.Exit.// Spaces are added between arguments when neither is a string.func ( *SugaredLogger) ( ...interface{}) {.log(FatalLevel, "", , nil)}// Logf formats the message according to the format specifier// and logs it at provided level.func ( *SugaredLogger) ( zapcore.Level, string, ...interface{}) {.log(, , , nil)}// Debugf formats the message according to the format specifier// and logs it at [DebugLevel].func ( *SugaredLogger) ( string, ...interface{}) {.log(DebugLevel, , , nil)}// Infof formats the message according to the format specifier// and logs it at [InfoLevel].func ( *SugaredLogger) ( string, ...interface{}) {.log(InfoLevel, , , nil)}// Warnf formats the message according to the format specifier// and logs it at [WarnLevel].func ( *SugaredLogger) ( string, ...interface{}) {.log(WarnLevel, , , nil)}// Errorf formats the message according to the format specifier// and logs it at [ErrorLevel].func ( *SugaredLogger) ( string, ...interface{}) {.log(ErrorLevel, , , nil)}// DPanicf formats the message according to the format specifier// and logs it at [DPanicLevel].// In development, the logger then panics. (See [DPanicLevel] for details.)func ( *SugaredLogger) ( string, ...interface{}) {.log(DPanicLevel, , , nil)}// Panicf formats the message according to the format specifier// and panics.func ( *SugaredLogger) ( string, ...interface{}) {.log(PanicLevel, , , nil)}// Fatalf formats the message according to the format specifier// and calls os.Exit.func ( *SugaredLogger) ( string, ...interface{}) {.log(FatalLevel, , , nil)}// Logw logs a message with some additional context. The variadic key-value// pairs are treated as they are in With.func ( *SugaredLogger) ( zapcore.Level, string, ...interface{}) {.log(, , nil, )}// Debugw logs a message with some additional context. The variadic key-value// pairs are treated as they are in With.//// When debug-level logging is disabled, this is much faster than//// s.With(keysAndValues).Debug(msg)func ( *SugaredLogger) ( string, ...interface{}) {.log(DebugLevel, , nil, )}// Infow logs a message with some additional context. The variadic key-value// pairs are treated as they are in With.func ( *SugaredLogger) ( string, ...interface{}) {.log(InfoLevel, , nil, )}// Warnw logs a message with some additional context. The variadic key-value// pairs are treated as they are in With.func ( *SugaredLogger) ( string, ...interface{}) {.log(WarnLevel, , nil, )}// Errorw logs a message with some additional context. The variadic key-value// pairs are treated as they are in With.func ( *SugaredLogger) ( string, ...interface{}) {.log(ErrorLevel, , nil, )}// DPanicw logs a message with some additional context. In development, the// logger then panics. (See DPanicLevel for details.) The variadic key-value// pairs are treated as they are in With.func ( *SugaredLogger) ( string, ...interface{}) {.log(DPanicLevel, , nil, )}// Panicw logs a message with some additional context, then panics. The// variadic key-value pairs are treated as they are in With.func ( *SugaredLogger) ( string, ...interface{}) {.log(PanicLevel, , nil, )}// Fatalw logs a message with some additional context, then calls os.Exit. The// variadic key-value pairs are treated as they are in With.func ( *SugaredLogger) ( string, ...interface{}) {.log(FatalLevel, , nil, )}// Logln logs a message at provided level.// Spaces are always added between arguments.func ( *SugaredLogger) ( zapcore.Level, ...interface{}) {.logln(, , nil)}// Debugln logs a message at [DebugLevel].// Spaces are always added between arguments.func ( *SugaredLogger) ( ...interface{}) {.logln(DebugLevel, , nil)}// Infoln logs a message at [InfoLevel].// Spaces are always added between arguments.func ( *SugaredLogger) ( ...interface{}) {.logln(InfoLevel, , nil)}// Warnln logs a message at [WarnLevel].// Spaces are always added between arguments.func ( *SugaredLogger) ( ...interface{}) {.logln(WarnLevel, , nil)}// Errorln logs a message at [ErrorLevel].// Spaces are always added between arguments.func ( *SugaredLogger) ( ...interface{}) {.logln(ErrorLevel, , nil)}// DPanicln logs a message at [DPanicLevel].// In development, the logger then panics. (See [DPanicLevel] for details.)// Spaces are always added between arguments.func ( *SugaredLogger) ( ...interface{}) {.logln(DPanicLevel, , nil)}// Panicln logs a message at [PanicLevel] and panics.// Spaces are always added between arguments.func ( *SugaredLogger) ( ...interface{}) {.logln(PanicLevel, , nil)}// Fatalln logs a message at [FatalLevel] and calls os.Exit.// Spaces are always added between arguments.func ( *SugaredLogger) ( ...interface{}) {.logln(FatalLevel, , nil)}// Sync flushes any buffered log entries.func ( *SugaredLogger) () error {return .base.Sync()}// log message with Sprint, Sprintf, or neither.func ( *SugaredLogger) ( zapcore.Level, string, []interface{}, []interface{}) {// If logging at this level is completely disabled, skip the overhead of// string formatting.if < DPanicLevel && !.base.Core().Enabled() {return}:= getMessage(, )if := .base.Check(, ); != nil {.Write(.sweetenFields()...)}}// logln message with Sprintlnfunc ( *SugaredLogger) ( zapcore.Level, []interface{}, []interface{}) {if < DPanicLevel && !.base.Core().Enabled() {return}:= getMessageln()if := .base.Check(, ); != nil {.Write(.sweetenFields()...)}}// getMessage format with Sprint, Sprintf, or neither.func ( string, []interface{}) string {if len() == 0 {return}if != "" {return fmt.Sprintf(, ...)}if len() == 1 {if , := [0].(string); {return}}return fmt.Sprint(...)}// getMessageln format with Sprintln.func ( []interface{}) string {:= fmt.Sprintln(...)return [:len()-1]}func ( *SugaredLogger) ( []interface{}) []Field {if len() == 0 {return nil}var (// Allocate enough space for the worst case; if users pass only structured// fields, we shouldn't penalize them with extra allocations.= make([]Field, 0, len())invalidPairsbool)for := 0; < len(); {// This is a strongly-typed field. Consume it and move on.if , := [].(Field); {= append(, )++continue}// If it is an error, consume it and move on.if , := [].(error); {if ! {= true= append(, Error())} else {.base.Error(_multipleErrMsg, Error())}++continue}// Make sure this element isn't a dangling key.if == len()-1 {.base.Error(_oddNumberErrMsg, Any("ignored", []))break}// Consume this value and the next, treating them as a key-value pair. If the// key isn't a string, add this pair to the slice of invalid pairs., := [], [+1]if , := .(string); ! {// Subsequent errors are likely, so allocate once up front.if cap() == 0 {= make(invalidPairs, 0, len()/2)}= append(, invalidPair{, , })} else {= append(, Any(, ))}+= 2}// If we encountered any invalid key-value pairs, log an error.if len() > 0 {.base.Error(_nonStringKeyErrMsg, Array("invalid", ))}return}type invalidPair struct {position intkey, value interface{}}func ( invalidPair) ( zapcore.ObjectEncoder) error {.AddInt64("position", int64(.position))Any("key", .key).AddTo()Any("value", .value).AddTo()return nil}type invalidPairs []invalidPairfunc ( invalidPairs) ( zapcore.ArrayEncoder) error {var errorfor := range {= multierr.Append(, .AppendObject([]))}return}
The pages are generated with Golds v0.7.6. (GOOS=linux GOARCH=amd64)