modulepackage
2.0.1+incompatible
Repository: https://github.com/coder/slog.git
Documentation: pkg.go.dev
# README
slog
slog is a minimal structured logging library for Go.
Install
go get cdr.dev/slog
Features
- Minimal API
- First class context.Context support
- First class testing.TB support
- Package slogtest/assert provides test assertion helpers
- Beautiful human readable logging output
- Prints multiline fields and errors nicely
- Machine readable JSON output
- GCP Stackdriver support
- Stdlib log adapter
- Skip caller frames with slog.Helper
- Encodes values as if with
json.Marshal
- Transparently log opencensus trace and span IDs
- Single dependency on go.opencensus.io
- Log to multiple sinks
Example
Many more examples available at godoc.
ctx := sloghuman.Make(ctx, os.Stdout)
slog.Info(ctx, "my message here",
slog.F("field_name", "something or the other"),
slog.F("some_map", slog.M(
slog.F("nested_fields", time.Date(2000, time.February, 5, 4, 4, 4, 0, time.UTC)),
)),
slog.Error(
xerrors.Errorf("wrap1: %w",
xerrors.Errorf("wrap2: %w",
io.EOF,
),
),
),
)
Why?
At Coder we’ve used Uber’s zap for several years. It is a fantastic library for performance. Thanks Uber!
However we felt the API and developer experience could be improved.
Here is a list of reasons how we improved on zap with slog.
-
slog
has a minimal API surface -
slog
has a concise semi typed API- We found zap's fully typed API cumbersome. It does offer a sugared API but it's too easy to pass an invalid fields list since there is no static type checking. Furthermore, it's harder to read as there is no syntax grouping for each key value pair.
- We wanted an API that only accepted the equivalent of zap.Any for every field. This is slog.F.
-
sloghuman
uses a very human readable format- It colors distinct parts of each line to make it easier to scan logs. Even the JSON that represents
the fields in each log is syntax highlighted so that is very easy to scan. See the screenshot above.
- zap lacks appropriate colors for different levels and fields
- slog automatically prints one multiline field after the log to make errors and such much easier to read.
- zap logs multiline fields and errors stack traces as JSON strings which made them unreadable in a terminal.
- When logging to JSON, slog automatically converts a
golang.org/x/xerrors
chain into an array with fields for the location and wrapping messages.
- It colors distinct parts of each line to make it easier to scan logs. Even the JSON that represents
the fields in each log is syntax highlighted so that is very easy to scan. See the screenshot above.
-
Full context.Context support
slog
lets you set fields in acontext.Context
such that any log with the context prints those fields.slog
stores the actual logger in thecontext.Context
, following the example of the Go trace library. Our logger doesn't bloat type and function signatures.- We wanted to be able to pull up all relevant logs for a given trace, user or request. With zap, we were plugging these fields in for every relevant log or passing around a logger with the fields set. This became very verbose.
-
Simple and easy to extend
- A new backend only has to implement the simple Sink interface.
- The Logger type provides a nice API around Sink but also implements Sink to allow for composition.
- zap is hard and confusing to extend. There are too many structures and configuration options.
-
Structured logging of Go structures with
json.Marshal
- Entire encoding process is documented on godoc.
- With zap, We found ourselves often implementing zap's
ObjectMarshaler to log Go structures. This was
verbose and most of the time we ended up only implementing
fmt.Stringer
and usingzap.Stringer
instead.
-
slog takes inspiration from Go's stdlib and implements
slog.Helper
which works just liket.Helper
- It marks the calling function as a helper and skips it when reporting location info.
- We had many helper functions for logging but we wanted the line reported to be of the parent function. zap has an API for this but it's verbose and requires passing the logger around explicitly.
-
Tight integration with stdlib's
testing
package- You can configure
slogtest
to exit on any ERROR logs and it has a global stateless API that takes atesting.TB
so you do not need to create a logger first. - Test assertion helpers are provided in slogtest/assert.
- zap has zaptest but the API surface is large and doesn't integrate well. It does not support any of the features described above.
- You can configure
# Packages
No description provided by the author
# Functions
Critical logs the msg and fields at LevelCritical.
Debug logs the msg and fields at LevelDebug.
Err is the standard key used for logging a Go error value.
Error logs the msg and fields at LevelError.
F is a convenience constructor for Field.
Fatal logs the msg and fields at LevelFatal.
Helper marks the calling function as a helper and skips it for source location information.
Info logs the msg and fields at LevelInfo.
Leveled returns a logger that only logs entries equal to or above the given level.
M is a convenience constructor for Map.
Make creates a logger that writes logs to the passed sinks at LevelInfo.
Named appends the name to the set names on the logger.
Stdlib creates a standard library logger from the given logger.
Sync calls Sync on all the underlying sinks.
Warn logs the msg and fields at LevelWarn.
With returns a context that contains the given fields.
# Constants
LevelCritical is used when when something has gone wrong and should be immediately investigated.
LevelDebug is used for development and debugging messages.
LevelError is used when something has certainly gone wrong.
LevelFatal is used when the process is about to exit due to an error.
LevelInfo is used for normal informational messages.
LevelWarn is used when something has possibly gone wrong.