go1.21中slog日志包用法入门

 更新时间:2023年09月12日 08:33:35   作者:青峰上人  
go1.21中,slog这一被Go语言团队精心设计的结构化日志包正式落地,本文将带领读者上手slog,体会其与传统log的差异,感兴趣的小伙伴快跟随小编一起学习一下吧

WHY

在日志处理上,我们从前使用的log包缺乏结构化的输出,导致信息呈现出来的样子并非最适合人类阅读,而slog是一种结构化的日志,它可以用键值对的形式将我们需要的信息呈现出来,使得处理与分析日志变得更为容易。

HOW

1. 快速入门

package main
import (
	"log/slog"
)
func main() {
	slog.Info("my first slog msg", "greeting", "hello, slog")
	slog.Error("my secod slog message", "greeting", "hello slog")
	slog.Warn("my third message", "greeting", "hello slog")
}

以上是三条最简单的slog语句,其结果是这样的:

2023/09/10 21:51:03 INFO my first slog msg greeting="hello, slog"
2023/09/10 21:51:03 ERROR my secod slog message greeting="hello slog"
2023/09/10 21:51:03 WARN my third message greeting="hello slog"

这三行代码中的第一个参数代表了log的message,我们可以看到,此时打印出来的日志信息是文本信息,那如何使得日志以非纯文本(比如json)展现呢?

2. TextHandler和JSONHandler

当我们想要日志以key-value格式呈现时,我们可以用下面这种方式:

h := slog.NewTextHandler(os.Stderr, nil)
	l := slog.New(h)
	l.Info("greeting", "name", "xxx")

最终结果:

time=2023-09-10T21:58:34.144+08:00 level=INFO msg=greeting name=xxx

当我们想要日志以json格式呈现时,我们可以使用下面这种方式:

h1 := slog.NewJSONHandler(os.Stderr, nil)
	l1 := slog.New(h1)
	l1.Info("greeting", "name", "xxx")

最终结果:

{"time":"2023-09-10T22:00:04.687003+08:00","level":"INFO","msg":"greeting","name":"xxx"}

slog.NewJSONHandler函数和slog.NewTextHandler函数都会返回一个JsonHandler结构体或是TextHandler的引用,这个结构体会被slog.new函数接受,该函数返回一个Logger结构体的引用,这个logger结构体包含Handler接口,拥有一系列日志相关函数,是我们最终打印日志的地方

func NewJSONHandler(w io.Writer, opts *HandlerOptions) *JSONHandler {}
func NewTextHandler(w io.Writer, opts *HandlerOptions) *TextHandler {}
func New(h Handler) *Logger {}
type Logger struct {
	handler Handler // for structured logging
}
type Handler interface {}

如此,我们实现了基本的日志结构化输出。

3.日志配置

我们通过对slog.HandlerOptions配置,可以实现例如 是否输出日志来源 等设置;

s := &slog.HandlerOptions{
		AddSource: true,
	}
	slog.SetDefault(slog.New(slog.NewTextHandler(os.Stderr, s)))
	slog.Info("Test", "greeting", "hello, world")

此处笔者将该s设置为default情况,这样直接使用slog.info就可以用到之前的配置;

最终结果:

time=2023-09-10T22:11:04.432+08:00 level=INFO source="/Users/wurenyu/Library/Mobile Documents/com~apple~CloudDocs/Go_learn/basic/slog/t1.go:13" msg=Test greeting="hello, world"

可以看到,由于AddSource被设置为true,我们的输出日志中多了source这一信息;

又由于NewTextHandler,所以日志是以键值对的形式输出的。

再来看这一段代码:

opts := slog.HandlerOptions{
AddSource: true,
Level:     slog.LevelError,
}
slog.SetDefault(slog.New(slog.NewJSONHandler(os.Stderr, &opts)))
slog.Info("open file for reading", "name", "foo.txt", "path", "/home/tonybai/demo/foo.txt")
slog.Error("open file error", "err", os.ErrNotExist, "status", 2)

在slog配置中将Level设置为了LevelError,如此,将只能使用slog.error这一级别;

最终输出结果:

{"time":"2023-09-10T22:13:44.493714+08:00","level":"ERROR","source":{"function":"main.main","file":"/Users/wurenyu/Library/Mobile Documents/com~apple~CloudDocs/Go_learn/basic/slog/t1.go","line":16},"msg":"open file error","err":"file does not exist","status":2}

4. Group形式输出日志

baseLogger := slog.New(slog.NewJSONHandler(os.Stdout, nil))
	groupedLogger := baseLogger.WithGroup("TTT")
	// Log with the grouped logger
	groupedLogger.Info("This log entry includes module information.", "test1", "answer1")
	groupedLogger.Warn("This log entry also includes module information.", "test2", "answer2")

上述代码首先生成一个叫做baseLogger的logger,然后在这个logger上调用方法WithGroup,并传入参数“TTT”,后面两行分别输出info和warn级别的日志;

最终结果如下:

{"time":"2023-09-10T22:23:28.527786+08:00","level":"INFO","msg":"This log entry includes module information.","TTT":{"test1":"answer1"}}
{"time":"2023-09-10T22:23:28.528019+08:00","level":"WARN","msg":"This log entry also includes module information.","TTT":{"test2":"answer2"}}

可以看到,在groupLogger后面加上的键值对都被加在了TTT后面;

不过值得关注的是,slog是支持给logger自定义字段的,给一个logger加上一个属性之后,每次用这个logger输出日志,都会输出这个属性对应的键值对,而这个信息不会被包含在WithGroup函数传入的参数后面。

风格

个人认为一般不需要在msg中直接传入代码中的数据,msg中应该尽量直接使用constant常量,这样更可控。

WHAT

以下是slog大致的架构:

全文终。

以上就是go1.21中slog日志包用法入门的详细内容,更多关于go slog的资料请关注脚本之家其它相关文章!

相关文章

  • go中如何获取本机ip地址

    go中如何获取本机ip地址

    这篇文章主要介绍了go中如何获取本机ip地址问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-09-09
  • Go 简单实现多租户数据库隔离

    Go 简单实现多租户数据库隔离

    本文主要介绍了Go 简单实现多租户数据库隔离,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-05-05
  • 深入探讨Go语言中的map是否是并发安全以及解决方法

    深入探讨Go语言中的map是否是并发安全以及解决方法

    这篇文章主要来和大家探讨 Go 语言中的 map 是否是并发安全的,并提供三种方案来解决并发问题,文中的示例代码讲解详细,需要的可以参考一下
    2023-05-05
  • go语言通过结构体生成json示例解析

    go语言通过结构体生成json示例解析

    这篇文章主要为大家介绍了go语言通过结构体生成json示例解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步早日升职加薪
    2022-04-04
  • 掌握Golang中的select语句实现并发编程

    掌握Golang中的select语句实现并发编程

    Golang中的select语句用于在多个通道间选择可读或可写的操作,并阻塞等待其中一个通道进行操作。可以用于实现超时控制、取消和中断操作等。同时,select语句支持default分支,用于在没有任何通道可操作时执行默认操作
    2023-04-04
  • Go语言基础类型及常量用法示例详解

    Go语言基础类型及常量用法示例详解

    这篇文章主要为大家介绍了Go语言基础类型及常量的用法及示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助
    2021-11-11
  • Go语言编程中判断文件是否存在是创建目录的方法

    Go语言编程中判断文件是否存在是创建目录的方法

    这篇文章主要介绍了Go语言编程中判断文件是否存在是创建目录的方法,示例都是使用os包下的函数,需要的朋友可以参考下
    2015-10-10
  • golang switch语句的灵活写法介绍

    golang switch语句的灵活写法介绍

    这篇文章主要介绍了golang switch语句的灵活写法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-05-05
  • Go语言自定义linter静态检查工具

    Go语言自定义linter静态检查工具

    这篇文章主要介绍了Go语言自定义linter静态检查工具,Go语言是一门编译型语言,编译器将高级语言翻译成机器语言,会先对源代码做词法分析,词法分析是将字符序列转换为Token序列的过程,文章详细介绍需要的小伙伴可以参考一下
    2022-05-05
  • go语言中range用法

    go语言中range用法

    这篇文章主要介绍了go语言中range用法,实例分析了Go语言中range的功能及使用技巧,需要的朋友可以参考下
    2015-03-03

最新评论