I recently worked on happycontext, a Go wide-logging library that builds one structured event during a request and writes it when the request finishes.
The public API stayed compatible. The biggest improvement was a filtered zerolog write:
- Before: 237 ns
- After: 3.07 ns
- Result: 77× faster, 0 bytes, 0 allocations
A filtered write is a log call that the logger ignores because its level is below the configured minimum.
What changed
This work shipped in two pull requests:
The main changes were:
- Use
slog.LogAttrs instead of boxing every attribute into any.
- Reuse bounded attribute buffers.
- Avoid repeated configuration validation and map cloning.
- Select one policy instead of scanning every policy.
- Apply sampling before cloning event fields.
- Replace shared atomic sampler state with
math/rand/v2.
- Check logger levels before converting fields.
- Remove an unused
zerolog event that consumed an extra sampling decision.
Some results:
| Benchmark |
Before |
After |
Filtered slog write |
163 ns |
3.39 ns |
Filtered zap write |
354 ns |
24.3 ns |
Filtered zerolog write |
237 ns |
3.07 ns |
| 128-policy lookup |
1,842 ns |
395 ns |
| Parallel sampler |
42 ns |
1.3 ns |
The sampler became slightly slower in a serial microbenchmark, but more than 30× faster under parallel load. That was the important trade-off for request middleware.
Typical usage
A normal net/http service can keep its existing logger and add request fields through happycontext:
```go
logger := slog.New(slog.NewJSONHandler(os.Stdout, nil))
mw := stdhc.Middleware(hc.Config{
Sink: slogadapter.New(logger),
SamplingRate: 1.0,
Message: "request_completed",
})
mux := http.NewServeMux()
mux.HandleFunc("GET /orders/{id}", func(w http.ResponseWriter, r *http.Request) {
hc.Add(r.Context(), "user_id", "u_8472", "feature", "checkout")
if err := processOrder(r.Context()); err != nil {
hc.Error(r.Context(), err)
http.Error(w, "internal error", http.StatusInternalServerError)
return
}
w.WriteHeader(http.StatusOK)
})
_ = http.ListenAndServe(":8080", mw(mux))
```
The slog adapter can be replaced with the existing zap or zerolog adapters.
How AI was used
I used an AI coding agent to:
- Turn profiling results into a ranked plan.
- Inspect affected callers.
- Implement the two pull requests.
- Add adversarial and compatibility tests.
- Run benchmarks in separate worktrees.
- Review race-detector and allocation results.
- Challenge optimizations that did not matter.
AI did not decide what shipped. Measurements did.
We rejected an HTTP status fast path that saved about 0.33 ns. We also rejected a custom sampling threshold that improved the new path by less than 3%.
The final verification included race tests, go vet, static analysis, heap-retention checks, concurrent API tests, and repeated adapter benchmarks.
Reproduce the benchmarks
```bash
cd benches
go test -run '$' -bench 'BenchmarkAdapter' -benchmem -count=5
go test -run '$' -bench 'BenchmarkRouter' -benchmem -count=3
go test -run '$' -bench 'Benchmark' -benchmem
```
Use the same Go version, machine, and multiple benchmark samples when comparing results.
The percentages from the two pull requests should not be added together. They use different baselines and some gains overlap.
The general lesson was simple: the fastest work is often work you can prove is unnecessary.
- Check the log level before converting fields.
- Sample before cloning.
- Select one policy before normalizing everything.
- Reuse configuration only inside a read-only boundary.
- Remove shared contention from the hot path.
Project: github.com/happytoolin/happycontext
Full write-up: How We Used AI to Make happycontext Up to 77× Faster
EDIT - Fixed formatting