log
The log package provides structured application logs, HTTP trace propagation, and request-wide event logging with tail sampling.
Core Components:
Logger,SetDefault,Debug/Info/Warn/Error: Package-level logging API built on top ofslog.New: Builds a text or JSON logger that automatically extracts values liketraceIdandserviceNamefromcontext.Context.TraceIDMiddleware: Adds a per-request trace ID to context and response headers.Event: Mutable wide-event model with attrs, steps, errors, severity, and duration.WideEventLogger: Writes finalizedEventvalues through aSampler.WideEventMiddleware: Creates request-wide events, stores them in context, and emits them after handlers finish.Sampler,SamplerFunc,DefaultSampler: Tail-sampling rules for keeping errors, slow requests, selected status codes, and random samples.EventFromContext: Fetches the current request-wide event from context usingWideEventKey.
Full package docs at pkg.go.dev
Step-by-step guide
Section titled “Step-by-step guide”-
Configure default structured logging
logger := log.New(os.Stdout, "json", slog.LevelInfo, nil)log.SetDefault(logger)This switches package-level logging to JSON and keeps context extraction enabled.
-
Add trace IDs to each request
server := httpserver.New("8080", 3*time.Second)server.Use(log.NewTraceIDMiddleware(nil, ""))With default arguments, the middleware stores IDs under
log.TraceIDKeyand writesPlatforma-Trace-Idresponse headers. -
Configure wide-event logging with sampling
wideLogger := log.NewWideEventLogger(os.Stdout,log.NewDefaultSampler(2*time.Second, 500, 0.05),"json",nil,)server.Use(log.NewWideEventMiddleware(wideLogger, "", nil))This keeps all error events, slow requests (>=2s),
5xxresponses, and 5% of the remaining traffic. -
Enrich events and logs inside handlers
server.HandleFunc("/users", func(w http.ResponseWriter, r *http.Request) {log.InfoContext(r.Context(), "users request started")if ev := log.EventFromContext(r.Context()); ev != nil {ev.AddStep(slog.LevelInfo, "query users table")ev.AddAttrs(map[string]any{"users.limit": 50})}w.WriteHeader(http.StatusOK)})InfoContextincludes request metadata (for exampletraceId), andEventFromContextlets handlers attach detailed wide-event data. -
Verify runtime output
{"level":"INFO","msg":"users request started","traceId":"14b3..."}{"level":"INFO","name":"http.request","duration":"12ms","request.status":200}The first line is an immediate log entry. The second line is the finalized request-wide event emitted after the response is completed.
Using with Application
Section titled “Using with Application”Integrate logging by registering an HTTP service and attaching log middlewares before app.Run:
app := application.New()
server := httpserver.New("8080", 3*time.Second)server.Use(log.NewTraceIDMiddleware(nil, ""))
wideLogger := log.NewWideEventLogger( os.Stdout, log.NewDefaultSampler(2*time.Second, 500, 0.05), "json", nil,)server.Use(log.NewWideEventMiddleware(wideLogger, "", nil))
server.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) { log.InfoContext(r.Context(), "health check") w.WriteHeader(http.StatusOK)})
app.RegisterService("api", server)app.Run(ctx)Complete example
Section titled “Complete example”package main
import ( "context" "errors" "log/slog" "os" "time"
"github.com/platforma-dev/platforma/log")
func main() { logger := log.NewWideEventLogger( os.Stdout, log.NewDefaultSampler(3*time.Second, 200, 0.1), "json", nil, )
ev := log.NewEvent("test_event")
ev.AddStep(slog.LevelInfo, "some step") ev.AddError(errors.New("some error")) ev.AddAttrs(map[string]any{ "attr1": 1, "attr2": true, })
logger.WriteEvent(context.Background(), ev)}