profile-image

masatora.net

slogの使い方

Go
ログ

slog

Go1.21で構造化ロガーslogが標準ライブラリとして追加された。1.20以前にもlogパッケージは存在したが、テキストでしか出力できず、ログレベルの設定等もできなかった。そのためZap等のサードパーティライブラリを使用する事が多かった。 slogは構造化ログとログレベルを提供する。

基本的な使い方

ごく簡単に使うことができる。

slog.Info("hello", "count", 3)

出力は以下。

2022/11/08 15:28:26 INFO hello count=3

アーキテクチャ

Image from Gyazo

  • Logger: ロガーのフロントエンド。ログ出力のためのメソッドを提供する。呼び出しの度にRecordを作成する。
  • Record: RecordはHandlerに渡されて出力される。
  • Handler: ロガーのバックエンド。出力形式や出力先などを制御する。

JSON形式で出力する

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
    },
}))

参考