Logging and Observability

Overview

Production applications need structured logging, metrics, and tracing for debugging and monitoring.

Standard log Package

import "log"

log.Println("Info message")
log.Printf("User %d logged in", userID)
log.Fatal("Critical error")  // Calls os.Exit(1)
log.Panic("Panic!")          // Calls panic()

JSON Output

logger := slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{
    Level: slog.LevelDebug,
}))
slog.SetDefault(logger)

Context Integration

slog can automatically extract values from context using a custom handler or slog.Attr.

func handler(w http.ResponseWriter, r *http.Request) {
    logger := slog.With("request_id", r.Header.Get("X-Request-ID"))
    logger.Info("started")
}

Log Levels

slog provides four levels by default: Debug, Info, Warn, and Error. - slog.Debug("debug info") - slog.Info("informational") - slog.Warn("warning") - slog.Error("error", "err", err)

Custom Logger

logger := log.New(os.Stderr, "API: ", log.Ldate|log.Ltime|log.Lshortfile)
logger.Println("Starting server")

Metrics

import "expvar"

var (
    requests = expvar.NewInt("requests")
    errors   = expvar.NewInt("errors")
)

func handler(w http.ResponseWriter, r *http.Request) {
    requests.Add(1)
    // ...
}

// Expose at /debug/vars
import _ "expvar"

Tracing

import "runtime/trace"

f, _ := os.Create("trace.out")
trace.Start(f)
defer trace.Stop()

// Run with: go tool trace trace.out

Summary

Package Purpose
log Simple logging
log/slog Structured logging
expvar Metrics exposure
runtime/trace Execution tracing