Go1.21で構造化ロガーslogが標準ライブラリとして追加された。1.20以前にもlogパッケージは存在したが、テキストでしか出力できず、ログレベルの設定等もできなかった。そのためZap等のサードパーティライブラリを使用する事が多かった。 slogは構造化ログとログレベルを提供する。
ごく簡単に使うことができる。
slog.Info("hello", "count", 3)
出力は以下。
2022/11/08 15:28:26 INFO hello count=3
JSONHandlerを使用することで、JSON形式でログを出力できる。
logger := slog.New(slog.NewJSONHandler(os.Stdout, nil))
logger.Info("hello", "count", 3)
{"time":"2022-11-08T15:28:26.000000000-05:00","level":"INFO","msg":"hello","count":3}
slogのログレベルはデフォルトでDebug,Info,Warn,Errorの4種類定義されている。
type Level int
const (
LevelDebug Level = -4
LevelInfo Level = 0
LevelWarn Level = 4
LevelError Level = 8
)
Levelはint型で-4から4刻みで定義されているので、独自のレベルを定義してフィルタすることもできる。
const LevelFatal = slog.Level(12)
logger := slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{
Level: LevelFatal,
}))
logger.Log(context.Background(), LevelFatal, "test")
ただし、上記だと以下のようにログレベルがいい感じに表示されない。
{"time":"2023-09-24T02:31:00.353259+09:00","level":"ERROR+4","msg":"test"}
独自に定義したログレベル名を表示するには以下のようにする。
logger := slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{
ReplaceAttr: func(groups []string, a slog.Attr) slog.Attr {
// NOTE: slogにログレベル`FATAL`を追加
if a.Key != slog.LevelKey {
return a
}
if level := a.Value.Any().(slog.Level); level == LevelFatal.ToSlogLevel() {
a.Value = slog.StringValue("FATAL")
}
return a
},
}))