8

Go slog 日志包尝鲜

 1 year ago
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.
neoserver,ios ssh client

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 语言文章也非常值得一读。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK