zap——SugaredLogger

zap——SugaredLoggerSugaredLogger//ASugaredLoggerwrapsthebaseLoggerfunctionalityinaslower,butless//verbose,API.AnyLoggercanbeconvertedtoaSugaredLoggerwithitsSugar//method.////UnliketheLo…

大家好,欢迎来到IT知识分享网。zap——SugaredLogger"

SugaredLogger

// 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 three methods: one for loosely-typed
// structured logging, one for println-style formatting, and one for
// printf-style formatting. For example, SugaredLoggers can produce InfoLevel
// output with Infow ("info with" structured context), Info, or Infof.
type SugaredLogger struct { 
   
    base *Logger
}

先看下注释,SugaredLogger用一个较慢但不太冗长的API包装基本Logger功能。Logger可以使用Sugar方法转换为SugaredLogger。SugaredLogger可以不用结构化log。针对每个log level,提供了三个方法:格式宽松的结构化log,println格式化的log,printf格式化的log。例如,可以使用Infow,Info,Infof生成InfoLevel的输出。

我们就以InfoLevel的三个方法为例,看下具体的处理过程。

InfoLevel

// Info uses fmt.Sprint to construct and log a message.
func (s *SugaredLogger) Info(args ...interface{ 
   }) { 
   
    s.log(InfoLevel, "", args, nil)
}

// Infof uses fmt.Sprintf to log a templated message.
func (s *SugaredLogger) Infof(template string, args ...interface{ 
   }) { 
   
    s.log(InfoLevel, template, args, nil)
}

// Infow logs a message with some additional context. The variadic key-value
// pairs are treated as they are in With.
func (s *SugaredLogger) Infow(msg string, keysAndValues ...interface{ 
   }) { 
   
    s.log(InfoLevel, msg, nil, keysAndValues)
}

Info、Infof、Infow均调用了log方法,区别在于传入的参数不同,Info仅传入args参数,Infof提供了args、template参数,Infow提供了msg和keysAndValues参数。

func (s *SugaredLogger) log(lvl zapcore.Level, template string, fmtArgs []interface{ 
   }, context []interface{ 
   }) { 
   
    // If logging at this level is completely disabled, skip the overhead of
    // string formatting.
    if lvl < DPanicLevel && !s.base.Core().Enabled(lvl) { 
   
        return
    }

    // Format with Sprint, Sprintf, or neither.
    msg := template
    if msg == "" && len(fmtArgs) > 0 { 
   
        msg = fmt.Sprint(fmtArgs...)
    } else if msg != "" && len(fmtArgs) > 0 { 
   
        msg = fmt.Sprintf(template, fmtArgs...)
    }

    if ce := s.base.Check(lvl, msg); ce != nil { 
   
        ce.Write(s.sweetenFields(context)...)
    }
}

具体看下fmtArgs的处理过程,如果存在template,则使用fmt.Sprintf格式化fmtArgs;如果不存在,则使用fmt.Sprint格式化参数,最终对msg进行处理。SugaredLogger慢首先就体现在使用了fmt.Sprintf,Sprintf内部会使用反射处理数据。

Check的过程就是调用Logger处理的,已在之前的文章中分析过,此处不再细述。

func (s *SugaredLogger) sweetenFields(args []interface{ 
   }) []Field { 
   
    if len(args) == 0 { 
   
        return nil
    }

    // Allocate enough space for the worst case; if users pass only structured
    // fields, we shouldn't penalize them with extra allocations.
    //为最坏的情况分配足够的空间;如果只有结构化的fileds,不要用Sugar.
    fields := make([]Field, 0, len(args))
    var invalid invalidPairs

    for i := 0; i < len(args); { 
   
        // This is a strongly-typed field. Consume it and move on.
        if f, ok := args[i].(Field); ok { 
   
            fields = append(fields, f)
            i++
            continue
        }

        // Make sure this element isn't a dangling key.
        // 确保最后的是成对的key、value
        if i == len(args)-1 { 
   
            s.base.DPanic(_oddNumberErrMsg, Any("ignored", args[i]))
            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.
        // 取当前值及下一个值为key、value。如果key是string类型,存入fileds中;否则,存入无效的fileds中。
        key, val := args[i], args[i+1]
        if keyStr, ok := key.(string); !ok { 
   
            // Subsequent errors are likely, so allocate once up front.
            if cap(invalid) == 0 { 
   
                invalid = make(invalidPairs, 0, len(args)/2)
            }
            invalid = append(invalid, invalidPair{ 
   i, key, val})
        } else { 
   
            fields = append(fields, Any(keyStr, val))
        }
        i += 2
    }

    // If we encountered any invalid key-value pairs, log an error.
    // 如果存在key不为string,DPanic
    if len(invalid) > 0 { 
   
        s.base.DPanic(_nonStringKeyErrMsg, Array("invalid", invalid))
    }
    return fields
}

使用Infow时,keysAndValues中的key的类型必须是string,否则会panic。如果参数都是结构化的Fileds,不要使用Sugar,会造成额外的内存分配。

后续的调用与Logger内的处理一致。

总结

SugaredLogger是在Logger的基础上,提供了额外参数的格式化方式,提供更大的便利性以格式化具体的msg,在可能带来风险的同时,还会造成额外的内存分配。实际可以通过,Logger Info的fields参数实现类似的功能。如果我们对log格式没有特别大的随意性要求,强烈建议使用Logger而不是SugaredLogger。

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/21518.html

(0)

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信