首页 > 其他分享 >Go 语言之自定义 zap 日志

Go 语言之自定义 zap 日志

时间:2023-06-17 14:33:56浏览次数:49  
标签:zapcore log 自定义 url Go 日志 Logger zap

Go 语言之自定义 zap 日志

zap 日志https://github.com/uber-go/zap

一、日志写入文件

  • zap.NewProductionzap.NewDevelopment 是预设配置好的。
  • zap.New 可自定义配置

zap.New源码

这是构造Logger最灵活的方式,但也是最冗长的方式。

对于典型的用例,高度固执己见的预设(NewProduction、NewDevelopment和NewExample)或Config结构体更方便。

// New constructs a new Logger from the provided zapcore.Core and Options. If
// the passed zapcore.Core is nil, it falls back to using a no-op
// implementation.
//
// This is the most flexible way to construct a Logger, but also the most
// verbose. For typical use cases, the highly-opinionated presets
// (NewProduction, NewDevelopment, and NewExample) or the Config struct are
// more convenient.
//
// For sample code, see the package-level AdvancedConfiguration example.
func New(core zapcore.Core, options ...Option) *Logger {
	if core == nil {
		return NewNop()
	}
	log := &Logger{
		core:        core,
		errorOutput: zapcore.Lock(os.Stderr),
		addStack:    zapcore.FatalLevel + 1,
		clock:       zapcore.DefaultClock,
	}
	return log.WithOptions(options...)
}

zapcore.Core 源码

// Core is a minimal, fast logger interface. It's designed for library authors
// to wrap in a more user-friendly API.
type Core interface {
	LevelEnabler

	// With adds structured context to the Core.
	With([]Field) Core
	// Check determines whether the supplied Entry should be logged (using the
	// embedded LevelEnabler and possibly some extra logic). If the entry
	// should be logged, the Core adds itself to the CheckedEntry and returns
	// the result.
	//
	// Callers must use Check before calling Write.
	Check(Entry, *CheckedEntry) *CheckedEntry
	// Write serializes the Entry and any Fields supplied at the log site and
	// writes them to their destination.
	//
	// If called, Write should always log the Entry and Fields; it should not
	// replicate the logic of Check.
	Write(Entry, []Field) error
	// Sync flushes buffered logs (if any).
	Sync() error
}

zapcore.AddSync(file) 源码解析

func AddSync(w io.Writer) WriteSyncer {
	switch w := w.(type) {
	case WriteSyncer:
		return w
	default:
		return writerWrapper{w}
	}
}

type writerWrapper struct {
	io.Writer
}

func (w writerWrapper) Sync() error {
	return nil
}

type WriteSyncer interface {
	io.Writer
	Sync() error
}

日志级别

// A Level is a logging priority. Higher levels are more important.
type Level int8

const (
	// DebugLevel logs are typically voluminous, and are usually disabled in
	// production.
	DebugLevel Level = iota - 1
	// InfoLevel is the default logging priority.
	InfoLevel
	// WarnLevel logs are more important than Info, but don't need individual
	// human review.
	WarnLevel
	// ErrorLevel logs are high-priority. If an application is running smoothly,
	// it shouldn't generate any error-level logs.
	ErrorLevel
	// DPanicLevel logs are particularly important errors. In development the
	// logger panics after writing the message.
	DPanicLevel
	// PanicLevel logs a message, then panics.
	PanicLevel
	// FatalLevel logs a message, then calls os.Exit(1).
	FatalLevel

	_minLevel = DebugLevel
	_maxLevel = FatalLevel

	// InvalidLevel is an invalid value for Level.
	//
	// Core implementations may panic if they see messages of this level.
	InvalidLevel = _maxLevel + 1
)

实操

package main

import (
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
	"net/http"
	"os"
)

// 定义一个全局 logger 实例
// Logger提供快速、分级、结构化的日志记录。所有方法对于并发使用都是安全的。
// Logger是为每一微秒和每一个分配都很重要的上下文设计的,
// 因此它的API有意倾向于性能和类型安全,而不是简便性。
// 对于大多数应用程序,SugaredLogger在性能和人体工程学之间取得了更好的平衡。
var logger *zap.Logger

// SugaredLogger将基本的Logger功能封装在一个较慢但不那么冗长的API中。任何Logger都可以通过其Sugar方法转换为sugardlogger。
//与Logger不同,SugaredLogger并不坚持结构化日志记录。对于每个日志级别,它公开了四个方法:
//   - 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 logging
var sugarLogger *zap.SugaredLogger

func main() {
	// 初始化
	InitLogger()
	// Sync调用底层Core的Sync方法,刷新所有缓冲的日志条目。应用程序在退出之前应该注意调用Sync。
	// 在程序退出之前,把缓冲区里的日志刷到磁盘上
	defer logger.Sync()
	simpleHttpGet("www.baidu.com")
	simpleHttpGet("http://www.baidu.com")
}

func InitLogger() {
	writeSyncer := getLogWriter()
	encoder := getEncoder()
	// NewCore创建一个向WriteSyncer写入日志的Core。

	// A WriteSyncer is an io.Writer that can also flush any buffered data. Note
	// that *os.File (and thus, os.Stderr and os.Stdout) implement WriteSyncer.

	// LevelEnabler决定在记录消息时是否启用给定的日志级别。
	// Each concrete Level value implements a static LevelEnabler which returns
	// true for itself and all higher logging levels. For example WarnLevel.Enabled()
	// will return true for WarnLevel, ErrorLevel, DPanicLevel, PanicLevel, and
	// FatalLevel, but return false for InfoLevel and DebugLevel.
	core := zapcore.NewCore(encoder, writeSyncer, zapcore.DebugLevel)

	// New constructs a new Logger from the provided zapcore.Core and Options. If
	// the passed zapcore.Core is nil, it falls back to using a no-op
	// implementation.
	logger = zap.New(core)
	// Sugar封装了Logger,以提供更符合人体工程学的API,但速度略慢。糖化一个Logger的成本非常低,
	// 因此一个应用程序同时使用Loggers和SugaredLoggers是合理的,在性能敏感代码的边界上在它们之间进行转换。
	sugarLogger = logger.Sugar()
}

func getEncoder() zapcore.Encoder {
	// NewJSONEncoder创建了一个快速、低分配的JSON编码器。编码器适当地转义所有字段键和值。
	// NewProductionEncoderConfig returns an opinionated EncoderConfig for
	// production environments.
	return zapcore.NewJSONEncoder(zap.NewProductionEncoderConfig())
}

func getLogWriter() zapcore.WriteSyncer {
	// Create创建或截断指定文件。如果文件已经存在,它将被截断。如果该文件不存在,则以模式0666(在umask之前)创建。
	// 如果成功,返回的File上的方法可以用于IO;关联的文件描述符模式为O_RDWR。如果有一个错误,它的类型将是PathError。
	file, _ := os.Create("./test.log")
	// AddSync converts an io.Writer to a WriteSyncer. It attempts to be
	// intelligent: if the concrete type of the io.Writer implements WriteSyncer,
	// we'll use the existing Sync method. If it doesn't, we'll add a no-op Sync.
	return zapcore.AddSync(file)
}

func simpleHttpGet(url string) {
	// Get向指定的URL发出Get命令。如果响应是以下重定向代码之一,则Get跟随重定向,最多可重定向10个:
	//	301 (Moved Permanently)
	//	302 (Found)
	//	303 (See Other)
	//	307 (Temporary Redirect)
	//	308 (Permanent Redirect)
	// Get is a wrapper around DefaultClient.Get.
	// 使用NewRequest和DefaultClient.Do来发出带有自定义头的请求。
	resp, err := http.Get(url)
	if err != nil {
		// Error在ErrorLevel记录消息。该消息包括在日志站点传递的任何字段,以及日志记录器上积累的任何字段。
		//logger.Error(

		// 错误使用fmt。以Sprint方式构造和记录消息。
		sugarLogger.Error(
			"Error fetching url..",
			zap.String("url", url), // 字符串用给定的键和值构造一个字段。
			zap.Error(err))         // // Error is shorthand for the common idiom NamedError("error", err).
	} else {
		// Info以infollevel记录消息。该消息包括在日志站点传递的任何字段,以及日志记录器上积累的任何字段。
		//logger.Info("Success..",

		// Info使用fmt。以Sprint方式构造和记录消息。
		sugarLogger.Info("Success..",
			zap.String("statusCode", resp.Status),
			zap.String("url", url))
		resp.Body.Close()
	}
}

运行

Code/go/zap_demo via 

标签:zapcore,log,自定义,url,Go,日志,Logger,zap
From: https://www.cnblogs.com/QiaoPengjun/p/17487453.html

相关文章

  • gorm简介
    gorm简介什么是gorm?gorm是一个强大的Go编程语言中的ORM(对象关系映射)库。ORM是一种技术,它将数据库表中的数据映射到面向对象的模型中,从而简化了数据库操作。gorm的特点gorm具有许多令人称赞的特点,使其成为Go开发者的首选ORM库之一。1.简单易用gorm提供了简洁而直观的API,使得......
  • Go 语言之 zap 日志库简单使用
    Go语言之zap日志库简单使用默认的Gologlog:https://pkg.go.dev/logpackagemainimport( "log" "os")funcinit(){ log.SetPrefix("LOG:")//设置前缀 f,err:=os.OpenFile("./log.log",os.O_WRONLY|os.O_CREATE|os.O_APPEND,......
  • golang之context
    context用来解决goroutine之间退出通知、元数据传递的功能。 context使用起来非常方便。源码里对外提供了一个创建根节点context的函数:funcBackground()Context background是一个空的context,它不能被取消,没有值,也没有超时时间。有了根节点context,又提供了四个函数创......
  • golang之fmt格式化
    常用fmt中用于格式化的占位符 普通占位符占位符说明举例输出%v相应值的默认格式。Printf("%v",people){zhangsan},%+v打印结构体时,会添加字段名Printf("%+v",people){Name:zhangsan}%#v......
  • golang之errors包
    errors包常用方法funcUnwrap(errerror)error//获得err包含下一层错误funcIs(err,targeterror)bool//判断err是否包含targetfuncAs(errerror,targetinterface{})bool//判断err是否为target类型   自定义错误信息errors.New("......
  • golang之jwt
    golang-jwt是go语言中用来生成和解析jwt的一个第三方库。本文中使用目前最新的v5版本。安装goget-ugithub.com/golang-jwt/jwt/v5 在代码中引用import"github.com/golang-jwt/jwt/v5" 结构体假设jwt原始的payload如下,username,exp为过期时间,nbf为生效时间,iat为签发时间。第一......
  • 通过Systemctl管理自定义linux服务文件
    Systemd默认从目录/etc/systemd/system/读取配置文件。但是,里面存放的大部分文件都是符号链接,指向目录/usr/lib/systemd/system/,真正的配置文件存放在那个目录。systemctlenable命令用于在上面两个目录之间,建立符号链接关系。sudosystemctlenable[example]等同于sudoln-......
  • 如何调试golang程序
    在Golang中进行调试和性能分析是非常重要的,在开发过程中发现问题并及时修复可以极大地提高代码质量和效率。介绍两种常用的调试工具,dlv和pprof,以及如何使用它们进行代码调试和性能分析。一、dlv调试工具1.安装在使用dlv前需要先安装,可以通过以下命令进行安装:goget-ugithub.......
  • 仿喜茶GO小程序前端模板源码,奶茶店微信小程序源码
    本项目包含:首页点单喜茶百货百货详情历史订单我的积分商城积分商城详情页我的-微信一键登录我的-成为星球会员我的-个人资料我的-钱包我的-阿喜有礼会员码任务中心下载地址点击下载仿喜茶小程序源码运行效果图 ......
  • Go Redis 管道和事务之 go-redis
    GoRedis管道和事务之go-redisGoRedis管道和事务官方文档介绍Redispipelines(管道)允许一次性发送多个命令来提高性能,go-redis支持同样的操作,你可以使用go-redis一次性发送多个命令到服务器,并一次读取返回结果,而不是一个个命令的操作。GoRedis管道和事务:https://red......