Article:

Intro

go1.21で構造化ログを出すslogが標準ライブラリに導入されました。これを使ってTraceIDを一緒にログに出すようにします。

前回: Goプログラムのトレースを取ってGrafanaCloudで可視化する

コード

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
type CustomHandler struct {
	slog.Handler
}

func (h *CustomHandler) Handle(ctx context.Context, r slog.Record) error {
	span := trace.SpanFromContext(ctx)
	if span.SpanContext().IsValid() {
		r.AddAttrs(slog.String("traceID", span.SpanContext().TraceID().String()))
		r.AddAttrs(slog.String("spanID", span.SpanContext().SpanID().String()))
	}

	return h.Handler.Handle(ctx, r)
}

func main() {
	handler := &CustomHandler{Handler: slog.NewJSONHandler(os.Stdout, nil)}
	logger := slog.New(handler)
	slog.SetDefault(logger)

	cleanup, err := setupTraceProvider("example-service", "1.0.0")
	if err != nil {
		panic(err)
	}
	defer cleanup()

	ctx, span := tracer.Start(context.Background(), "main")
	defer span.End()

	someFunc(ctx)
}

func someFunc(ctx context.Context) {
	ctx, span := tracer.Start(ctx, "someFunc")
	defer span.End()

	slog.InfoContext(ctx, "someFunc called")
}

全文gist

自動でtraceIDとspanIDを埋め込むためにカスタムハンドラを作成します。最初にslog.SetDefaultすることでその後のコードではslog.InfoContextの呼び出しだけでこのカスタムハンドラが呼び出されていますね。便利。

実行結果

1
2
3
[totegamma@19:00]~/slogtest$ go run main.go
{"time":"2023-10-31T19:00:45.673728302+09:00","level":"INFO","msg":"someFunc called","traceID":"464f9d7e3697569ebd922bcfdfd61245","spanID":"288320072aa2bf76"}
[totegamma@19:00]~/slogtest$

traceID/spanID込みでログ出力ができました。