...

Text file src/cdr.dev/slog/README.md

Documentation: cdr.dev/slog

     1# slog
     2
     3[![GitHub Release](https://img.shields.io/github/v/release/cdr/slog?color=6b9ded&sort=semver)](https://github.com/cdr/slog/releases)
     4[![GoDoc](https://godoc.org/cdr.dev/slog?status.svg)](https://godoc.org/cdr.dev/slog)
     5[![Coveralls](https://img.shields.io/coveralls/github/cdr/slog?color=65d6a4)](https://coveralls.io/github/cdr/slog)
     6[![CI Status](https://github.com/cdr/slog/workflows/ci/badge.svg)](https://github.com/cdr/slog/actions)
     7
     8slog is a minimal structured logging library for Go.
     9
    10## Install
    11
    12```bash
    13go get cdr.dev/slog
    14```
    15
    16## Features
    17
    18- Minimal API
    19- First class [context.Context](https://blog.golang.org/context) support
    20- First class [testing.TB](https://godoc.org/cdr.dev/slog/sloggers/slogtest) support
    21  - Package [slogtest/assert](https://godoc.org/cdr.dev/slog/sloggers/slogtest/assert) provides test assertion helpers
    22- Beautiful human readable logging output
    23  - Prints multiline fields and errors nicely
    24- Machine readable JSON output
    25- [GCP Stackdriver](https://godoc.org/cdr.dev/slog/sloggers/slogstackdriver) support
    26- [Stdlib](https://godoc.org/cdr.dev/slog#Stdlib) log adapter
    27- Skip caller frames with [slog.Helper](https://godoc.org/cdr.dev/slog#Helper)
    28- Encodes values as if with `json.Marshal`
    29- Transparently log [opencensus](https://godoc.org/go.opencensus.io/trace) trace and span IDs
    30- [Single dependency](https://godoc.org/cdr.dev/slog?imports) on go.opencensus.io
    31- Log to multiple sinks
    32
    33## Example
    34
    35Many more examples available at [godoc](https://godoc.org/cdr.dev/slog#pkg-examples).
    36
    37```go
    38log := slog.Make(sloghuman.Sink(os.Stdout))
    39
    40log.Info(context.Background(), "my message here",
    41    slog.F("field_name", "something or the other"),
    42    slog.F("some_map", slog.M(
    43        slog.F("nested_fields", time.Date(2000, time.February, 5, 4, 4, 4, 0, time.UTC)),
    44    )),
    45    slog.Error(
    46        xerrors.Errorf("wrap1: %w",
    47            xerrors.Errorf("wrap2: %w",
    48                io.EOF,
    49            ),
    50        ),
    51    ),
    52)
    53```
    54
    55![Example output screenshot](https://i.imgur.com/KGRmQFo.png)
    56
    57## Why?
    58
    59At [Coder](https://github.com/cdr) we’ve used Uber’s [zap](https://github.com/uber-go/zap) for several years.
    60It is a fantastic library for performance. Thanks Uber!
    61
    62However we felt the API and developer experience could be improved.
    63
    64Here is a list of reasons how we improved on zap with slog.
    65
    661. `slog` has a minimal API surface
    67
    68   - Compare [slog](https://godoc.org/cdr.dev/slog) to [zap](https://godoc.org/go.uber.org/zap) and
    69     [zapcore](https://godoc.org/go.uber.org/zap/zapcore).
    70   - The sprawling API makes zap hard to understand, use and extend.
    71
    721. `slog` has a concise semi typed API
    73
    74   - We found zap's fully typed API cumbersome. It does offer a
    75     [sugared API](https://godoc.org/go.uber.org/zap#hdr-Choosing_a_Logger)
    76     but it's too easy to pass an invalid fields list since there is no static type checking.
    77     Furthermore, it's harder to read as there is no syntax grouping for each key value pair.
    78   - We wanted an API that only accepted the equivalent of [zap.Any](https://godoc.org/go.uber.org/zap#Any)
    79     for every field. This is [slog.F](https://godoc.org/cdr.dev/slog#F).
    80
    811. [`sloghuman`](https://godoc.org/cdr.dev/slog/sloggers/sloghuman) uses a very human readable format
    82
    83   - It colors distinct parts of each line to make it easier to scan logs. Even the JSON that represents
    84     the fields in each log is syntax highlighted so that is very easy to scan. See the screenshot above.
    85     - zap lacks appropriate colors for different levels and fields.
    86   - slog automatically prints one multiline field after the log to make errors and such much easier to read.
    87     - zap logs multiline fields and errors stack traces as JSON strings which made them unreadable in a terminal.
    88   - When logging to JSON, slog automatically converts a [`golang.org/x/xerrors`](https://golang.org/x/xerrors) chain
    89     into an array with fields for the location and wrapping messages.
    90
    911. Full [context.Context](https://blog.golang.org/context) support
    92
    93   - `slog` lets you set fields in a `context.Context` such that any log with the context prints those fields.
    94   - We wanted to be able to pull up all relevant logs for a given trace, user or request. With zap, we were plugging
    95     these fields in for every relevant log or passing around a logger with the fields set. This became very verbose.
    96
    971. Simple and easy to extend
    98
    99   - A new backend only has to implement the simple Sink interface.
   100   - The Logger type provides a nice API around Sink but also implements
   101     Sink to allow for composition.
   102   - zap is hard and confusing to extend. There are too many structures and configuration options.
   103
   1041. Structured logging of Go structures with `json.Marshal`
   105
   106   - Entire encoding process is documented on [godoc](https://godoc.org/cdr.dev/slog#Map.MarshalJSON).
   107   - With zap, We found ourselves often implementing zap's
   108     [ObjectMarshaler](https://godoc.org/go.uber.org/zap/zapcore#ObjectMarshaler) to log Go structures. This was
   109     verbose and most of the time we ended up only implementing `fmt.Stringer` and using `zap.Stringer` instead.
   110
   1111. slog takes inspiration from Go's stdlib and implements [`slog.Helper`](https://godoc.org/cdr.dev/slog#Helper)
   112   which works just like [`t.Helper`](https://golang.org/pkg/testing/#T.Helper)
   113
   114   - It marks the calling function as a helper and skips it when reporting location info.
   115   - We had many helper functions for logging but we wanted the line reported to be of the parent function.
   116     zap has an [API](https://godoc.org/go.uber.org/zap#AddCallerSkip) for this but it's verbose and requires
   117     passing the logger around explicitly.
   118
   1191. Tight integration with stdlib's [`testing`](https://golang.org/pkg/testing) package
   120   - You can configure [`slogtest`](https://godoc.org/cdr.dev/slog/sloggers/slogtest) to exit on any ERROR logs
   121     and it has a global stateless API that takes a `testing.TB` so you do not need to create a logger first.
   122   - Test assertion helpers are provided in [slogtest/assert](https://godoc.org/cdr.dev/slog/sloggers/slogtest/assert).
   123   - zap has [zaptest](https://godoc.org/go.uber.org/zap/zaptest) but the API surface is large and doesn't
   124     integrate well. It does not support any of the features described above.

View as plain text