Handler level

September 28, 2026

Each handler has an optional Level value, which controls which logs to drop, and which to actually log:

type HandlerOptions

type HandlerOptions struct {
…
	// Level reports the minimum record level that will be logged.
	// The handler discards records with lower levels.
	// If Level is nil, the handler assumes LevelInfo.
	// The handler calls Level.Level for each record processed;
	// to adjust the minimum level dynamically, use a LevelVar.
	Level Leveler

For common usage, you’ll simply set this to one of the defined slog.Level values: Debug, Info, Warn, or Error.

But notice that the type of this field isn’t slog.Level, it’s slog.Leveler, which is actually an interface type. We’ll talk in more detail about how to take advantage of this soon, but it’s quite handy because it allows you to easily change the handler’s level dynamically at runtime, by passing a value that satisfies the slog.Leveler interface. This allows you to change the handler’s level via a database option, or by reading a config file dynamically at runtime, or any other number of ways.


Share this

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

Unsure? Browse the archive .

Related Content


Test logging with ReplaceAttr

Today’s topic is probably the most interesting, subtle, and complicated of the three HandlerOptions fields: ReplaceAttr. type HandlerOptions type HandlerOptions struct { … // ReplaceAttr is called to rewrite each non-group attribute before it is logged. // The attribute's value has been resolved (see [Value.Resolve]). // If ReplaceAttr returns a zero Attr, the attribute is discarded. // // The built-in attributes with keys "time", "level", "source", and "msg" // are passed to this function, except that time is omitted // if zero, and source is omitted if AddSource is false.


slog.HandlerOptions

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.


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.

Get daily content like this in your inbox!

Subscribe