golang结构化日志slog的用法简介

 更新时间:2023年09月17日 08:32:02   作者:洛天枫  
日志是任何软件的重要组成部分,Go 提供了一个内置日志包(slog),在本文中,小编将简单介绍一下slog包的功能以及如何在 Go 应用程序中使用它,感兴趣的可以了解下

日志是任何软件的重要组成部分,Go 提供了一个内置日志包(slog)。然而,随着应用的复杂性不断增加,对结构化日志的需求也越来越明显。结构化日志允许开发人员以结构化格式记录数据,便于日志聚合工具进行解析和分析,目前业界使用比较多的是:zap。

在本文中,我将简单介绍 slog 包、它的功能以及如何在 Go 应用程序中使用它。

什么是 slog

slog 提供结构化日志记录,其中的日志记录包括一条消息、level 和其他各种以键值对表示的属性。

使用

最新的1.21版本引入了slog。要在 Go 项目中使用slog,可以通过以下方式导入它:

import "log/slog"

这里写一个非常简单的例子:

func main() {
	slog.Info("hello, world!", "coding", "happy")
}

输出:

2023/09/15 13:42:27 INFO hello, world! coding=happy

功能

slog 提供了许多有用的功能,使其成为 Go 的强大日志包。以下是其中的一些主要功能:

  • 结构化日志
  • 严重级别日志
  • 分组日志
  • 自定义处理

结构化日志

slog 默认提供两种方式:

  • TextHandler
  • JSONHandler

我们写一下使用这两个方式的例子:

func main() {
	textHandler := slog.NewTextHandler(os.Stdout, nil)
	textLogger := slog.New(textHandler)
	textLogger.Info("TextDemo",
		slog.String("app-version", "v0.0.1"),
		slog.Int("release-version", 1),
	)
	jsonHandler := slog.NewJSONHandler(os.Stdout, nil)
	jsonLogger := slog.New(jsonHandler)
	jsonLogger.Info("JsonDemo",
		slog.String("app-version", "v0.0.1"),
		slog.Int("release-version", 1),
	)
}

输出为:

time=2023-09-15T13:48:37.424+08:00 level=INFO msg=TextDemo app-version=v0.0.1 release-version=1
{"time":"2023-09-15T13:48:37.4647782+08:00","level":"INFO","msg":"JsonDemo","app-version":"v0.0.1","release-version":1}

从上面我们可以看到,代码中使用了类似slog.String的方法,slog提供了指定属性的功能。有多种类型的属性可供选择:

  • slog.String:字符串属性。
  • slog.Int:整数属性。
  • slog.Float64:浮点属性。
  • slog.Bool:布尔属性。
  • slog.Duration:持续时间属性。
  • slog.Time:时间属性。
  • slog.Group:组属性,可用于将相关属性分组
func main() {
	jsonHandler := slog.NewJSONHandler(os.Stdout, nil)
	jsonLogger := slog.New(jsonHandler)
	jsonLogger.Info(
		"attributes",
		slog.String("version", "1.0.0"),
		slog.Int("app-version", 1),
		slog.Float64("point-value", 1.2),
		slog.Bool("status", true),
		slog.Duration("duration", time.Hour*1),
		slog.Time("time", time.Now()),
		slog.Group(
			"request",
			slog.String("path", "<https://example.com>"),
			slog.String("method", "get"),
		),
	)
}

对应的输出,我已经将其格式化了:

{
  "time": "2023-09-15T13:53:43.8848272+08:00",
  "level": "INFO",
  "msg": "attributes",
  "version": "1.0.0",
  "app-version": 1,
  "point-value": 1.2,
  "status": true,
  "duration": 3600000000000,
  "time": "2023-09-15T13:53:43.8848272+08:00",
  "request": {
    "path": "<https://example.com>",
    "method": "get"
  }
}

严重级别日志

这允许我们记录不同严重程度的信息。slog 默认提供四个日志级别,每个级别都有一个整数值:

  • DEBUG(-4)
  • INFO(0)
  • WARN(4)
  • ERROR(8)

例子:

func main() {
	jsonHandler := slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{
		Level: slog.LevelDebug,
	})
	jsonLogger := slog.New(jsonHandler)
	jsonLogger.Debug("Hello, world!")
	jsonLogger.Info("Hello, world!")
	jsonLogger.Warn("Hello, world!")
	jsonLogger.Error("Hello, world!")
}

NOTE: 记得在NewHandler时设置级别。

分组日志

分组日志指的是将日志信息归类为逻辑组或类别的做法。Slog 通过使用与日志记录相关联的属性或键值对来支持分组日志记录。

例子:

func main() {
	jsonHandler := slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{
		Level: slog.LevelDebug,
	})
	jsonLogger := slog.New(jsonHandler).WithGroup("request")
	jsonLogger.Info("",
		slog.String("url", "<https://example.com>"),
		slog.String("method", "GET"),
		slog.Int("response-code", 200),
	)
}

这里有个比较好的实践:

  • 在 http 服务的 middleware 中定义一个 request 组的 logger,会一些 4xx、5xx等请求的一些信息打印出来。
  • 而普通业务的话,我们又可以使用一个 service 组的 logger

自定义处理

slog 能够创建自定义handler,将日志信息写入不同的目的地,如文件、数据库或外部服务。

slog 提供的处理程序接口定义了自定义处理程序必须实现的方法。处理程序接口有四个方法:

type Handler interface {
    Enabled(Level) bool
    Handle(Record) error
    WithAttrs([]Attr) Handler
    WithGroup(string) Handler
}

下面举例说明如何创建一个将日志信息写入文件的自定义handler:

type FileHandler struct {
	file *os.File
}
func NewFileHandler(filename string) (*FileHandler, error) {
	file, err := os.OpenFile(filename, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
	if err != nil {
		return nil, err
	}
	return &FileHandler{file}, nil
}
func (h *FileHandler) Enabled(_ context.Context, level slog.Level) bool {
	return true
}
func (h *FileHandler) Handle(_ context.Context, record slog.Record) error {
	_, err := h.file.WriteString(record.Message + "\n")
	return err
}
func (h *FileHandler) WithAttrs(attrs []slog.Attr) slog.Handler {
	return h
}
func (h *FileHandler) WithGroup(name string) slog.Handler {
	return h
}
func (h *FileHandler) Close() error {
	return h.file.Close()
}
func main() {
	fileHandler, err := NewFileHandler("log.log")
	if err != nil {
		panic(err)
	}
	defer fileHandler.Close()
	logger := slog.New(fileHandler)
	logger.Info("Hello, world!")
	logger.Debug("Debugging errors")
}

这个时候运行程序时,控制台就不会有对应的日志输出了,而是输出到对应文件上:

 slogDemo  cat .\log.log
Hello, world!
Debugging errors

总结

slog 是一个功能强大的 Go 日志包,提供结构化日志功能。它易于使用,并提供了许多有用的功能,如级别日志和自定义处理程序。如果你正在寻找一个能满足你不断增长的应用程序需求的日志包,那么 slog 绝对值得你一试。

到此这篇关于golang结构化日志slog的用法简介的文章就介绍到这了,更多相关go slog内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • golang copy函数使用的坑

    golang copy函数使用的坑

    本文主要介绍了golang copy函数使用的坑,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-04-04
  • Golang两行代码实现发送钉钉机器人消息

    Golang两行代码实现发送钉钉机器人消息

    创建一个钉钉机器人必须使用加签,本文通过Golang两行代码实现发送钉钉机器人消息,本文给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧
    2021-12-12
  • go语言beego框架web开发语法笔记示例

    go语言beego框架web开发语法笔记示例

    这篇文章主要为大家介绍了go语言beego框架web开发语法笔记示例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步早日升职加薪
    2022-04-04
  • PHP和GO对接ChatGPT实现聊天机器人效果实例

    PHP和GO对接ChatGPT实现聊天机器人效果实例

    这篇文章主要为大家介绍了PHP和GO对接ChatGPT实现聊天机器人效果实例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2024-01-01
  • 模块一 GO语言基础知识-库源码文件

    模块一 GO语言基础知识-库源码文件

    这篇文章主要介绍了模块一 GO语言基础知识-库源码文件,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-01-01
  • Go语言break跳转语句怎么使用

    Go语言break跳转语句怎么使用

    这篇文章主要介绍了Go语言break跳转语句怎么使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习吧
    2023-01-01
  • Golang验证器之validator是使用详解

    Golang验证器之validator是使用详解

    Validator是一个 Golang 的第三方库,用于对数据进行校验,常用于 API 的开发中,对客户端发出的请求数据进行严格校验,防止恶意请求。本文通过示例详细讲解了Validator的使用,需要的可以参考一下
    2022-08-08
  • go语言中使用ent做关联查询的示例详解

    go语言中使用ent做关联查询的示例详解

    go语言的ent框架是facebook开源的ORM框架,是go语言开发中的常用框架,而关联查询又是日常开发中的常见数据库操作,故文本给出一个使用ent做关联查询的使用示例,需要的朋友可以参考下
    2024-02-02
  • golang切片反序实例

    golang切片反序实例

    这篇文章主要介绍了golang切片反序实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-12-12
  • Go 语言结构体链表的基本操作

    Go 语言结构体链表的基本操作

    链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的,这篇文章主要介绍了Go 语言结构体链表,需要的朋友可以参考下
    2022-04-04

最新评论