The default handler

April 7, 2026

Much like the older log package, log/slog ships with a “default logger”. You can use this logger without doing any configuration, just by calling any of the package-level logging functions:

slog.Error("oh noes!")

While you’d probably never want to use the default logger in a serious server application, it can be a convenience for small or throw-away utilities. But how does it work? That’s today’s topic!

Overview

The default handler formats the log record’s message, time, level, and attributes as a string and passes it to the log package.

2022/11/08 15:28:26 INFO hello count=3

So that’s doubly convenient—not only does it log things in a reasonable format, but it also passes them to the log package for backward compatibility. This means that if your application already takes advantage of the default log package’s logger, you don’t need to do any additional configuration to start using log/slog. Sweet!

But wait… how does the default log package’s logger work? Well, it’s pretty limited (which is, of course, largely why log/slog was added to replace it!) By default, it simply writes to STDERR. Though you can configure the default log.Logger… a little bit—mainly by redirecting where those logs go (e.g. to a file). But that’s a good segue into the default logger configuration we do care about—you can also configure the log/slog default logger, which we’ll talk about tomorrow!


Share this

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

Unsure? Browse the archive .

Related Content


Lazy attribute evaluation for JSONHandler

As I was writing yesterday’s post, a portion of the GoDoc confused me. I’ve now spent over 3 hours with Claude trying to parse the prose grammatically, build test cases, and make general sense of it. I think I finally have… Here’s hoping! So, yesterday we saw how you can lazy-evaluate some values when using TextHandler. But the proposed solution (pass a fmt.Stringer rather than a literal string) has other, likely uninintended, consequences if you’re using JSONHandler:


Attribute evaluation

log.With isn’t the only trick available for improving performance of logging. Many values you may want to pass to a logger need to be calculated. And sometimes that calculation is expensive. And if a log is omitted, because it’s a debug log, and our logger is only configured for info-and-up level, that calculation should be skipped. Performance considerations … The arguments to a log call are always evaluated, even if the log event is discarded.


Performance considerations

You’ve likely wondered why the log/slog package has some odd-looking functions and concepts in some places. Why do you set a handler’s level to a Leveler value, rather than a simple Level? Why so many ways to create key/value pairs ("key", "value" vs "key", slog.AnyValue("value") vs "key", slog.StringValue("value") vs slog.Any("key", "value") vs slog.String("key", "value"))? It mostly comes down to one thing: Performance. Or, more accurately, trying to balance performance with an easy-to-use API.

Get daily content like this in your inbox!

Subscribe