Movatterモバイル変換


[0]ホーム

URL:


slog

packagestandard library
go1.25.2Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 7, 2025 License:BSD-3-ClauseImports:23Imported by:56,840

Details

Repository

cs.opensource.google/go/go

Links

Documentation

Overview

Package slog provides structured logging,in which log records include a message,a severity level, and various other attributesexpressed as key-value pairs.

It defines a type,Logger,which provides several methods (such asLogger.Info andLogger.Error)for reporting events of interest.

Each Logger is associated with aHandler.A Logger output method creates aRecord from the method argumentsand passes it to the Handler, which decides how to handle it.There is a default Logger accessible through top-level functions(such asInfo andError) that call the corresponding Logger methods.

A log record consists of a time, a level, a message, and a set of key-valuepairs, where the keys are strings and the values may be of any type.As an example,

slog.Info("hello", "count", 3)

creates a record containing the time of the call,a level of Info, the message "hello", and a singlepair with key "count" and value 3.

TheInfo top-level function calls theLogger.Info method on the default Logger.In addition toLogger.Info, there are methods for Debug, Warn and Error levels.Besides these convenience methods for common levels,there is also aLogger.Log method which takes the level as an argument.Each of these methods has a corresponding top-level function that uses thedefault logger.

The default handler formats the log record's message, time, level, and attributesas a string and passes it to thelog package.

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

For more control over the output format, create a logger with a different handler.This statement usesNew to create a new logger with aTextHandlerthat 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 unambiguouslyparsed by machine. This statement:

logger.Info("hello", "count", 3)

produces this output:

time=2022-11-08T15:28:26.000-05:00 level=INFO msg=hello count=3

The package also providesJSONHandler, whose output is line-delimited JSON:

logger := slog.New(slog.NewJSONHandler(os.Stdout, nil))logger.Info("hello", "count", 3)

produces this output:

{"time":"2022-11-08T15:28:26.000000000-05:00","level":"INFO","msg":"hello","count":3}

BothTextHandler andJSONHandler can be configured withHandlerOptions.There are options for setting the minimum level (see Levels, below),displaying the source file and line of the log call, andmodifying attributes before they are logged.

Setting a logger as the default with

slog.SetDefault(logger)

will cause the top-level functions likeInfo to use it.SetDefault also updates the default logger used by thelog package,so that existing applications that uselog.Printf and related functionswill send log records to the logger's handler without needing to be rewritten.

Some attributes are common to many log calls.For example, you may wish to include the URL or trace identifier of a server requestwith all log events arising from the request.Rather than repeat the attribute with every log call, you can useLogger.Withto construct a new Logger containing the attributes:

logger2 := logger.With("url", r.URL)

The arguments to With are the same key-value pairs used inLogger.Info.The result is a new Logger with the same handler as the original, but additionalattributes that will appear in the output of every call.

Levels

ALevel is an integer representing the importance or severity of a log event.The higher the level, the more severe the event.This package defines constants for the most common levels,but any int can be used as a level.

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 bysetting [HandlerOptions.Level].The program's `main` function typically does this.The default value is LevelInfo.

Setting the [HandlerOptions.Level] field to aLevel valuefixes the handler's minimum level throughout its lifetime.Setting it to aLevelVar allows the level to be varied dynamically.A LevelVar holds a Level and is safe to read or write from multiplegoroutines.To vary the level dynamically for an entire program, first initializea global LevelVar:

var programLevel = new(slog.LevelVar) // Info by default

Then use the LevelVar to construct a handler, and make it the default:

h := slog.NewJSONHandler(os.Stderr, &slog.HandlerOptions{Level: programLevel})slog.SetDefault(slog.New(h))

Now the program can change its logging level with a single statement:

programLevel.Set(slog.LevelDebug)

Groups

Attributes can be collected into groups.A group has a name that is used to qualify the names of its attributes.How this qualification is displayed depends on the handler.TextHandler separates the group and attribute names with a dot.JSONHandler treats each group as a separate JSON object, with the group name as the key.

UseGroup to create a Group attribute from a name and a list of key-value pairs:

slog.Group("request",    "method", r.Method,    "url", r.URL)

TextHandler would display this group as

request.method=GET request.url=http://example.com

JSONHandler would display it as

"request":{"method":"GET","url":"http://example.com"}

UseLogger.WithGroup to qualify all of a Logger's outputwith a group name. Calling WithGroup on a Logger results in anew Logger with the same Handler as the original, but with allits attributes qualified by the group name.

This can help prevent duplicate attribute keys in large systems,where subsystems might use the same keys.Pass each subsystem a different Logger with its own group name so thatpotential duplicates are qualified:

logger := slog.Default().With("id", systemID)parserLogger := logger.WithGroup("parser")parseInput(input, parserLogger)

When parseInput logs with parserLogger, its keys will be qualified with "parser",so even if it uses the common key "id", the log line will have distinct keys.

Contexts

Some handlers may wish to include information from thecontext.Context that isavailable at the call site. One example of such informationis the identifier for the current span when tracing is enabled.

TheLogger.Log andLogger.LogAttrs methods take a context as a firstargument, as do their corresponding top-level functions.

Although the convenience methods on Logger (Info and so on) and thecorresponding top-level functions do not take a context, the alternatives endingin "Context" do. For example,

slog.InfoContext(ctx, "message")

It is recommended to pass a context to an output method if one is available.

Attrs and Values

AnAttr is a key-value pair. The Logger output methods accept Attrs as well asalternating 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 forAttr such asInt,String, andBoolfor common types, as well as the functionAny for constructing Attrs of anytype.

The value part of an Attr is a type calledValue.Like an [any], a Value can hold any Go value,but it can represent typical values, including all numbers and strings,without an allocation.

For the most efficient log output, useLogger.LogAttrs.It is similar toLogger.Log but accepts only Attrs, not alternatingkeys and values; this allows it, too, to avoid allocation.

The call

logger.LogAttrs(ctx, slog.LevelInfo, "hello", slog.Int("count", 3))

is the most efficient way to achieve the same output as

slog.InfoContext(ctx, "hello", "count", 3)

Customizing a type's logging behavior

If a type implements theLogValuer interface, theValue returned from its LogValuemethod is used for logging. You can use this to control how values of the typeappear in logs. For example, you can redact secret information like passwords,or gather a struct's fields in a Group. See the examples underLogValuer fordetails.

A LogValue method may return a Value that itself implementsLogValuer. TheValue.Resolvemethod handles these cases carefully, avoiding infinite loops and unbounded recursion.Handler authors and others may wish to useValue.Resolve instead of calling LogValue directly.

Wrapping output methods

The logger functions use reflection over the call stack to find the file nameand line number of the logging call within the application. This can produceincorrect source information for functions that wrap slog. For instance, if youdefine this function in file mylog.go:

func Infof(logger *slog.Logger, format string, args ...any) {    logger.Info(fmt.Sprintf(format, args...))}

and you call it like this in main.go:

Infof(slog.Default(), "hello, %s", "world")

then slog will report the source file as mylog.go, not main.go.

A correct implementation of Infof will obtain the source location(pc) and pass it to NewRecord.The Infof function in the package-level example called "wrapping"demonstrates how to do this.

Working with Records

Sometimes a Handler will need to modify a Recordbefore passing it on to another Handler or backend.A Record contains a mixture of simple public fields (e.g. Time, Level, Message)and hidden fields that refer to state (such as attributes) indirectly. Thismeans that modifying a simple copy of a Record (e.g. by callingRecord.Add orRecord.AddAttrs to add attributes)may have unexpected effects on the original.Before modifying a Record, useRecord.Clone tocreate a copy that shares no state with the original,or create a new Record withNewRecordand build up its Attrs by traversing the old ones withRecord.Attrs.

Performance considerations

If profiling your application demonstrates that logging is taking significant time,the following suggestions may help.

If many log lines have a common attribute, useLogger.With to create a Logger withthat attribute. The built-in handlers will format that attribute only once, at thecall toLogger.With. TheHandler interface is designed to allow that optimization,and a well-written Handler should take advantage of it.

The arguments to a log call are always evaluated, even if the log event is discarded.If possible, defer computation so that it happens only if the value is actually logged.For example, consider the call

slog.Info("starting request", "url", r.URL.String())  // may compute String unnecessarily

The URL.String method will be called even if the logger discards Info-level events.Instead, pass the URL directly:

slog.Info("starting request", "url", &r.URL) // calls URL.String only if needed

The built-inTextHandler will call its String method, but onlyif the log event is enabled.Avoiding the call to String also preserves the structure of the underlying value.For exampleJSONHandler emits the components of the parsed URL as a JSON object.If you want to avoid eagerly paying the cost of the String callwithout causing the handler to potentially inspect the structure of the value,wrap the value in a fmt.Stringer implementation that hides its Marshal methods.

You can also use theLogValuer interface to avoid unnecessary work in disabled logcalls. Say you need to log some expensive value:

slog.Debug("frobbing", "value", computeExpensiveValue(arg))

Even if this line is disabled, computeExpensiveValue will be called.To avoid that, define a type implementing LogValuer:

type expensive struct { arg int }func (e expensive) LogValue() slog.Value {    return slog.AnyValue(computeExpensiveValue(e.arg))}

Then use a value of that type in log calls:

slog.Debug("frobbing", "value", expensive{arg})

Now computeExpensiveValue will only be called when the line is enabled.

The built-in handlers acquire a lock before callingio.Writer.Writeto ensure that exactly oneRecord is written at a time in its entirety.Although each log record has a timestamp,the built-in handlers do not use that time to sort the written records.User-defined handlers are responsible for their own locking and sorting.

Writing a handler

For a guide to writing a custom handler, seehttps://golang.org/s/slog-handler-guide.

Example (DiscardHandler)
package mainimport ("log/slog""os")func main() {removeTime := func(groups []string, a slog.Attr) slog.Attr {if a.Key == slog.TimeKey && len(groups) == 0 {return slog.Attr{}}return a}// A slog.TextHandler can output log messages.logger1 := slog.New(slog.NewTextHandler(os.Stdout,&slog.HandlerOptions{ReplaceAttr: removeTime},))logger1.Info("message 1")// A slog.DiscardHandler will discard all messages.logger2 := slog.New(slog.DiscardHandler)logger2.Info("message 2")}
Output:level=INFO msg="message 1"

Example (Wrapping)
package mainimport ("context""fmt""log/slog""os""path/filepath""runtime""time")// Infof is an example of a user-defined logging function that wraps slog.// The log record contains the source position of the caller of Infof.func Infof(logger *slog.Logger, format string, args ...any) {if !logger.Enabled(context.Background(), slog.LevelInfo) {return}var pcs [1]uintptrruntime.Callers(2, pcs[:]) // skip [Callers, Infof]r := slog.NewRecord(time.Now(), slog.LevelInfo, fmt.Sprintf(format, args...), pcs[0])_ = logger.Handler().Handle(context.Background(), r)}func main() {replace := func(groups []string, a slog.Attr) slog.Attr {// Remove time.if a.Key == slog.TimeKey && len(groups) == 0 {return slog.Attr{}}// Remove the directory from the source's filename.if a.Key == slog.SourceKey {source := a.Value.Any().(*slog.Source)source.File = filepath.Base(source.File)}return a}logger := slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{AddSource: true, ReplaceAttr: replace}))Infof(logger, "message, %s", "formatted")}
Output:level=INFO source=example_wrap_test.go:43 msg="message, formatted"

Index

Examples

Constants

View Source
const (// TimeKey is the key used by the built-in handlers for the time// when the log method is called. The associated Value is a [time.Time].TimeKey = "time"// LevelKey is the key used by the built-in handlers for the level// of the log call. The associated value is a [Level].LevelKey = "level"// MessageKey is the key used by the built-in handlers for the// message of the log call. The associated value is a string.MessageKey = "msg"// SourceKey is the key used by the built-in handlers for the source file// and line of the log call. The associated value is a *[Source].SourceKey = "source")

Keys for "built-in" attributes.

Variables

This section is empty.

Functions

funcDebug

func Debug(msgstring, args ...any)

Debug callsLogger.Debug on the default logger.

funcDebugContext

func DebugContext(ctxcontext.Context, msgstring, args ...any)

DebugContext callsLogger.DebugContext on the default logger.

funcError

func Error(msgstring, args ...any)

Error callsLogger.Error on the default logger.

funcErrorContext

func ErrorContext(ctxcontext.Context, msgstring, args ...any)

ErrorContext callsLogger.ErrorContext on the default logger.

funcInfo

func Info(msgstring, args ...any)

Info callsLogger.Info on the default logger.

funcInfoContext

func InfoContext(ctxcontext.Context, msgstring, args ...any)

InfoContext callsLogger.InfoContext on the default logger.

funcLog

func Log(ctxcontext.Context, levelLevel, msgstring, args ...any)

Log callsLogger.Log on the default logger.

funcLogAttrs

func LogAttrs(ctxcontext.Context, levelLevel, msgstring, attrs ...Attr)

LogAttrs callsLogger.LogAttrs on the default logger.

funcNewLogLogger

func NewLogLogger(hHandler, levelLevel) *log.Logger

NewLogLogger returns a newlog.Logger such that each call to its Output methoddispatches a Record to the specified handler. The logger acts as a bridge fromthe older log API to newer structured logging handlers.

funcSetDefault

func SetDefault(l *Logger)

SetDefault makes l the defaultLogger, which is used bythe top-level functionsInfo,Debug and so on.After this call, output from the log package's default Logger(as withlog.Print, etc.) will be logged using l's Handler,at a level controlled bySetLogLoggerLevel.

funcWarn

func Warn(msgstring, args ...any)

Warn callsLogger.Warn on the default logger.

funcWarnContext

func WarnContext(ctxcontext.Context, msgstring, args ...any)

WarnContext callsLogger.WarnContext on the default logger.

Types

typeAttr

type Attr struct {KeystringValueValue}

An Attr is a key-value pair.

funcAny

func Any(keystring, valueany)Attr

Any returns an Attr for the supplied value.SeeAnyValue for how values are treated.

funcBool

func Bool(keystring, vbool)Attr

Bool returns an Attr for a bool.

funcDuration

func Duration(keystring, vtime.Duration)Attr

Duration returns an Attr for atime.Duration.

funcFloat64

func Float64(keystring, vfloat64)Attr

Float64 returns an Attr for a floating-point number.

funcGroup

func Group(keystring, args ...any)Attr

Group returns an Attr for a GroupValue.The first argument is the key; the remaining argumentsare converted to Attrs as inLogger.Log.

Use Group to collect several key-value pairs under a singlekey on a log line, or as the result of LogValuein order to log a single value as multiple Attrs.

Example
package mainimport ("log/slog""net/http""os""time")func main() {r, _ := http.NewRequest("GET", "localhost", nil)// ...logger := slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{ReplaceAttr: func(groups []string, a slog.Attr) slog.Attr {if a.Key == slog.TimeKey && len(groups) == 0 {return slog.Attr{}}return a},}),)logger.Info("finished",slog.Group("req",slog.String("method", r.Method),slog.String("url", r.URL.String())),slog.Int("status", http.StatusOK),slog.Duration("duration", time.Second))}
Output:level=INFO msg=finished req.method=GET req.url=localhost status=200 duration=1s

funcGroupAttrsadded ingo1.25.0

func GroupAttrs(keystring, attrs ...Attr)Attr

GroupAttrs returns an Attr for a GroupValueconsisting of the given Attrs.

GroupAttrs is a more efficient version ofGroupthat accepts onlyAttr values.

Example
package mainimport ("context""log/slog""net/http""os")func main() {r, _ := http.NewRequest("POST", "localhost", http.NoBody)// ...logger := slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{Level: slog.LevelDebug,ReplaceAttr: func(groups []string, a slog.Attr) slog.Attr {if a.Key == slog.TimeKey && len(groups) == 0 {return slog.Attr{}}return a},}),)// Use []slog.Attr to accumulate attributes.attrs := []slog.Attr{slog.String("method", r.Method)}attrs = append(attrs, slog.String("url", r.URL.String()))if r.Method == "POST" {attrs = append(attrs, slog.Int("content-length", int(r.ContentLength)))}// Group the attributes under a key.logger.LogAttrs(context.Background(), slog.LevelInfo,"finished",slog.Int("status", http.StatusOK),slog.GroupAttrs("req", attrs...),)// Groups with empty keys are inlined.logger.LogAttrs(context.Background(), slog.LevelInfo,"finished",slog.Int("status", http.StatusOK),slog.GroupAttrs("", attrs...),)}
Output:level=INFO msg=finished status=200 req.method=POST req.url=localhost req.content-length=0level=INFO msg=finished status=200 method=POST url=localhost content-length=0

funcInt

func Int(keystring, valueint)Attr

Int converts an int to an int64 and returnsan Attr with that value.

funcInt64

func Int64(keystring, valueint64)Attr

Int64 returns an Attr for an int64.

funcString

func String(key, valuestring)Attr

String returns an Attr for a string value.

funcTime

func Time(keystring, vtime.Time)Attr

Time returns an Attr for atime.Time.It discards the monotonic portion.

funcUint64

func Uint64(keystring, vuint64)Attr

Uint64 returns an Attr for a uint64.

func (Attr)Equal

func (aAttr) Equal(bAttr)bool

Equal reports whether a and b have equal keys and values.

func (Attr)String

func (aAttr) String()string

typeHandler

type Handler interface {// Enabled reports whether the handler handles records at the given level.// The handler ignores records whose level is lower.// It is called early, before any arguments are processed,// to save effort if the log event should be discarded.// If called from a Logger method, the first argument is the context// passed to that method, or context.Background() if nil was passed// or the method does not take a context.// The context is passed so Enabled can use its values// to make a decision.Enabled(context.Context,Level)bool// Handle handles the Record.// It will only be called when Enabled returns true.// The Context argument is as for Enabled.// It is present solely to provide Handlers access to the context's values.// Canceling the context should not affect record processing.// (Among other things, log messages may be necessary to debug a// cancellation-related problem.)//// Handle methods that produce output should observe the following rules://   - If r.Time is the zero time, ignore the time.//   - If r.PC is zero, ignore it.//   - Attr's values should be resolved.//   - If an Attr's key and value are both the zero value, ignore the Attr.//     This can be tested with attr.Equal(Attr{}).//   - If a group's key is empty, inline the group's Attrs.//   - If a group has no Attrs (even if it has a non-empty key),//     ignore it.//// [Logger] discards any errors from Handle. Wrap the Handle method to// process any errors from Handlers.Handle(context.Context,Record)error// WithAttrs returns a new Handler whose attributes consist of// both the receiver's attributes and the arguments.// The Handler owns the slice: it may retain, modify or discard it.WithAttrs(attrs []Attr)Handler// WithGroup returns a new Handler with the given group appended to// the receiver's existing groups.// The keys of all subsequent attributes, whether added by With or in a// Record, should be qualified by the sequence of group names.//// How this qualification happens is up to the Handler, so long as// this Handler's attribute keys differ from those of another Handler// with a different sequence of group names.//// A Handler should treat WithGroup as starting a Group of Attrs that ends// at the end of the log event. That is,////     logger.WithGroup("s").LogAttrs(ctx, level, msg, slog.Int("a", 1), slog.Int("b", 2))//// should behave like////     logger.LogAttrs(ctx, level, msg, slog.Group("s", slog.Int("a", 1), slog.Int("b", 2)))//// If the name is empty, WithGroup returns the receiver.WithGroup(namestring)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 themwith additional attributes and pass them on to another handler.

Any of the Handler's methods may be called concurrently with itselfor with other methods. It is the responsibility of the Handler tomanage this concurrency.

Users of the slog package should not invoke Handler methods directly.They should use the methods ofLogger instead.

Before implementing your own handler, consulthttps://go.dev/s/slog-handler-guide.

Example (LevelHandler)

This example shows how to Use a LevelHandler to change the level of anexisting Handler while preserving its other behavior.

This example demonstrates increasing the log level to reduce a logger'soutput.

Another typical use would be to decrease the log level (to LevelDebug, say)during a part of the program that was suspected of containing a bug.

package mainimport ("context""log/slog""os")// A LevelHandler wraps a Handler with an Enabled method// that returns false for levels below a minimum.type LevelHandler struct {level   slog.Levelerhandler slog.Handler}// NewLevelHandler returns a LevelHandler with the given level.// All methods except Enabled delegate to h.func NewLevelHandler(level slog.Leveler, h slog.Handler) *LevelHandler {// Optimization: avoid chains of LevelHandlers.if lh, ok := h.(*LevelHandler); ok {h = lh.Handler()}return &LevelHandler{level, h}}// Enabled implements Handler.Enabled by reporting whether// level is at least as large as h's level.func (h *LevelHandler) Enabled(_ context.Context, level slog.Level) bool {return level >= h.level.Level()}// Handle implements Handler.Handle.func (h *LevelHandler) Handle(ctx context.Context, r slog.Record) error {return h.handler.Handle(ctx, r)}// WithAttrs implements Handler.WithAttrs.func (h *LevelHandler) WithAttrs(attrs []slog.Attr) slog.Handler {return NewLevelHandler(h.level, h.handler.WithAttrs(attrs))}// WithGroup implements Handler.WithGroup.func (h *LevelHandler) WithGroup(name string) slog.Handler {return NewLevelHandler(h.level, h.handler.WithGroup(name))}// Handler returns the Handler wrapped by h.func (h *LevelHandler) Handler() slog.Handler {return h.handler}// This example shows how to Use a LevelHandler to change the level of an// existing Handler while preserving its other behavior.//// This example demonstrates increasing the log level to reduce a logger's// output.//// Another typical use would be to decrease the log level (to LevelDebug, say)// during a part of the program that was suspected of containing a bug.func main() {removeTime := func(groups []string, a slog.Attr) slog.Attr {if a.Key == slog.TimeKey && len(groups) == 0 {return slog.Attr{}}return a}th := slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{ReplaceAttr: removeTime})logger := slog.New(NewLevelHandler(slog.LevelWarn, th))logger.Info("not printed")logger.Warn("printed")}
Output:level=WARN msg=printed

var DiscardHandlerHandler = discardHandler{}

DiscardHandler discards all log output.DiscardHandler.Enabled returns false for all Levels.

typeHandlerOptions

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.AddSourcebool// 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.LevelLeveler// 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.//// The first argument is a list of currently open groups that contain the// Attr. It must not be retained or modified. ReplaceAttr is never called// for Group attributes, only their contents. For example, the attribute// list////     Int("a", 1), Group("g", Int("b", 2)), Int("c", 3)//// results in consecutive calls to ReplaceAttr with the following arguments:////     nil, Int("a", 1)//     []string{"g"}, Int("b", 2)//     nil, Int("c", 3)//// ReplaceAttr can be used to change the default keys of the built-in// attributes, convert types (for example, to replace a `time.Time` with the// integer seconds since the Unix epoch), sanitize personal information, or// remove attributes from the output.ReplaceAttr func(groups []string, aAttr)Attr}

HandlerOptions are options for aTextHandler orJSONHandler.A zero HandlerOptions consists entirely of default values.

Example (CustomLevels)

This example demonstrates using custom log levels and custom log level names.In addition to the default log levels, it introduces Trace, Notice, andEmergency levels. The ReplaceAttr changes the way levels are printed for boththe standard log levels and the custom log levels.

package mainimport ("context""log/slog""os")func main() {// Exported constants from a custom logging package.const (LevelTrace     = slog.Level(-8)LevelDebug     = slog.LevelDebugLevelInfo      = slog.LevelInfoLevelNotice    = slog.Level(2)LevelWarning   = slog.LevelWarnLevelError     = slog.LevelErrorLevelEmergency = slog.Level(12))th := slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{// Set a custom level to show all log output. The default value is// LevelInfo, which would drop Debug and Trace logs.Level: LevelTrace,ReplaceAttr: func(groups []string, a slog.Attr) slog.Attr {// Remove time from the output for predictable test output.if a.Key == slog.TimeKey {return slog.Attr{}}// Customize the name of the level key and the output string, including// custom level values.if a.Key == slog.LevelKey {// Rename the level key from "level" to "sev".a.Key = "sev"// Handle custom level values.level := a.Value.Any().(slog.Level)// This could also look up the name from a map or other structure, but// this demonstrates using a switch statement to rename levels. For// maximum performance, the string values should be constants, but this// example uses the raw strings for readability.switch {case level < LevelDebug:a.Value = slog.StringValue("TRACE")case level < LevelInfo:a.Value = slog.StringValue("DEBUG")case level < LevelNotice:a.Value = slog.StringValue("INFO")case level < LevelWarning:a.Value = slog.StringValue("NOTICE")case level < LevelError:a.Value = slog.StringValue("WARNING")case level < LevelEmergency:a.Value = slog.StringValue("ERROR")default:a.Value = slog.StringValue("EMERGENCY")}}return a},})logger := slog.New(th)ctx := context.Background()logger.Log(ctx, LevelEmergency, "missing pilots")logger.Error("failed to start engines", "err", "missing fuel")logger.Warn("falling back to default value")logger.Log(ctx, LevelNotice, "all systems are running")logger.Info("initiating launch")logger.Debug("starting background job")logger.Log(ctx, LevelTrace, "button clicked")}
Output:sev=EMERGENCY msg="missing pilots"sev=ERROR msg="failed to start engines" err="missing fuel"sev=WARNING msg="falling back to default value"sev=NOTICE msg="all systems are running"sev=INFO msg="initiating launch"sev=DEBUG msg="starting background job"sev=TRACE msg="button clicked"

typeJSONHandler

type JSONHandler struct {// contains filtered or unexported fields}

JSONHandler is aHandler that writes Records to anio.Writer asline-delimited JSON objects.

funcNewJSONHandler

func NewJSONHandler(wio.Writer, opts *HandlerOptions) *JSONHandler

NewJSONHandler creates aJSONHandler that writes to w,using the given options.If opts is nil, the default options are used.

func (*JSONHandler)Enabled

func (h *JSONHandler) Enabled(_context.Context, levelLevel)bool

Enabled reports whether the handler handles records at the given level.The handler ignores records whose level is lower.

func (*JSONHandler)Handle

func (h *JSONHandler) Handle(_context.Context, rRecord)error

Handle formats its argumentRecord as a JSON object on a single line.

If the Record's time is zero, the time is omitted.Otherwise, the key is "time"and the value is output as with json.Marshal.

The level's key is "level" and its value is the result of callingLevel.String.

If the AddSource option is set and source information is available,the key is "source", and the value is a record of typeSource.

The message's key is "msg".

To modify these or other attributes, or remove them from the output, use[HandlerOptions.ReplaceAttr].

Values are formatted as with anencoding/json.Encoder with SetEscapeHTML(false),with two exceptions.

First, an Attr whose Value is of type error is formatted as a string, bycalling its Error method. Only errors in Attrs receive this special treatment,not errors embedded in structs, slices, maps or other data structures thatare processed by theencoding/json package.

Second, an encoding failure does not cause Handle to return an error.Instead, the error message is formatted as a string.

Each call to Handle results in a single serialized call to io.Writer.Write.

func (*JSONHandler)WithAttrs

func (h *JSONHandler) WithAttrs(attrs []Attr)Handler

WithAttrs returns a newJSONHandler whose attributes consistsof h's attributes followed by attrs.

func (*JSONHandler)WithGroup

func (h *JSONHandler) WithGroup(namestring)Handler

typeKind

type Kindint

Kind is the kind of aValue.

const (KindAnyKind =iotaKindBoolKindDurationKindFloat64KindInt64KindStringKindTimeKindUint64KindGroupKindLogValuer)

func (Kind)String

func (kKind) String()string

typeLevel

type Levelint

A Level is the importance or severity of a log event.The higher the level, the more important or severe the event.

const (LevelDebugLevel = -4LevelInfoLevel = 0LevelWarnLevel = 4LevelErrorLevel = 8)

Names for common levels.

Level numbers are inherently arbitrary,but we picked them to satisfy three constraints.Any system can map them to another numbering scheme if it wishes.

First, we wanted the default level to be Info, Since Levels are ints, Info isthe default value for int, zero.

Second, we wanted to make it easy to use levels to specify logger verbosity.Since a larger level means a more severe event, a logger that accepts eventswith smaller (or more negative) level means a more verbose logger. Loggerverbosity is thus the negation of event severity, and the default verbosityof 0 accepts all events at least as severe as INFO.

Third, we wanted some room between levels to accommodate schemes with namedlevels between ours. For example, Google Cloud Logging defines a Notice levelbetween Info and Warn. Since there are only a few of these intermediatelevels, the gap between the numbers need not be large. Our gap of 4 matchesOpenTelemetry's mapping. Subtracting 9 from an OpenTelemetry level in theDEBUG, INFO, WARN and ERROR ranges converts it to the corresponding slogLevel range. OpenTelemetry also has the names TRACE and FATAL, which slogdoes not. But those OpenTelemetry levels can still be represented as slogLevels by using the appropriate integers.

funcSetLogLoggerLeveladded ingo1.22.0

func SetLogLoggerLevel(levelLevel) (oldLevelLevel)

SetLogLoggerLevel controls the level for the bridge to thelog package.

BeforeSetDefault is called, slog top-level logging functions call the defaultlog.Logger.In that mode, SetLogLoggerLevel sets the minimum level for those calls.By default, the minimum level is Info, so calls toDebug(as well as top-level logging calls at lower levels)will not be passed to the log.Logger. After calling

slog.SetLogLoggerLevel(slog.LevelDebug)

calls toDebug will be passed to the log.Logger.

AfterSetDefault is called, calls to the defaultlog.Logger are passed to theslog default handler. In that mode,SetLogLoggerLevel sets the level at which those calls are logged.That is, after calling

slog.SetLogLoggerLevel(slog.LevelDebug)

A call tolog.Printf will result in output at levelLevelDebug.

SetLogLoggerLevel returns the previous value.

Example (Log)

This example shows how to use slog.SetLogLoggerLevel to change the minimal levelof the internal default handler for slog package before calling slog.SetDefault.

package mainimport ("log""log/slog""os")func main() {defer log.SetFlags(log.Flags()) // revert changes after the examplelog.SetFlags(0)defer log.SetOutput(log.Writer()) // revert changes after the examplelog.SetOutput(os.Stdout)// Default logging level is slog.LevelInfo.log.Print("log debug") // log debugslog.Debug("debug")    // no outputslog.Info("info")      // INFO info// Set the default logging level to slog.LevelDebug.currentLogLevel := slog.SetLogLoggerLevel(slog.LevelDebug)defer slog.SetLogLoggerLevel(currentLogLevel) // revert changes after the examplelog.Print("log debug") // log debugslog.Debug("debug")    // DEBUG debugslog.Info("info")      // INFO info}
Output:log debugINFO infolog debugDEBUG debugINFO info

Example (Slog)

This example shows how to use slog.SetLogLoggerLevel to change the minimal levelof the internal writer that uses the custom handler for log package aftercalling slog.SetDefault.

package mainimport ("log""log/slog""os")func main() {// Set the default logging level to slog.LevelError.currentLogLevel := slog.SetLogLoggerLevel(slog.LevelError)defer slog.SetLogLoggerLevel(currentLogLevel) // revert changes after the exampledefer slog.SetDefault(slog.Default()) // revert changes after the exampleremoveTime := func(groups []string, a slog.Attr) slog.Attr {if a.Key == slog.TimeKey && len(groups) == 0 {return slog.Attr{}}return a}slog.SetDefault(slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{ReplaceAttr: removeTime})))log.Print("error") // level=ERROR msg=error}
Output:level=ERROR msg=error

func (Level)AppendTextadded ingo1.24.0

func (lLevel) AppendText(b []byte) ([]byte,error)

AppendText implementsencoding.TextAppenderby callingLevel.String.

func (Level)Level

func (lLevel) Level()Level

Level returns the receiver.It implementsLeveler.

func (Level)MarshalJSON

func (lLevel) MarshalJSON() ([]byte,error)

MarshalJSON implementsencoding/json.Marshalerby quoting the output ofLevel.String.

func (Level)MarshalText

func (lLevel) MarshalText() ([]byte,error)

MarshalText implementsencoding.TextMarshalerby callingLevel.AppendText.

func (Level)String

func (lLevel) String()string

String returns a name for the level.If the level has a name, then that namein uppercase is returned.If the level is between named values, thenan integer is appended to the uppercased name.Examples:

LevelWarn.String() => "WARN"(LevelInfo+2).String() => "INFO+2"

func (*Level)UnmarshalJSON

func (l *Level) UnmarshalJSON(data []byte)error

UnmarshalJSON implementsencoding/json.UnmarshalerIt accepts any string produced byLevel.MarshalJSON,ignoring case.It also accepts numeric offsets that would result in a different string onoutput. For example, "Error-8" would marshal as "INFO".

func (*Level)UnmarshalText

func (l *Level) UnmarshalText(data []byte)error

UnmarshalText implementsencoding.TextUnmarshaler.It accepts any string produced byLevel.MarshalText,ignoring case.It also accepts numeric offsets that would result in a different string onoutput. For example, "Error-8" would marshal as "INFO".

typeLevelVar

type LevelVar struct {// contains filtered or unexported fields}

A LevelVar is aLevel variable, to allow aHandler level to changedynamically.It implementsLeveler as well as a Set method,and it is safe for use by multiple goroutines.The zero LevelVar corresponds toLevelInfo.

func (*LevelVar)AppendTextadded ingo1.24.0

func (v *LevelVar) AppendText(b []byte) ([]byte,error)

AppendText implementsencoding.TextAppenderby callingLevel.AppendText.

func (*LevelVar)Level

func (v *LevelVar) Level()Level

Level returns v's level.

func (*LevelVar)MarshalText

func (v *LevelVar) MarshalText() ([]byte,error)

MarshalText implementsencoding.TextMarshalerby callingLevelVar.AppendText.

func (*LevelVar)Set

func (v *LevelVar) Set(lLevel)

Set sets v's level to l.

func (*LevelVar)String

func (v *LevelVar) String()string

func (*LevelVar)UnmarshalText

func (v *LevelVar) UnmarshalText(data []byte)error

UnmarshalText implementsencoding.TextUnmarshalerby callingLevel.UnmarshalText.

typeLeveler

type Leveler interface {Level()Level}

A Leveler provides aLevel value.

As Level itself implements Leveler, clients typically supplya Level value wherever a Leveler is needed, such as inHandlerOptions.Clients who need to vary the level dynamically can provide a more complexLeveler implementation such as *LevelVar.

typeLogValuer

type LogValuer interface {LogValue()Value}

A LogValuer is any Go value that can convert itself into a Value for logging.

This mechanism may be used to defer expensive operations until they areneeded, or to expand a single value into a sequence of components.

Example (Group)
package mainimport "log/slog"type Name struct {First, Last string}// LogValue implements slog.LogValuer.// It returns a group containing the fields of// the Name, so that they appear together in the log output.func (n Name) LogValue() slog.Value {return slog.GroupValue(slog.String("first", n.First),slog.String("last", n.Last))}func main() {n := Name{"Perry", "Platypus"}slog.Info("mission accomplished", "agent", n)// JSON Output would look in part like:// {//     ...//     "msg": "mission accomplished",//     "agent": {//         "first": "Perry",//         "last": "Platypus"//     }// }}

Example (Secret)

This example demonstrates a Value that replaces itselfwith an alternative representation to avoid revealing secrets.

package mainimport ("log/slog""os")// A token is a secret value that grants permissions.type Token string// LogValue implements slog.LogValuer.// It avoids revealing the token.func (Token) LogValue() slog.Value {return slog.StringValue("REDACTED_TOKEN")}// This example demonstrates a Value that replaces itself// with an alternative representation to avoid revealing secrets.func main() {t := Token("shhhh!")removeTime := func(groups []string, a slog.Attr) slog.Attr {if a.Key == slog.TimeKey && len(groups) == 0 {return slog.Attr{}}return a}logger := slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{ReplaceAttr: removeTime}))logger.Info("permission granted", "user", "Perry", "token", t)}
Output:level=INFO msg="permission granted" user=Perry token=REDACTED_TOKEN

typeLogger

type Logger struct {// contains filtered or unexported fields}

A Logger records structured information about each call to itsLog, Debug, Info, Warn, and Error methods.For each call, it creates aRecord and passes it to aHandler.

To create a new Logger, callNew or a Logger methodthat begins "With".

funcDefault

func Default() *Logger

Default returns the defaultLogger.

funcNew

func New(hHandler) *Logger

New creates a new Logger with the given non-nil Handler.

funcWith

func With(args ...any) *Logger

With callsLogger.With on the default logger.

func (*Logger)Debug

func (l *Logger) Debug(msgstring, args ...any)

Debug logs atLevelDebug.

func (*Logger)DebugContext

func (l *Logger) DebugContext(ctxcontext.Context, msgstring, args ...any)

DebugContext logs atLevelDebug with the given context.

func (*Logger)Enabled

func (l *Logger) Enabled(ctxcontext.Context, levelLevel)bool

Enabled reports whether l emits log records at the given context and level.

func (*Logger)Error

func (l *Logger) Error(msgstring, args ...any)

Error logs atLevelError.

func (*Logger)ErrorContext

func (l *Logger) ErrorContext(ctxcontext.Context, msgstring, args ...any)

ErrorContext logs atLevelError with the given context.

func (*Logger)Handler

func (l *Logger) Handler()Handler

Handler returns l's Handler.

func (*Logger)Info

func (l *Logger) Info(msgstring, args ...any)

Info logs atLevelInfo.

func (*Logger)InfoContext

func (l *Logger) InfoContext(ctxcontext.Context, msgstring, args ...any)

InfoContext logs atLevelInfo with the given context.

func (*Logger)Log

func (l *Logger) Log(ctxcontext.Context, levelLevel, msgstring, args ...any)

Log emits a log record with the current time and the given level and message.The Record's Attrs consist of the Logger's attributes followed bythe Attrs specified by args.

The attribute arguments are processed as follows:

  • If an argument is an Attr, it is used as is.
  • If an argument is a string and this is not the last argument,the following argument is treated as the value and the two are combinedinto an Attr.
  • Otherwise, the argument is treated as a value with key "!BADKEY".

func (*Logger)LogAttrs

func (l *Logger) LogAttrs(ctxcontext.Context, levelLevel, msgstring, attrs ...Attr)

LogAttrs is a more efficient version ofLogger.Log that accepts only Attrs.

func (*Logger)Warn

func (l *Logger) Warn(msgstring, args ...any)

Warn logs atLevelWarn.

func (*Logger)WarnContext

func (l *Logger) WarnContext(ctxcontext.Context, msgstring, args ...any)

WarnContext logs atLevelWarn with the given context.

func (*Logger)With

func (l *Logger) With(args ...any) *Logger

With returns a Logger that includes the given attributesin each output operation. Arguments are converted toattributes as if byLogger.Log.

func (*Logger)WithGroup

func (l *Logger) WithGroup(namestring) *Logger

WithGroup returns a Logger that starts a group, if name is non-empty.The keys of all attributes added to the Logger will be qualified by the givenname. (How that qualification happens depends on the [Handler.WithGroup]method of the Logger's Handler.)

If name is empty, WithGroup returns the receiver.

typeRecord

type Record struct {// The time at which the output method (Log, Info, etc.) was called.Timetime.Time// The log message.Messagestring// The level of the event.LevelLevel// The program counter at the time the record was constructed, as determined// by runtime.Callers. If zero, no program counter is available.//// The only valid use for this value is as an argument to// [runtime.CallersFrames]. In particular, it must not be passed to// [runtime.FuncForPC].PCuintptr// contains filtered or unexported fields}

A Record holds information about a log event.Copies of a Record share state.Do not modify a Record after handing out a copy to it.CallNewRecord to create a new Record.UseRecord.Clone to create a copy with no shared state.

funcNewRecord

func NewRecord(ttime.Time, levelLevel, msgstring, pcuintptr)Record

NewRecord creates aRecord from the given arguments.UseRecord.AddAttrs to add attributes to the Record.

NewRecord is intended for logging APIs that want to support aHandler asa backend.

func (*Record)Add

func (r *Record) Add(args ...any)

Add converts the args to Attrs as described inLogger.Log,then appends the Attrs to theRecord's list of Attrs.It omits empty groups.

func (*Record)AddAttrs

func (r *Record) AddAttrs(attrs ...Attr)

AddAttrs appends the given Attrs to theRecord's list of Attrs.It omits empty groups.

func (Record)Attrs

func (rRecord) Attrs(f func(Attr)bool)

Attrs calls f on each Attr in theRecord.Iteration stops if f returns false.

func (Record)Clone

func (rRecord) Clone()Record

Clone returns a copy of the record with no shared state.The original record and the clone can both be modifiedwithout interfering with each other.

func (Record)NumAttrs

func (rRecord) NumAttrs()int

NumAttrs returns the number of attributes in theRecord.

func (Record)Sourceadded ingo1.25.0

func (rRecord) Source() *Source

Source returns a new Source for the log event using r's PC.If the PC field is zero, meaning the Record was created without the necessary informationor the location is unavailable, then nil is returned.

typeSource

type Source struct {// Function is the package path-qualified function name containing the// source line. If non-empty, this string uniquely identifies a single// function in the program. This may be the empty string if not known.Functionstring `json:"function"`// File and Line are the file name and line number (1-based) of the source// line. These may be the empty string and zero, respectively, if not known.Filestring `json:"file"`Lineint    `json:"line"`}

Source describes the location of a line of source code.

typeTextHandler

type TextHandler struct {// contains filtered or unexported fields}

TextHandler is aHandler that writes Records to anio.Writer as asequence of key=value pairs separated by spaces and followed by a newline.

funcNewTextHandler

func NewTextHandler(wio.Writer, opts *HandlerOptions) *TextHandler

NewTextHandler creates aTextHandler that writes to w,using the given options.If opts is nil, the default options are used.

func (*TextHandler)Enabled

func (h *TextHandler) Enabled(_context.Context, levelLevel)bool

Enabled reports whether the handler handles records at the given level.The handler ignores records whose level is lower.

func (*TextHandler)Handle

func (h *TextHandler) Handle(_context.Context, rRecord)error

Handle formats its argumentRecord as a single line of space-separatedkey=value items.

If the Record's time is zero, the time is omitted.Otherwise, the key is "time"and the value is output in RFC3339 format with millisecond precision.

The level's key is "level" and its value is the result of callingLevel.String.

If the AddSource option is set and source information is available,the key is "source" and the value is output as FILE:LINE.

The message's key is "msg".

To modify these or other attributes, or remove them from the output, use[HandlerOptions.ReplaceAttr].

If a value implementsencoding.TextMarshaler, the result of MarshalText iswritten. Otherwise, the result offmt.Sprint is written.

Keys and values are quoted withstrconv.Quote if they contain Unicode spacecharacters, non-printing characters, '"' or '='.

Keys inside groups consist of components (keys or group names) separated bydots. No further escaping is performed.Thus there is no way to determine from the key "a.b.c" whether thereare two groups "a" and "b" and a key "c", or a single group "a.b" and a key "c",or single group "a" and a key "b.c".If it is necessary to reconstruct the group structure of a keyeven in the presence of dots inside components, use[HandlerOptions.ReplaceAttr] to encode that information in the key.

Each call to Handle results in a single serialized call toio.Writer.Write.

func (*TextHandler)WithAttrs

func (h *TextHandler) WithAttrs(attrs []Attr)Handler

WithAttrs returns a newTextHandler whose attributes consistsof h's attributes followed by attrs.

func (*TextHandler)WithGroup

func (h *TextHandler) WithGroup(namestring)Handler

typeValue

type Value struct {// contains filtered or unexported fields}

A Value can represent any Go value, but unlike type any,it can represent most small values without an allocation.The zero Value corresponds to nil.

funcAnyValue

func AnyValue(vany)Value

AnyValue returns aValue for the supplied value.

If the supplied value is of type Value, it is returnedunmodified.

Given a value of one of Go's predeclared string, bool, or(non-complex) numeric types, AnyValue returns a Value of kindKindString,KindBool,KindUint64,KindInt64, orKindFloat64.The width of the original numeric type is not preserved.

Given atime.Time ortime.Duration value, AnyValue returns a Value of kindKindTime orKindDuration. The monotonic time is not preserved.

For nil, or values of all other types, including named types whoseunderlying type is numeric, AnyValue returns a value of kindKindAny.

funcBoolValue

func BoolValue(vbool)Value

BoolValue returns aValue for a bool.

funcDurationValue

func DurationValue(vtime.Duration)Value

DurationValue returns aValue for atime.Duration.

funcFloat64Value

func Float64Value(vfloat64)Value

Float64Value returns aValue for a floating-point number.

funcGroupValue

func GroupValue(as ...Attr)Value

GroupValue returns a newValue for a list of Attrs.The caller must not subsequently mutate the argument slice.

funcInt64Value

func Int64Value(vint64)Value

Int64Value returns aValue for an int64.

funcIntValue

func IntValue(vint)Value

IntValue returns aValue for an int.

funcStringValue

func StringValue(valuestring)Value

StringValue returns a newValue for a string.

funcTimeValue

func TimeValue(vtime.Time)Value

TimeValue returns aValue for atime.Time.It discards the monotonic portion.

funcUint64Value

func Uint64Value(vuint64)Value

Uint64Value returns aValue for a uint64.

func (Value)Any

func (vValue) Any()any

Any returns v's value as an any.

func (Value)Bool

func (vValue) Bool()bool

Bool returns v's value as a bool. It panicsif v is not a bool.

func (Value)Duration

func (vValue) Duration()time.Duration

Duration returns v's value as atime.Duration. It panicsif v is not a time.Duration.

func (Value)Equal

func (vValue) Equal(wValue)bool

Equal reports whether v and w represent the same Go value.

func (Value)Float64

func (vValue) Float64()float64

Float64 returns v's value as a float64. It panicsif v is not a float64.

func (Value)Group

func (vValue) Group() []Attr

Group returns v's value as a []Attr.It panics if v'sKind is notKindGroup.

func (Value)Int64

func (vValue) Int64()int64

Int64 returns v's value as an int64. It panicsif v is not a signed integer.

func (Value)Kind

func (vValue) Kind()Kind

Kind returns v's Kind.

func (Value)LogValuer

func (vValue) LogValuer()LogValuer

LogValuer returns v's value as a LogValuer. It panicsif v is not a LogValuer.

func (Value)Resolve

func (vValue) Resolve() (rvValue)

Resolve repeatedly calls LogValue on v while it implementsLogValuer,and returns the result.If v resolves to a group, the group's attributes' values are not recursivelyresolved.If the number of LogValue calls exceeds a threshold, a Value containing anerror is returned.Resolve's return value is guaranteed not to be of KindKindLogValuer.

func (Value)String

func (vValue) String()string

String returns Value's value as a string, formatted likefmt.Sprint. Unlikethe methods Int64, Float64, and so on, which panic if v is of thewrong kind, String never panics.

func (Value)Time

func (vValue) Time()time.Time

Time returns v's value as atime.Time. It panicsif v is not a time.Time.

func (Value)Uint64

func (vValue) Uint64()uint64

Uint64 returns v's value as a uint64. It panicsif v is not an unsigned integer.

Source Files

View all Source files

Directories

PathSynopsis
benchmarks
Package benchmarks contains benchmarks for slog.
Package benchmarks contains benchmarks for slog.
buffer
Package buffer provides a pool-allocated byte buffer.
Package buffer provides a pool-allocated byte buffer.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f orF : Jump to
y orY : Canonical URL
go.dev uses cookies from Google to deliver and enhance the quality of its services and to analyze traffic.Learn more.

[8]ページ先頭

©2009-2025 Movatter.jp