How to Set Up Structured Logging with Trace IDs in Go

Implement structured logging with trace IDs in Go by using log/slog with a custom handler to inject context values into JSON log records.

Go does not have a built-in structured logging package with trace IDs; you must implement this using the log/slog package combined with context and a UUID library. The following example demonstrates how to inject a trace ID into the context and retrieve it within a custom Handler to include it in every log record.

package main

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

	"github.com/google/uuid"
)

func main() {
	// Create a custom handler that adds TraceID from context
	handler := slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{
		AddSource: true,
	}).WithAttrs([]slog.Attr{slog.String("trace_id", "")})

	logger := slog.New(handler)

	// Generate a trace ID
	ctx := context.Background()
	ctx = context.WithValue(ctx, "trace_id", uuid.New().String())

	// Log with context
	logger.InfoContext(ctx, "Request started", "time", time.Now())
}

Note: The standard log/slog package does not automatically extract values from context into log attributes. You must create a custom Handler or use a wrapper function to inject the trace ID from the context into the log record before passing it to the handler.