slog.HandlerOptions

September 19, 2026

Now we’ll begin looking at HandlerOptions. Despite the Handler-centricity, this is something we care heavily about as mere users of the slog library.

Whenever you instantiate either slog.JSONHandler or slog.TextHandler, you have the option of providing a HandlerOptions object, to tweak the default handler behavior.

We’ll look at each of the config options, one at a time.

type HandlerOptions

type HandlerOptions struct {
	// AddSource causes the handler to compute the source code position
	// of the log statement and add a SourceKey attribute to the output.
	AddSource bool

The first option, AddSource, is honestly something I’ve never felt a need to use. But it’s good to know it’s there, in case you ever do.

When enabled, it adds a source key/value pair to each log, as you can see in this example:

func main() {
	logger := slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{AddSource: true}))
	logger.Info("Hello, 世界")
}

Output:

time=2009-11-10T23:00:00.000Z level=INFO source=/tmp/sandbox837883246/prog.go:12 msg="Hello, 世界"

The main reason I don’t use this, is that I generally include a full stack trace in my error objects, which then get logged:

2024-06-10T12:34:56Z ERROR Failed to connect to database
github.com/myorg/myapp/db.Connect
    /src/bootdev/course-draft-learn-logging/examples/errors/stacktrace/main.go:25
github.com/myorg/myapp/handlers.GetUser
    /src/bootdev/course-draft-learn-logging/examples/errors/stacktrace/main.go:40
github.com/myorg/myapp/server.ServeHTTP
    /src/bootdev/course-draft-learn-logging/examples/errors/stacktrace/main.go:55
net/http.serverHandler.ServeHTTP
    /usr/local/go/src/net/http/server.go:2887
net/http.(*conn).serve
    /usr/local/go/src/net/http/server.go:1952

If you’re interested in a much more detailed look at this particular strategy, as well as other logging and observability topics, I go into much more detail on this in the course I created for Boot.dev, Logging and Observability in Go. And if you use code JHALL when you sign up, you can get 25% off your first year!


Share this

Direct to your inbox, daily. I respect your privacy .

Unsure? Browse the archive .

Related Content


The better test alternative to slog.DiscardHandler

Last time I described slog.DiscardHandler as a viable way to silence logs in tests. Now I want to tell you why I never use that option, and you probably shouldn’t, either. But first a story. The slog package was introduced with Go 1.21 in August of 2023. It didn’t yet have slog.DiscardHandler, so you had to roll your own. But that was easy: logger := slog.New(slog.NewTextHandler(io.Discard, nil)) Easy as it was, it was also annoying.


slog.DiscardHandler

Now that we’ve made it through the Handler interface, let’s look at the first of the implementations provided by the standard library: the DiscardHandler. var DiscardHandler Handler = discardHandler{} DiscardHandler discards all log output. DiscardHandler.Enabled returns false for all Levels. Why would you ever want a discard handler? Two likely scenarios come to mind. The one where I most frequently use it, is testing. You may not wish to log anything during a test, and this is a simple way to do that:


slog.Handler

I’m probably doing this in backwards order, but that’s the order the GoDoc presents it… Now that we’ve looked at each of the methods of the Handler interface, we come to its general description: type Handler A Handler handles log records produced by a Logger. A typical handler may print log records to standard error, or write them to a file or database, or perhaps augment them with additional attributes and pass them on to another handler.

Get daily content like this in your inbox!

Subscribe