Open7
s-logについて
slogは構造化されたログシステム
- メッセージの内容
- ログのレベル
- キー&バリューのペアで構成できる
ログ設定例
package main
import "log/slog"
func main() {
slog.Info("hello", "count", 3)
}
出力結果
2009/11/10 23:00:00 INFO hello count=3
テキスト形式で標準エラーに書き込む TextHandler をNewして作成
ログ構成をmsgやKey&Valueを含めて、視覚的に見やすくしている感じかな?
設定例
package main
import (
"log/slog"
"os"
)
func main() {
logger := slog.New(slog.NewTextHandler(os.Stderr, nil))
logger.Info("hello", "count", 3)
logger.Error("error")
}
出力結果
time=2009-11-10T23:00:00.000Z level=INFO msg=hello count=3
time=2009-11-10T23:00:00.000Z level=ERROR msg=""
JSON形式で出力
設定例
package main
import (
"log/slog"
"os"
)
func main() {
logger := slog.New(slog.NewJSONHandler(os.Stdout, nil))
logger.Info("hello", "count", 3)
}
出力結果
{"time":"2009-11-10T23:00:00Z","level":"INFO","msg":"hello","count":3}
これおもろい!Cloud Loggingとかでいい感じに出せるというやつか
カスタムロガー設定をDefault設定する
設定例
package main
import (
"log/slog"
"os"
)
func main() {
// カスタムロガーをNewして作成
logger := slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{
Level: slog.LevelDebug,
}))
// デフォルトロガーとして設定
slog.SetDefault(logger)
// これ以降、slog.Info()などはこのカスタムロガーが適用される
slog.Info("アプリケーション開始", "version", "1.0.0")
slog.Error("エラーが発生しました", "error", "connection timeout")
}
出力結果
{"time":"2009-11-10T23:00:00Z","level":"INFO","msg":"アプリケーション開始","version":"1.0.0"}
{"time":"2009-11-10T23:00:00Z","level":"ERROR","msg":"エラーが発生しました","error":"connection timeout"}
Withで設定したKey&Valueを含めるようにする
必ず共通で設定したい値を共通設定できるやつ
設定例
package main
import (
"log/slog"
"os"
)
func main() {
logger := slog.New(slog.NewJSONHandler(os.Stdout, nil))
logger.Info("通常のログ")
// Withでlogger2はurlを含む
logger2 := logger.With("url", "/api/users")
logger2.Info("リクエスト開始")
logger2.Error("エラーが発生", "error", "connection timeout")
logger2.Info("処理完了", "status", "success", "duration", "100ms")
}
出力結果
{"time":"2009-11-10T23:00:00Z","level":"INFO","msg":"通常のログ"}
{"time":"2009-11-10T23:00:00Z","level":"INFO","msg":"リクエスト開始","url":"/api/users"}
{"time":"2009-11-10T23:00:00Z","level":"ERROR","msg":"エラーが発生","url":"/api/users","error":"connection timeout"}
{"time":"2009-11-10T23:00:00Z","level":"INFO","msg":"処理完了","url":"/api/users","status":"success","duration":"100ms"}
Context
これも結構使うよね
Contextを含めることができる
トップレベルでは不要だけど、コンテキストを含めたい場面が多いと思う
設定例
package main
import (
"context"
"log/slog"
"os"
)
func main() {
// JSONハンドラーでロガーを作成
logger := slog.New(slog.NewJSONHandler(os.Stdout, nil))
slog.SetDefault(logger)
// 通常のコンテキスト
ctx := context.Background()
// コンテキストに値を追加
ctx = context.WithValue(ctx, "user_id", "12345")
ctx = context.WithValue(ctx, "request_id", "req-abc123")
// InfoContextを使用してログ出力
slog.InfoContext(ctx, "hello", "count", 3)
// 比較用:通常のInfo
slog.Info("hello without context", "count", 3)
// 他のレベルでもContextが使える
slog.ErrorContext(ctx, "error occurred", "error", "database timeout")
slog.DebugContext(ctx, "debug info", "step", "validation")
}
出力例
{"time":"2009-11-10T23:00:00Z","level":"INFO","msg":"hello","count":3}
{"time":"2009-11-10T23:00:00Z","level":"INFO","msg":"hello without context","count":3}
{"time":"2009-11-10T23:00:00Z","level":"ERROR","msg":"error occurred","error":"database timeout"}
Wrap
Printfのようにできるやーつ
設定例
package main
import (
"fmt"
"log/slog"
"os"
)
func Infof(logger *slog.Logger, format string, args ...any) {
logger.Info(fmt.Sprintf(format, args...))
}
func main() {
logger := slog.New(slog.NewTextHandler(os.Stdout, nil))
Infof(logger, "Hello %s, you have %d messages", "Taro", 5)
}
出力例
time=2009-11-10T23:00:00.000Z level=INFO msg="Hello Taro, you have 5 messages"