2 min read
Values
TIL Logger.LogAttrs is a thing! But what is that thing?? Yesterday I mentioned that using an slog.Attr can be marginally more efficient than using naked key/value pairs in a log call. While true, that glosses over what is likely to be a much more impactful performance consideration in certain applications… Attrs and Values … The value part of an Attr is a type called Value. Like an [any], a Value can hold any Go value, but it can represent typical values, including all numbers and strings, without an allocation.
2 min read
Attrs
We’ve been talking about key/value pairs. The log/slog package has a name for these: Attr (short for “attribute”). And there’s more than one way to build an attribute: Attrs and Values An Attr is a key-value pair. The Logger output methods accept Attrs as well as alternating keys and values. The statement slog.Info("hello", slog.Int("count", 3)) behaves the same as slog.Info("hello", "count", 3) There are convenience constructors for Attr such as Int, String, and Bool for common types, as well as the function Any for constructing Attrs of any type.
2 min read
Contexts
[**Idiomatic Testing in Go**](/idiomatic-testing/) starts TOMORROW! My my, how time flies! There are still a few seats available, and there’s still time to sign up. Learn how to get the most out of the tests in your Go app! One feature I often see overlooked capability of the log/slog package, is to extract log key/value pairs from context: Contexts Some handlers may wish to include information from the context.Context that is available at the call site.
2 min read
More with Groups
Organizing log key/value pairs by group is a nice way to organize your logging data, but what about organizing the way your application groups data? Maybe you want all logs created by a particular code path to be grouped together. How can you accomplish this? Enter WithGroup… Groups … Use Logger.WithGroup to qualify all of a Logger’s output with a group name. Calling WithGroup on a Logger results in a new Logger with the same Handler as the original, but with all its attributes qualified by the group name.
1 min read
Groups
Early bird registration for [**Idiomatic Testing in Go**](/idiomatic-testing/) ends today! Not sure how to adapt your xUnit habits to Go? This is the course for you! Sign up today to save 25% over the full price. – Sometimes you want to group several key/value attributes together when logging. Maybe different aspects of an error (error_code, error_detail, stacktrace, etc), or different aspects of an HTTP response (bytes_sent, status_code, etc). The log/slog package gives us this!
2 min read
Filtering logs by level
Levels In an application, you may wish to log messages only at a certain level or greater. One common configuration is to log messages at Info or higher levels, suppressing debug logging until it is needed. The built-in handlers can be configured with the minimum level to output by setting [HandlerOptions.Level]. The program’s main function typically does this. The default value is LevelInfo. Pretty straight forward, eh? Only want to log Info-and-above inproduction?
2 min read
Log levels
I'm launching a new live course: **Idiomatic Testing in Go**. The course begins May 5. Early-bird pricing is in effect until April 28. Why Go avoids assert libraries Better alternatives to mocks Make writing tests fun! See pricing & reserve → log/slog provides some rather sophisticated capabilities around log levels. We’ll get into it, but the good news is, you don’t need to care about how sophisticated it can get, if you don’t care.
Subscribe to Boldly Go: Daily
Every day I'll send you advice to improve your understanding of Go. Don't miss out! I will respect your inbox, and honor my privacy policy.
Unsure? Browse the archive.
1 min read
Logging common fields
It’s common that you’ll want to include certain attributes in all logs in an application or component. log/slog makes this pretty easy. Overview … Some attributes are common to many log calls. For example, you may wish to include the URL or trace identifier of a server request with all log events arising from the request. Rather than repeat the attribute with every log call, you can use Logger.With to construct a new Logger containing the attributes:
1 min read
Handler configuration
The default slog handlers are quite configurable. Overview … Both TextHandler and JSONHandler can be configured with HandlerOptions. There are options for setting the minimum level (see Levels, below), displaying the source file and line of the log call, and modifying attributes before they are logged. While HandlerOptions only exposes three fields: AddSource bool Level Leveler ReplaceAttr func(groups []string, a Attr) Attr The last one provides an immense amount of flexibility, letting you filter, replace, or augment log key/value pairs as they are processed.
1 min read
Chosing an slog handler
log/slog ships with two default handlers: the TextHandler and the JSONHandler. Overview … For more control over the output format, create a logger with a different handler. This statement uses New to create a new logger with a TextHandler that writes structured records in text form to standard error: logger := slog.New(slog.NewTextHandler(os.Stderr, nil)) TextHandler output is a sequence of key=value pairs, easily and unambiguously parsed by machine. This statement: logger.Info("hello", "count", 3) produces this output:
1 min read
Overriding the default handler
Today I’m going to jump around a bit in the GoDoc, to talk about a topic I mentioned last time: how to override the default logger. Overview … Setting a logger as the default with slog.SetDefault(logger) will cause the top-level functions like Info to use it. SetDefault also updates the default logger used by the log package, so that existing applications that use log.Printf and related functions will send log records to the logger’s handler without needing to be rewritten.