Go 语言之自定义 zap 日志

打印 上一主题 下一主题

主题 929|帖子 929|积分 2787

Go 语言之自定义 zap 日志

zap 日志https://github.com/uber-go/zap
一、日志写入文件


  • zap.NewProduction、zap.NewDevelopment 是预设配置好的。
  • zap.New 可自定义配置
zap.New源码

这是构造Logger最灵活的方式,但也是最冗长的方式。
对于典型的用例,高度固执己见的预设(NewProduction、NewDevelopment和NewExample)或Config结构体更方便。
  1. // New constructs a new Logger from the provided zapcore.Core and Options. If
  2. // the passed zapcore.Core is nil, it falls back to using a no-op
  3. // implementation.
  4. //
  5. // This is the most flexible way to construct a Logger, but also the most
  6. // verbose. For typical use cases, the highly-opinionated presets
  7. // (NewProduction, NewDevelopment, and NewExample) or the Config struct are
  8. // more convenient.
  9. //
  10. // For sample code, see the package-level AdvancedConfiguration example.
  11. func New(core zapcore.Core, options ...Option) *Logger {
  12.         if core == nil {
  13.                 return NewNop()
  14.         }
  15.         log := &Logger{
  16.                 core:        core,
  17.                 errorOutput: zapcore.Lock(os.Stderr),
  18.                 addStack:    zapcore.FatalLevel + 1,
  19.                 clock:       zapcore.DefaultClock,
  20.         }
  21.         return log.WithOptions(options...)
  22. }
复制代码
zapcore.Core 源码
  1. // Core is a minimal, fast logger interface. It's designed for library authors
  2. // to wrap in a more user-friendly API.
  3. type Core interface {
  4.         LevelEnabler
  5.         // With adds structured context to the Core.
  6.         With([]Field) Core
  7.         // Check determines whether the supplied Entry should be logged (using the
  8.         // embedded LevelEnabler and possibly some extra logic). If the entry
  9.         // should be logged, the Core adds itself to the CheckedEntry and returns
  10.         // the result.
  11.         //
  12.         // Callers must use Check before calling Write.
  13.         Check(Entry, *CheckedEntry) *CheckedEntry
  14.         // Write serializes the Entry and any Fields supplied at the log site and
  15.         // writes them to their destination.
  16.         //
  17.         // If called, Write should always log the Entry and Fields; it should not
  18.         // replicate the logic of Check.
  19.         Write(Entry, []Field) error
  20.         // Sync flushes buffered logs (if any).
  21.         Sync() error
  22. }
复制代码
zapcore.AddSync(file) 源码解析
  1. func AddSync(w io.Writer) WriteSyncer {
  2.         switch w := w.(type) {
  3.         case WriteSyncer:
  4.                 return w
  5.         default:
  6.                 return writerWrapper{w}
  7.         }
  8. }
  9. type writerWrapper struct {
  10.         io.Writer
  11. }
  12. func (w writerWrapper) Sync() error {
  13.         return nil
  14. }
  15. type WriteSyncer interface {
  16.         io.Writer
  17.         Sync() error
  18. }
复制代码
日志级别
  1. // A Level is a logging priority. Higher levels are more important.
  2. type Level int8
  3. const (
  4.         // DebugLevel logs are typically voluminous, and are usually disabled in
  5.         // production.
  6.         DebugLevel Level = iota - 1
  7.         // InfoLevel is the default logging priority.
  8.         InfoLevel
  9.         // WarnLevel logs are more important than Info, but don't need individual
  10.         // human review.
  11.         WarnLevel
  12.         // ErrorLevel logs are high-priority. If an application is running smoothly,
  13.         // it shouldn't generate any error-level logs.
  14.         ErrorLevel
  15.         // DPanicLevel logs are particularly important errors. In development the
  16.         // logger panics after writing the message.
  17.         DPanicLevel
  18.         // PanicLevel logs a message, then panics.
  19.         PanicLevel
  20.         // FatalLevel logs a message, then calls os.Exit(1).
  21.         FatalLevel
  22.         _minLevel = DebugLevel
  23.         _maxLevel = FatalLevel
  24.         // InvalidLevel is an invalid value for Level.
  25.         //
  26.         // Core implementations may panic if they see messages of this level.
  27.         InvalidLevel = _maxLevel + 1
  28. )
复制代码
实操
  1. package main
  2. import (
  3.         "go.uber.org/zap"
  4.         "go.uber.org/zap/zapcore"
  5.         "net/http"
  6.         "os"
  7. )
  8. // 定义一个全局 logger 实例
  9. // Logger提供快速、分级、结构化的日志记录。所有方法对于并发使用都是安全的。
  10. // Logger是为每一微秒和每一个分配都很重要的上下文设计的,
  11. // 因此它的API有意倾向于性能和类型安全,而不是简便性。
  12. // 对于大多数应用程序,SugaredLogger在性能和人体工程学之间取得了更好的平衡。
  13. var logger *zap.Logger
  14. // SugaredLogger将基本的Logger功能封装在一个较慢但不那么冗长的API中。任何Logger都可以通过其Sugar方法转换为sugardlogger。
  15. //与Logger不同,SugaredLogger并不坚持结构化日志记录。对于每个日志级别,它公开了四个方法:
  16. //   - methods named after the log level for log.Print-style logging
  17. //   - methods ending in "w" for loosely-typed structured logging
  18. //   - methods ending in "f" for log.Printf-style logging
  19. //   - methods ending in "ln" for log.Println-style logging
  20. // For example, the methods for InfoLevel are:
  21. //
  22. //        Info(...any)           Print-style logging
  23. //        Infow(...any)          Structured logging (read as "info with")
  24. //        Infof(string, ...any)  Printf-style logging
  25. //        Infoln(...any)         Println-style logging
  26. var sugarLogger *zap.SugaredLogger
  27. func main() {
  28.         // 初始化
  29.         InitLogger()
  30.         // Sync调用底层Core的Sync方法,刷新所有缓冲的日志条目。应用程序在退出之前应该注意调用Sync。
  31.         // 在程序退出之前,把缓冲区里的日志刷到磁盘上
  32.         defer logger.Sync()
  33.         simpleHttpGet("www.baidu.com")
  34.         simpleHttpGet("http://www.baidu.com")
  35. }
  36. func InitLogger() {
  37.         writeSyncer := getLogWriter()
  38.         encoder := getEncoder()
  39.         // NewCore创建一个向WriteSyncer写入日志的Core。
  40.         // A WriteSyncer is an io.Writer that can also flush any buffered data. Note
  41.         // that *os.File (and thus, os.Stderr and os.Stdout) implement WriteSyncer.
  42.         // LevelEnabler决定在记录消息时是否启用给定的日志级别。
  43.         // Each concrete Level value implements a static LevelEnabler which returns
  44.         // true for itself and all higher logging levels. For example WarnLevel.Enabled()
  45.         // will return true for WarnLevel, ErrorLevel, DPanicLevel, PanicLevel, and
  46.         // FatalLevel, but return false for InfoLevel and DebugLevel.
  47.         core := zapcore.NewCore(encoder, writeSyncer, zapcore.DebugLevel)
  48.         // New constructs a new Logger from the provided zapcore.Core and Options. If
  49.         // the passed zapcore.Core is nil, it falls back to using a no-op
  50.         // implementation.
  51.         logger = zap.New(core)
  52.         // Sugar封装了Logger,以提供更符合人体工程学的API,但速度略慢。糖化一个Logger的成本非常低,
  53.         // 因此一个应用程序同时使用Loggers和SugaredLoggers是合理的,在性能敏感代码的边界上在它们之间进行转换。
  54.         sugarLogger = logger.Sugar()
  55. }
  56. func getEncoder() zapcore.Encoder {
  57.         // NewJSONEncoder创建了一个快速、低分配的JSON编码器。编码器适当地转义所有字段键和值。
  58.         // NewProductionEncoderConfig returns an opinionated EncoderConfig for
  59.         // production environments.
  60.         return zapcore.NewJSONEncoder(zap.NewProductionEncoderConfig())
  61. }
  62. func getLogWriter() zapcore.WriteSyncer {
  63.         // Create创建或截断指定文件。如果文件已经存在,它将被截断。如果该文件不存在,则以模式0666(在umask之前)创建。
  64.         // 如果成功,返回的File上的方法可以用于IO;关联的文件描述符模式为O_RDWR。如果有一个错误,它的类型将是PathError。
  65.         file, _ := os.Create("./test.log")
  66.         // AddSync converts an io.Writer to a WriteSyncer. It attempts to be
  67.         // intelligent: if the concrete type of the io.Writer implements WriteSyncer,
  68.         // we'll use the existing Sync method. If it doesn't, we'll add a no-op Sync.
  69.         return zapcore.AddSync(file)
  70. }
  71. func simpleHttpGet(url string) {
  72.         // Get向指定的URL发出Get命令。如果响应是以下重定向代码之一,则Get跟随重定向,最多可重定向10个:
  73.         //        301 (Moved Permanently)
  74.         //        302 (Found)
  75.         //        303 (See Other)
  76.         //        307 (Temporary Redirect)
  77.         //        308 (Permanent Redirect)
  78.         // Get is a wrapper around DefaultClient.Get.
  79.         // 使用NewRequest和DefaultClient.Do来发出带有自定义头的请求。
  80.         resp, err := http.Get(url)
  81.         if err != nil {
  82.                 // Error在ErrorLevel记录消息。该消息包括在日志站点传递的任何字段,以及日志记录器上积累的任何字段。
  83.                 //logger.Error(
  84.                 // 错误使用fmt。以Sprint方式构造和记录消息。
  85.                 sugarLogger.Error(
  86.                         "Error fetching url..",
  87.                         zap.String("url", url), // 字符串用给定的键和值构造一个字段。
  88.                         zap.Error(err))         // // Error is shorthand for the common idiom NamedError("error", err).
  89.         } else {
  90.                 // Info以infollevel记录消息。该消息包括在日志站点传递的任何字段,以及日志记录器上积累的任何字段。
  91.                 //logger.Info("Success..",
  92.                 // Info使用fmt。以Sprint方式构造和记录消息。
  93.                 sugarLogger.Info("Success..",
  94.                         zap.String("statusCode", resp.Status),
  95.                         zap.String("url", url))
  96.                 resp.Body.Close()
  97.         }
  98. }
复制代码
运行

[code]Code/go/zap_demo via
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

大号在练葵花宝典

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表