Go slog 日志包尝鲜
source link: https://www.ganymedenil.com/2022/12/21/go-standard-library-by-slog-early.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
slog 是 Go 团队开发的一个实验性日志包,它提供了结构化日志记录的功能。 注意:当前该包还未在Go基础库中包含。
创建新的 Go 项目或者使用现有的项目通过以下命令进行安装。
go get golang.org/x/exp/slog
package main
import "golang.org/x/exp/slog"
func main() {
slog.Info("Go is best language!")
}
$ go run main.go
2022/12/21 11:16:00 INFO Go is best language!
默认情况下,输出包括时间、日志级别和消息。
以下是可用的日志级别。
Debug
Info
Warn
Error
结构化日志记录
slog 是一个结构化日志记录工具,支持两种记录格式:text 和 json。
Text Handler
首先创建一个 text handler 和 一个 new logger。
package main
import (
"os"
"golang.org/x/exp/slog")
func main() {
textHandler := slog.NewTextHandler(os.Stdout)
logger := slog.New(textHandler)
logger.Info("Go is the best language!")
}
$ go run main.go
time=2022-12-21T11:20:52.919+08:00 level=INFO msg="Go is the best language!"
我们可以看出日志是以键值对的形式输出。这通常称为 logfmt 格式。
许多日志分析工具都可以处理logfmt格式的日志。Logfmt
也是人类可读的一种日志格式。
JSON Handler
你还可以输出 JSON 格式的日志。
package main
import (
"os"
"golang.org/x/exp/slog")
func main() {
jsonHandler := slog.NewJSONHandler(os.Stdout) // 👈
logger := slog.New(jsonHandler)
logger.Info("Go is the best language!")
}
$ go run main.go
{"time":"2022-12-21T11:26:08.355317+08:00","level":"INFO","msg":"Go is the best language!"}
每个日志都记录为一个 json 对象,其中包含属性。
slog 是一个结构化的记录器,提供了指定属性的能力。
package main
import (
"os"
"golang.org/x/exp/slog")
func main() {
textHandler := slog.NewTextHandler(os.Stdout)
logger := slog.New(textHandler)
logger.Info("Usage Statistics", slog.Int("current-memory", 50))
}
$ go run main.go
time=2022-12-21T11:28:27.209+08:00 level=INFO msg="Usage Statistics" current-memory=50
在上面的示例中,使用 .
添加了一个整数属性slog.Int
。
以下是各类支持的属性:
String
Int64
Int
Uint64
Float64
Bool
Time
Duration
你可以根据需要添加任意数量的属性。
package main
import (
"os"
"golang.org/x/exp/slog")
func main() {
textHandler := slog.NewTextHandler(os.Stdout)
logger := slog.New(textHandler)
logger.Info("Usage Statistics",
slog.Int("current-memory", 50),
slog.Int("min-memory", 20),
slog.Int("max-memory", 80),
slog.Int("cpu", 10),
slog.String("app-version", "v0.0.1-beta"),
)
}
$ go run main.go
time=2022-12-21T11:31:12.469+08:00 level=INFO msg="Usage Statistics" current-memory=50 min-memory=20 max-memory=80 cpu=10 app-version=v0.0.1-beta
你可以将属性分组在一个键下。例如,所有内存属性都可以分组在 memory
键下。
package main
import (
"os"
"golang.org/x/exp/slog")
func main() {
textHandler := slog.NewTextHandler(os.Stdout)
logger := slog.New(textHandler)
logger.Info("Usage Statistics",
slog.Group("memory",
slog.Int("current", 50),
slog.Int("min", 20),
slog.Int("max", 80)),
slog.Int("cpu", 10),
slog.String("app-version", "v0.0.1-beta"),
)
}
$ go run main.go
time=2022-12-21T11:33:38.016+08:00 level=INFO msg="Usage Statistics" memory.current=50 memory.min=20 memory.max=80 cpu=10 app-version=v0.0.1-beta
使用 JsonHandler
输出将如下所示。
$ go run main.go | jq
{
"time": "2022-12-21T11:35:24.648829+08:00",
"level": "INFO",
"msg": "Usage Statistics",
"memory": {
"current": 50,
"min": 20,
"max": 80
},
"cpu": 10,
"app-version": "v0.0.1-beta"
}
假设你希望拥有一个应包含在所有正在生成的日志中的属性,此类属性的示例包括服务名称、应用程序版本。
package main
import (
"os"
"golang.org/x/exp/slog")
func main() {
textHandler := slog.NewTextHandler(os.Stdout).
WithAttrs([]slog.Attr{slog.String("app-version", "v0.0.1-beta")}) // 👈 为所有日志添加属性
logger := slog.New(textHandler)
logger.Info("Generating statistics")
logger.Info("Usage Statistics",
slog.Group("memory",
slog.Int("current", 50),
slog.Int("min", 20),
slog.Int("max", 80)),
slog.Int("cpu", 10),
)
}
$ go run main.go
time=2022-12-21T11:37:26.363+08:00 level=INFO msg="Generating statistics" app-version=v0.0.1-beta
time=2022-12-21T11:37:26.363+08:00 level=INFO msg="Usage Statistics" app-version=v0.0.1-beta memory.current=50 memory.min=20 memory.max=80 cpu=10
你可以看到 app-version
两个日志中都包含该属性。在处理程序上使用函数指定的属性WithAttrs
将包含在所有日志中。
在 context 中传递 logger
理想情况下,你希望创建一个具有特定配置和属性的记录器,并在整个应用程序中使用它。
slog具有内置函数,可让让你在context
中使用。
package main
import (
"context"
"os"
"golang.org/x/exp/slog")
func main() {
textHandler := slog.NewTextHandler(os.Stdout).
WithAttrs([]slog.Attr{slog.String("app-version", "v0.0.1-beta")})
logger := slog.New(textHandler)
ctx := slog.NewContext(context.Background(), logger) // 👈 context containing logger sendUsageStatus(ctx)
}
func sendUsageStatus(ctx context.Context) {
logger := slog.FromContext(ctx) // 👈 grab logger from context
logger.Info("Generating statistics")
logger.Info("Usage Statistics",
slog.Group("memory",
slog.Int("current", 50),
slog.Int("min", 20),
slog.Int("max", 80)),
slog.Int("cpu", 10),
)
}
$ go run main.go
time=2022-12-21T11:41:28.333+08:00 level=INFO msg="Generating statistics" app-version=v0.0.1-beta
time=2022-12-21T11:41:28.334+08:00 level=INFO msg="Usage Statistics" app-version=v0.0.1-beta memory.current=50 memory.min=20 memory.max=80 cpu=10
NewContext
创建一个包含 logger 的 新的 context。
FromContext
从 contex t中获取 logger。如果 context 不包含 logger,它会返回default logger。
如果你使用的是默认 logger,它不会记录调试日志,因为默认日志级别为Info
.
你可以创建一个新的 logger,并将默认日志级别设置为Debug
以显示调试日志。
package main
import (
"os"
"golang.org/x/exp/slog")
func main() {
opts := slog.HandlerOptions{
Level: slog.LevelDebug,
}
textHandler := opts.NewTextHandler(os.Stdout)
logger := slog.New(textHandler)
logger.Debug("Debug")
logger.Info("Info")
logger.Warn("Warn")
}
$ go run main.go
time=2022-12-21T11:45:23.466+08:00 level=DEBUG msg=Debug
time=2022-12-21T11:45:23.466+08:00 level=INFO msg=Info
time=2022-12-21T11:45:23.466+08:00 level=WARN msg=Warn
Logging in Go with slog - https://thedevelopercafe.com/articles/logging-in-go-with-slog-a7bb489755c2
本文作者的其他 Go 语言文章也非常值得一读。
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK