いろいろ備忘録日記

主に .NET とか Go とか Flutter とか Python絡みのメモを公開しています。

Goメモ-484 (slogメモ-07)(動的にログレベルを変更)

関連記事

Goメモ-477 (slogメモ-01)(基本的な使い方) - いろいろ備忘録日記

Goメモ-478 (slogメモ-02)(構造化ログの出力) - いろいろ備忘録日記

Goメモ-479 (slogメモ-03)(デフォルトロガー) - いろいろ備忘録日記

Goメモ-480 (slogメモ-04)(従来のlogパッケージとの連携) - いろいろ備忘録日記

Goメモ-482 (slogメモ-05)(テキスト形式のログ) - いろいろ備忘録日記

Goメモ-483 (slogメモ-06)(JSON形式のログ) - いろいろ備忘録日記

GitHub - devlights/blog-summary: ブログ「いろいろ備忘録日記」のまとめ

概要

以下、自分用のメモです。

今更ながら、Go 1.21で導入された log/slog を使ってみたりしています。

少しづつメモしていきます。今回は動的なログレベルの変更(slog.LevelVar) について。

サンプル

main.go

package main

import (
    "context"
    "log/slog"
    "os"
)

func main() {
    var (
        rootCtx  = context.Background()
        ctx, cxl = context.WithCancel(rootCtx)
    )
    defer cxl()

    if err := run(ctx); err != nil {
        slog.Error("A fatal error occurred", "err", err)
        os.Exit(1)
    }
}

func run(_ context.Context) error {
    //
    // slog.LevelVarを使用することで、実行時にログレベルを動的に変更できる.
    //
    // 以下、https://pkg.go.dev/log/slog@go1.23.2#hdr-Levels にある記載を抜粋
    //
    // > Setting it to a LevelVar allows the level to be varied dynamically.
    // > A LevelVar holds a Level and is safe to read or write from multiple goroutines.
    //
    // >> LevelVar を設定することで、レベルを動的に変化させることができます。
    // >> LevelVar は Level を保持し、複数のゴルーチンから安全に読み書きできます。
    //

    var (
        level = &slog.LevelVar{}
        opt   = &slog.HandlerOptions{
            Level:       level,
            ReplaceAttr: noTimeKey,
        }
        handler    = slog.NewTextHandler(os.Stdout, opt)
        rootLogger = slog.New(handler)
        logger     *slog.Logger
    )

    // デフォルトのレベルはINFO。なのでDEBUGは出力されない
    logger = rootLogger.With("idx", "1")
    logger.Debug("this is DEBUG level message")
    logger.Info("this is INFO level message")

    // レベルを変更
    //   現実的な使い方だと、コマンドライン引数で -debug を受け取った場合に
    //   DEBUGレベルを有効にするなどの使い方が出来る。
    level.Set(slog.LevelDebug)

    // デフォルトのレベルがDEBUGに変更された
    logger = rootLogger.With("idx", "2")
    logger.Debug("this is DEBUG level message")
    logger.Info("this is INFO level message")

    return nil
}

func noTimeKey(groups []string, a slog.Attr) slog.Attr {
    if a.Key == slog.TimeKey {
        return slog.Attr{}
    }

    return a
}

実行すると以下のように出力されます。

Taskfile.yml

# https://taskfile.dev

version: '3'

tasks:
  default:
    cmds:
      - task: run
  run:
    cmds:
      - go run main.go

shell

$ task
task: [run] go run main.go
level=INFO msg="this is INFO level message" idx=1
level=DEBUG msg="this is DEBUG level message" idx=2
level=INFO msg="this is INFO level message" idx=2

try-golang/examples/slog at main · devlights/try-golang · GitHub

参考情報

Goのおすすめ書籍


過去の記事については、以下のページからご参照下さい。

サンプルコードは、以下の場所で公開しています。