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.
This package provides a high level API around the Sink interface. The implementations are in the sloggers subdirectory.
Example ¶
package main import ( "io" "testing" "golang.org/x/xerrors" "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"), slog.F("some_map", slog.M( slog.F("nested_fields", "wowow"), )), slog.Error( xerrors.Errorf("wrap1: %w", xerrors.Errorf("wrap2: %w", io.EOF, ), ), ), ) // t.go:55: 2019-12-05 21:20:31.218 [INFO] <examples_test.go:42> my message here {"field_name": "something or the other", "some_map": {"nested_fields": "wowow"}} ... // "error": wrap1: // cdr.dev/slog_test.TestExample // /Users/nhooyr/src/cdr/slog/examples_test.go:48 // - wrap2: // cdr.dev/slog_test.TestExample // /Users/nhooyr/src/cdr/slog/examples_test.go:49 // - EOF }
Output:
Index ¶
- func ForceJSON(v interface{}) interface{}
- func Helper()
- func Stdlib(ctx context.Context, l Logger) *log.Logger
- func With(ctx context.Context, fields ...Field) context.Context
- type Field
- type Level
- type 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) Named(name string) Logger
- func (l Logger) SetLevel(level Level)
- 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
- type Value
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func ForceJSON ¶
func ForceJSON(v interface{}) interface{}
ForceJSON ensures the value is logged via json.Marshal even if it implements fmt.Stringer or error.
See the ForceJSON example.
Example ¶
package main import ( "context" "fmt" "os" "cdr.dev/slog" "cdr.dev/slog/sloggers/sloghuman" ) type stringer struct { X int `json:"x"` } func (s *stringer) String() string { return fmt.Sprintf("string method: %v", s.X) } func (s *stringer) SlogValue() interface{} { return slog.ForceJSON(s) } func main() { l := sloghuman.Make(os.Stdout) l.Info(context.Background(), "hello", slog.F("stringer", &stringer{X: 3})) // 2019-12-06 23:33:40.263 [INFO] <example_force_json_test.go:27> hello {"stringer": {"x": 3}} }
Output:
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 = sloghuman.Make(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 Info level and the given ctx will be passed to the logger's Info 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, sloghuman.Make(os.Stdout)) l.Print("msg") // 2019-12-07 20:54:23.986 [INFO] (stdlib) <example_test.go:29> 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 := sloghuman.Make(os.Stdout) l.Info(ctx, "msg") // 2019-12-07 20:54:23.986 [INFO] <example_test.go:20> msg {"field": 1} }
Output:
Types ¶
type Field ¶
type Field struct { Name string Value interface{} }
Field represents a log field.
type Logger ¶
type Logger struct {
// contains filtered or unexported fields
}
Logger allows logging a ordered slice of fields to an underlying set of sinks.
func Tee ¶
Tee enables logging to multiple loggers.
Example ¶
package main import ( "context" "os" "cdr.dev/slog" "cdr.dev/slog/sloggers/sloghuman" "cdr.dev/slog/sloggers/slogstackdriver" ) func main() { ctx := context.Background() l := sloghuman.Make(os.Stdout) f, err := os.OpenFile("stackdriver", os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0644) if err != nil { l.Fatal(ctx, "failed to open stackdriver log file", slog.Error(err)) } l = slog.Tee(l, slogstackdriver.Make(f, nil)) l.Info(ctx, "log to stdout and stackdriver") // 2019-12-07 20:59:55.790 [INFO] <example_test.go:46> log to stdout and stackdriver }
Output:
func (Logger) Named ¶
Named names the logger. If there is already a name set, it will be joined by ".". E.g. if the name is currently "my_component" and then later the name "my_pkg" is set, then the final component will be "my_component.my_pkg".
Example ¶
package main import ( "context" "net" "os" "cdr.dev/slog" "cdr.dev/slog/sloggers/sloghuman" ) func main() { ctx := context.Background() l := sloghuman.Make(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) <example_test.go:85> received request {"remote address": "127.0.0.1"} }
Output:
func (Logger) SetLevel ¶
SetLevel changes the Logger's level.
Example ¶
package main import ( "context" "os" "cdr.dev/slog" "cdr.dev/slog/sloggers/sloghuman" ) func main() { ctx := context.Background() l := sloghuman.Make(os.Stdout) l.Debug(ctx, "testing1") l.Info(ctx, "received request") l.SetLevel(slog.LevelDebug) l.Debug(ctx, "testing2") // 2019-12-07 21:26:20.945 [INFO] <example_test.go:95> received request // 2019-12-07 21:26:20.945 [DEBUG] <example_test.go:99> testing2 }
Output:
func (Logger) Sync ¶
func (l Logger) Sync()
Sync calls Sync on the sinks underlying the logger. Used it to ensure all logs are flushed during exit.
type Map ¶
type Map []Field
Map represents an ordered map of fields.
func (Map) MarshalJSON ¶
MarshalJSON implements json.Marshaler.
type SinkEntry ¶
type SinkEntry struct { Time time.Time Level Level Message string LoggerName string Func string File string Line int SpanContext trace.SpanContext Fields Map }
SinkEntry represents the structure of a log entry. It is the argument to the sink when logging.
type Value ¶
type Value interface {
SlogValue() interface{}
}
Value represents a log value. Implement SlogValue in your own types to override the value encoded when logging.
Example ¶
package main import ( "context" "os" "cdr.dev/slog" "cdr.dev/slog/sloggers/sloghuman" ) type vals struct { first int second int } func (s *vals) SlogValue() interface{} { return slog.M( slog.F("total", s.first+s.second), slog.F("first", s.first), slog.F("second", s.second), ) } func main() { l := sloghuman.Make(os.Stdout) l.Info(context.Background(), "hello", slog.F("val", &vals{ first: 3, second: 6, })) // 2019-12-07 21:06:14.636 [INFO] <example_value_test.go:26> hello {"val": {"total": 9, "first": 3, "second": 6}} }
Output:
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 a JSON format.
|
Package slogjson contains the slogger that writes logs in a JSON format. |
slogstackdriver
Package slogstackdriver contains the slogger for GCP.
|
Package slogstackdriver contains the slogger for GCP. |
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. |