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}

3. 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大致的架构:

全文终。

Golang日志新选择:slog的更多相关文章

  1. 设计自用的golang日志模块

    设计自用的golang日志模块 golang的原生日志模块不能满足需求,而开源的第三方包,也不完全够用.用户较多的logrus,却没有rotate功能,这已经是众所周知的.对于运维来说,当然是希望日志 ...

  2. 从0写一个Golang日志处理包

    WHY 日志概述 日志几乎是每个实际的软件项目从开发到最后实际运行过程中都必不可少的东西.它对于查看代码运行流程,记录发生的事情等方面都是很重要的. 一个好的日志系统应当能准确地记录需要记录的信息,同 ...

  3. Mego(03) - ORM框架的新选择

    前言 从之前的两遍文章可以看出ORM的现状. Mego(01) - NET中主流ORM框架性能对比 Mego(02) - NET主流ORM框架分析 首先我们先谈下一个我们希望的ORM框架是什么样子的: ...

  4. 微信小程序,创业新选择

    微信小程序,创业新选择 创业者们 总是站在时代的风口浪尖,他们踌躇满志无所畏惧,这大概就是梦想的力量.但是,如果没有把梦想拆解成没有可预期的目标和可执行的实现路径那么一切都只能叫做梦想. 小程序 张小 ...

  5. NOSQL—MongoDB之外的新选择

    MongoDB之外的新选择 MongoDB拥有灵活的文档型数据结构和方便的操作语法,在新兴的互联网应用中得到了广泛的部署,但对于其底层的存储引擎一直未对外开放,虽说开源却有失完整.Mongo版本3中开 ...

  6. golang日志框架--logrus学习笔记

    golang日志框架--logrus学习笔记 golang标准库的日志框架非常简单,仅仅提供了print,panic和fatal三个函数,对于更精细的日志级别.日志文件分割以及日志分发等方面并没有提供 ...

  7. 前端工程师的新选择WebApp

    作为新一代移动端应用分发入口,小程序的趋势明朗化,竞争也在急剧激烈化.战线从手机 QQ.QQ 浏览器.支付宝.手机淘宝,华为,小米等九家手机厂商推出“快应用”,再拉到了谷歌的 Instant App ...

  8. 破解“低代码”的4大误区,拥抱低门槛高效率的软件开发新选择 ZT

    最近,每个人似乎都在谈论“低代码”.以美国的Outsystems.Kinvey,以及国内的活字格为代表的低代码开发平台,正在风靡整个IT世界.毕竟,能够以最少的编码快速开发应用的想法本身就很吸引人.但 ...

  9. 记-Golang日志文件读取及写入操作

    Golang语言的 os 包中OpenFile 函数,如下所示: func OpenFile(name string, flag int, perm FileMode) (*File, error) ...

  10. Oracle部署,关于日志文件系统选择(硬盘格式化、挂载)

    之前部署过好多Oracle服务,采用的日志文件系统一直是ext3.但是我观察到很多人在格式化/挂载数据盘时,采用的日志文件系统类型有ext3.ext4.xfs等,这不禁让我发出疑问,哪个类型的数据处理 ...

随机推荐

  1. Charles一文全明白

    自从用上了Mac本,抓包工具也从Fiddler换成了Charles,用了这么长时间,也是该对Charles做一个总结了,避免自己下次配置的时候又忘记怎么操作 1.Charles是什么? Charles ...

  2. cv学习总结(11.6-11.13)

    两层全连接神经网络的内容要比想象中的多很多,代码量也很多,在cs231n只用了15分钟讲解的东西我用了一周半的时间才完全的消化理解,这周终于完成了全连接神经网络博客的书写https://www.cnb ...

  3. RT_object

    以下图片来自"张世争"的微博  

  4. CKS 考试题整理 (09)-日志审计 log audit

    Task 在cluster中启用审计日志.为此,请启用日志后端,并确保: 日志存储在 /var/log/kubernetes/audit-logs.txt 日志文件能保留 10 天 最多保留 2 个旧 ...

  5. 发布一个Visual Studio 2022 插件,可以自动完成构造函数依赖注入代码

    赖注入(DI)在开发中既是常见的也是必需的技术.它帮助我们优化了代码结构,使得应用更加灵活.易于扩展,同时也降低了各个模块之间的耦合度,更容易进行单元测试,提高了编码效率和质量.不过,手动注入依赖项也 ...

  6. Python运维开发之路《模块》

      一.模块 1. 模块初识 模块定义:模块(module),通常也被称为库(lib,library),是一个包含所有你定义的函数和变量的文件,其后缀名是.py.模块可以被别的程序引入,以使用该模块中 ...

  7. iOS select标签适配去掉iOS默认select样式

    iOS端对select标签有独特的适配,如何取消这些默认样式呢 css样式表 加上 1 select { 2 -webkit-appearance: none; 3 } 博客同步更新:地址

  8. 2020中国系统架构师大会活动回顾:ZEGO实时音视频服务架构实践

    10月24日,即构科技后台架构负责人&高级技术专家祝永坚(jack),受邀参加2020中国系统架构师大会,在音视频架构与算法专场进行了主题为<ZEGO实时音视频服务架构实践>的技术 ...

  9. Starting Tomcat v8.0 Server at localhost has encountered a problem.

    现有Tomcat文件夹配置有问题,安装新的tomcat从新启动就好了

  10. elasticSearch初步学习反思

    转自自己的qq空间 2022年11月29日 每次找到新技术就会发癫 把业务整理完了 看着elasticSearch开始发癫 TM的把所有的一切都塞给它 反正全标记索引要啥拿啥 狠狠地获取就完了 思来想 ...