neilotoole.io

Web presence of Neil O'Toole.

slogt v2

Back in 2023 I wrote about slogt, a tiny package that bridges Go’s slog and the stdlib testing package, so that structured log output shows up neatly correlated with the test that produced it.

It always had one deficiency. The only output sink testing.T offered was t.Log(string) — a function, not an io.Writer. So slogt had to format each record itself and hand the finished string to t.Log, which meant the source location that testing prepended pointed at slogt’s own internals rather than at the line that actually called the logger. I noted the limitation in the README:

Alas, given the available functionality on testing.T (i.e. the Helper method), and how slog is implemented, there’s no way to have the correct callsite printed.

A few weeks later, in May 2023, earthboundkid filed a Go proposal, quoting that very line, and arguing that the fix had to come from the Go side:

golang/go#59928: testing: Add T.Output() etc

The proposal was accepted, and Go 1.25 shipped testing.TB.Output(): an io.Writer that writes to the test log without prepending a source location. That’s precisely the hook slogt had always been missing.

So, slogt v2 now routes its output through testing.TB.Output(). The bogus callsite is gone, and you can finally turn on AddSource: true and get the real one:

f := slogt.Factory(func(w io.Writer) slog.Handler {
	return slog.NewTextHandler(w, &slog.HandlerOptions{AddSource: true})
})
log := slogt.New(t, f)

v2 is a breaking change: it requires Go 1.25, the import path is now github.com/neilotoole/slogt/v2, the old exported Bridge type is gone, and the mutable Default variable has been replaced by SetDefault().

Three years and a stdlib change later, slogt is now complete.