Documentation ¶
Overview ¶
Package slog implements minimal structured logging.
See https://cdr.dev/slog for overview docs and a comparison with existing libraries.
The examples are the best way to understand how to use this library effectively.
The Logger type implements a high level API around the Sink interface. Logger implements Sink as well to allow composition.
Implementations of the Sink interface are available in the sloggers subdirectory.
Example ¶
package main import ( "context" "io" "os" "time" "golang.org/x/xerrors" "cdr.dev/slog" "cdr.dev/slog/sloggers/sloghuman" ) func main() { log := slog.Make(sloghuman.Sink(os.Stdout)) log.Info(context.Background(), "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, ), ), ), ) // 2019-12-09 05:04:53.398 [INFO] <example.go:16> my message here {"field_name": "something or the other", "some_map": {"nested_fields": "2000-02-05T04:04:04Z"}} ... // "error": wrap1: // main.main // /Users/nhooyr/src/cdr/scratch/example.go:22 // - wrap2: // main.main // /Users/nhooyr/src/cdr/scratch/example.go:23 // - EOF }
Output:
Example (Marshaller) ¶
package main import ( "context" "os" "cdr.dev/slog" "cdr.dev/slog/sloggers/sloghuman" ) type myStruct struct { foo int bar int } func (s myStruct) MarshalJSON() ([]byte, error) { return slog.M( slog.F("foo", s.foo), slog.F("bar", s.foo), ).MarshalJSON() } func main() { l := slog.Make(sloghuman.Sink(os.Stdout)) l.Info(context.Background(), "wow", slog.F("myStruct", myStruct{ foo: 1, bar: 2, }), ) // 2019-12-16 17:31:37.120 [INFO] <example_marshaller_test.go:26> wow {"myStruct": {"foo": 1, "bar": 1}} }
Output:
Example (Multiple) ¶
package main import ( "context" "os" "cdr.dev/slog" "cdr.dev/slog/sloggers/sloghuman" "cdr.dev/slog/sloggers/slogstackdriver" ) func main() { l := slog.Make(sloghuman.Sink(os.Stdout)) f, err := os.OpenFile("stackdriver", os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0o644) if err != nil { l.Fatal(context.Background(), "failed to open stackdriver log file", slog.Error(err)) } l = l.AppendSinks(slogstackdriver.Sink(f)) l.Info(context.Background(), "log to stdout and stackdriver") // 2019-12-07 20:59:55.790 [INFO] log to stdout and stackdriver }
Output:
Example (Struct) ¶
package main import ( "context" "os" "time" "cdr.dev/slog" "cdr.dev/slog/sloggers/sloghuman" ) func main() { l := slog.Make(sloghuman.Sink(os.Stdout)) type hello struct { Meow int `json:"meow"` Bar string `json:"bar"` M time.Time `json:"m"` } l.Info(context.Background(), "check out my structure", slog.F("hello", hello{ Meow: 1, Bar: "barbar", M: time.Date(2000, time.February, 5, 4, 4, 4, 0, time.UTC), }), ) // 2019-12-16 17:31:51.769 [INFO] <example_test.go:56> check out my structure {"hello": {"meow": 1, "bar": "barbar", "m": "2000-02-05T04:04:04Z"}} }
Output:
Example (Testing) ¶
package main import ( "testing" "cdr.dev/slog" "cdr.dev/slog/sloggers/slogtest" ) func main() { // Provided by the testing package in tests. var t testing.TB slogtest.Info(t, "my message here", slog.F("field_name", "something or the other"), ) // t.go:55: 2019-12-05 21:20:31.218 [INFO] my message here field_name="something or the other" }
Output:
Index ¶
- func Helper()
- func Stdlib(ctx context.Context, l Logger, level Level) *log.Logger
- func With(ctx context.Context, fields ...Field) context.Context
- type Field
- type Level
- type Logger
- func (l Logger) AppendSinks(s ...Sink) Logger
- func (l Logger) Critical(ctx context.Context, msg string, fields ...Field)
- func (l Logger) Debug(ctx context.Context, msg string, fields ...Field)
- func (l Logger) Error(ctx context.Context, msg string, fields ...Field)
- func (l Logger) Fatal(ctx context.Context, msg string, fields ...Field)
- func (l Logger) Info(ctx context.Context, msg string, fields ...Field)
- func (l Logger) Leveled(level Level) Logger
- func (l Logger) Log(ctx context.Context, e SinkEntry)
- func (l Logger) Named(name string) Logger
- func (l Logger) Sync()
- func (l Logger) Warn(ctx context.Context, msg string, fields ...Field)
- func (l Logger) With(fields ...Field) Logger
- type Map
- type Sink
- type SinkEntry
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Helper ¶
func Helper()
Helper marks the calling function as a helper and skips it for source location information. It's the slog equivalent of testing.TB.Helper().
Example ¶
package main import ( "context" "net/http" "os" "cdr.dev/slog" "cdr.dev/slog/sloggers/sloghuman" ) func httpLogHelper(ctx context.Context, status int) { slog.Helper() l.Info(ctx, "sending HTTP response", slog.F("status", status), ) } var l = slog.Make(sloghuman.Sink(os.Stdout)) func main() { ctx := context.Background() httpLogHelper(ctx, http.StatusBadGateway) // 2019-12-07 21:18:42.567 [INFO] <example_helper_test.go:24> sending HTTP response {"status": 502} }
Output:
func Stdlib ¶
Stdlib creates a standard library logger from the given logger.
All logs will be logged at the level set by the logger and the given ctx will be passed to the logger's Log method, thereby logging all fields and tracing info in the context.
You can redirect the stdlib default logger with log.SetOutput to the Writer on the logger returned by this function. See the example.
Example ¶
package main import ( "context" "os" "cdr.dev/slog" "cdr.dev/slog/sloggers/sloghuman" ) func main() { ctx := slog.With(context.Background(), slog.F("field", 1)) l := slog.Stdlib(ctx, slog.Make(sloghuman.Sink(os.Stdout)), slog.LevelInfo) l.Print("msg") // 2019-12-07 20:54:23.986 [INFO] (stdlib) msg field=1 }
Output:
func With ¶
With returns a context that contains the given fields.
Any logs written with the provided context will have the given logs prepended.
It will append to any fields already in ctx.
Example ¶
package main import ( "context" "os" "cdr.dev/slog" "cdr.dev/slog/sloggers/sloghuman" ) func main() { ctx := slog.With(context.Background(), slog.F("field", 1)) l := slog.Make(sloghuman.Sink(os.Stdout)) l.Info(ctx, "msg") // 2019-12-07 20:54:23.986 [INFO] msg field=1} }
Output:
Types ¶
type Field ¶
type Field struct { Name string Value interface{} }
Field represents a log field.
type Level ¶
type Level int
Level represents a log level.
const ( // LevelDebug is used for development and debugging messages. LevelDebug Level = iota // LevelInfo is used for normal informational messages. LevelInfo // LevelWarn is used when something has possibly gone wrong. LevelWarn // LevelError is used when something has certainly gone wrong. LevelError // LevelCritical is used when when something has gone wrong and should // be immediately investigated. LevelCritical // LevelFatal is used when the process is about to exit due to an error. LevelFatal )
The supported log levels.
The default level is Info.
type Logger ¶
type Logger struct {
// contains filtered or unexported fields
}
Logger wraps Sink with a nice API to log entries.
Logger is safe for concurrent use.
func (Logger) AppendSinks ¶ added in v1.4.0
AppendSinks appends the sinks to the set sink targets on the logger.
func (Logger) Fatal ¶
Fatal logs the msg and fields at LevelFatal.
It will then Sync() and os.Exit(1).
func (Logger) Leveled ¶ added in v0.5.0
Leveled returns a Logger that only logs entries equal to or above the given level.
Example ¶
package main import ( "context" "os" "cdr.dev/slog" "cdr.dev/slog/sloggers/sloghuman" ) func main() { ctx := context.Background() l := slog.Make(sloghuman.Sink(os.Stdout)) l.Debug(ctx, "testing1") l.Info(ctx, "received request") l = l.Leveled(slog.LevelDebug) l.Debug(ctx, "testing2") // 2019-12-07 21:26:20.945 [INFO] received request // 2019-12-07 21:26:20.945 [DEBU] testing2 }
Output:
func (Logger) Log ¶ added in v1.4.0
Log logs the given entry with the context to the underlying sinks.
It extends the entry with the set fields and names.
func (Logger) Named ¶
Named appends the name to the set names on the logger.
Example ¶
package main import ( "context" "net" "os" "cdr.dev/slog" "cdr.dev/slog/sloggers/sloghuman" ) func main() { ctx := context.Background() l := slog.Make(sloghuman.Sink(os.Stdout)) l = l.Named("http") l.Info(ctx, "received request", slog.F("remote address", net.IPv4(127, 0, 0, 1))) // 2019-12-07 21:20:56.974 [INFO] (http) received request remote_address=127.0.0.1} }
Output:
type Map ¶
type Map []Field
Map represents an ordered map of fields.
func (Map) MarshalJSON ¶
MarshalJSON implements json.Marshaler.
It is guaranteed to return a nil error. Any error marshalling a field will become the field's value.
Every field value is encoded with the following process:
1. json.Marshaller is handled.
2. xerrors.Formatter is handled.
3. structs that have a field with a json tag are encoded with json.Marshal.
4. error and fmt.Stringer is handled.
5. slices and arrays go through the encode function for every element.
6. For values that cannot be encoded with json.Marshal, fmt.Sprintf("%+v") is used.
7. json.Marshal(v) is used for all other values.
Directories ¶
Path | Synopsis |
---|---|
internal
|
|
assert
Package assert contains helpers for test assertions.
|
Package assert contains helpers for test assertions. |
entryhuman
Package entryhuman contains the code to format slog.SinkEntry for humans.
|
Package entryhuman contains the code to format slog.SinkEntry for humans. |
syncwriter
Package syncwriter implements a concurrency safe io.Writer wrapper.
|
Package syncwriter implements a concurrency safe io.Writer wrapper. |
sloggers
|
|
sloghuman
Package sloghuman contains the slogger that writes logs in a human readable format.
|
Package sloghuman contains the slogger that writes logs in a human readable format. |
slogjson
Package slogjson contains the slogger that writes logs in JSON.
|
Package slogjson contains the slogger that writes logs in JSON. |
slogstackdriver
Package slogstackdriver contains the slogger for google cloud's stackdriver.
|
Package slogstackdriver contains the slogger for google cloud's stackdriver. |
slogtest
Package slogtest contains the slogger for use with Go's testing package.
|
Package slogtest contains the slogger for use with Go's testing package. |
slogtest/assert
Package assert is a helper package for test assertions.
|
Package assert is a helper package for test assertions. |