diff --git a/go.mod b/go.mod index 22bb506a..0c38bfad 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/emersion/go-imap v1.2.1 github.com/emersion/go-sasl v0.0.0-20220912192320-0145f2c60ead github.com/google/go-cmp v0.5.9 - github.com/rs/zerolog v1.29.1 + github.com/rs/zerolog v1.30.0 github.com/sqs/go-xoauth2 v0.0.0-20120917012134-0911dad68e56 golang.org/x/oauth2 v0.10.0 gopkg.in/ini.v1 v1.67.0 diff --git a/go.sum b/go.sum index ddb71d18..43fda0bc 100644 --- a/go.sum +++ b/go.sum @@ -26,9 +26,9 @@ github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APP github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/rs/xid v1.4.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= -github.com/rs/zerolog v1.29.1 h1:cO+d60CHkknCbvzEWxP0S9K6KqyTjrCNUy1LdQLCGPc= -github.com/rs/zerolog v1.29.1/go.mod h1:Le6ESbR7hc+DP6Lt1THiV8CQSdkkNrd3R0XbEgp3ZBU= +github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= +github.com/rs/zerolog v1.30.0 h1:SymVODrcRsaRaSInD9yQtKbtWqwsfoPcRff/oRXLj4c= +github.com/rs/zerolog v1.30.0/go.mod h1:/tk+P47gFdPXq4QYjvCmT5/Gsug2nagsFWBWhAiSi1w= github.com/sqs/go-xoauth2 v0.0.0-20120917012134-0911dad68e56 h1:KCgKdj+ha4CgnVHIiJYGKzgZk3HfCc6XssESfOa6atM= github.com/sqs/go-xoauth2 v0.0.0-20120917012134-0911dad68e56/go.mod h1:ghDEBrT4oFcM4rv18bzcZaAWXbHPGpDa4e2hh9oXL8A= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= diff --git a/vendor/github.com/rs/zerolog/README.md b/vendor/github.com/rs/zerolog/README.md index e8cbfc28..b83ae159 100644 --- a/vendor/github.com/rs/zerolog/README.md +++ b/vendor/github.com/rs/zerolog/README.md @@ -24,7 +24,7 @@ Find out [who uses zerolog](https://github.com/rs/zerolog/wiki/Who-uses-zerolog) * [Sampling](#log-sampling) * [Hooks](#hooks) * [Contextual fields](#contextual-logging) -* `context.Context` integration +* [`context.Context` integration](#contextcontext-integration) * [Integration with `net/http`](#integration-with-nethttp) * [JSON and CBOR encoding formats](#binary-encoding) * [Pretty logging for development](#pretty-logging) @@ -499,7 +499,7 @@ log.Ctx(ctx).Info().Msg("hello world") ### Set as standard logger output ```go -log := zerolog.New(os.Stdout).With(). +stdlog := zerolog.New(os.Stdout).With(). Str("foo", "bar"). Logger() @@ -511,6 +511,58 @@ stdlog.Print("hello world") // Output: {"foo":"bar","message":"hello world"} ``` +### context.Context integration + +Go contexts are commonly passed throughout Go code, and this can help you pass +your Logger into places it might otherwise be hard to inject. The `Logger` +instance may be attached to Go context (`context.Context`) using +`Logger.WithContext(ctx)` and extracted from it using `zerolog.Ctx(ctx)`. +For example: + +```go +func f() { + logger := zerolog.New(os.Stdout) + ctx := context.Background() + + // Attach the Logger to the context.Context + ctx = logger.WithContext(ctx) + someFunc(ctx) +} + +func someFunc(ctx context.Context) { + // Get Logger from the go Context. if it's nil, then + // `zerolog.DefaultContextLogger` is returned, if + // `DefaultContextLogger` is nil, then a disabled logger is returned. + logger := zerolog.Ctx(ctx) + logger.Info().Msg("Hello") +} +``` + +A second form of `context.Context` integration allows you to pass the current +context.Context into the logged event, and retrieve it from hooks. This can be +useful to log trace and span IDs or other information stored in the go context, +and facilitates the unification of logging and tracing in some systems: + +```go +type TracingHook struct{} + +func (h TracingHook) Run(e *zerolog.Event, level zerolog.Level, msg string) { + ctx := e.Ctx() + spanId := getSpanIdFromContext(ctx) // as per your tracing framework + e.Str("span-id", spanId) +} + +func f() { + // Setup the logger + logger := zerolog.New(os.Stdout) + logger = logger.Hook(TracingHook{}) + + ctx := context.Background() + // Use the Ctx function to make the context available to the hook + logger.Info().Ctx(ctx).Msg("Hello") +} +``` + ### Integration with `net/http` The `github.com/rs/zerolog/hlog` package provides some helpers to integrate zerolog with `http.Handler`. @@ -703,6 +755,8 @@ Log a static string, without any context or `printf`-style templating: ## Caveats +### Field duplication + Note that zerolog does no de-duplication of fields. Using the same key multiple times creates multiple keys in final JSON: ```go @@ -714,3 +768,19 @@ logger.Info(). ``` In this case, many consumers will take the last value, but this is not guaranteed; check yours if in doubt. + +### Concurrency safety + +Be careful when calling UpdateContext. It is not concurrency safe. Use the With method to create a child logger: + +```go +func handler(w http.ResponseWriter, r *http.Request) { + // Create a child logger for concurrency safety + logger := log.Logger.With().Logger() + + // Add context fields, for example User-Agent from HTTP headers + logger.UpdateContext(func(c zerolog.Context) zerolog.Context { + ... + }) +} +``` diff --git a/vendor/github.com/rs/zerolog/context.go b/vendor/github.com/rs/zerolog/context.go index f398e319..9d860e50 100644 --- a/vendor/github.com/rs/zerolog/context.go +++ b/vendor/github.com/rs/zerolog/context.go @@ -1,6 +1,7 @@ package zerolog import ( + "context" "fmt" "io/ioutil" "math" @@ -165,6 +166,15 @@ func (c Context) Err(err error) Context { return c.AnErr(ErrorFieldName, err) } +// Ctx adds the context.Context to the logger context. The context.Context is +// not rendered in the error message, but is made available for hooks to use. +// A typical use case is to extract tracing information from the +// context.Context. +func (c Context) Ctx(ctx context.Context) Context { + c.l.ctx = ctx + return c +} + // Bool adds the field key with val as a bool to the logger context. func (c Context) Bool(key string, b bool) Context { c.l.context = enc.AppendBool(enc.AppendKey(c.l.context, key), b) @@ -329,8 +339,9 @@ func (ts timestampHook) Run(e *Event, level Level, msg string) { var th = timestampHook{} -// Timestamp adds the current local time as UNIX timestamp to the logger context with the "time" key. +// Timestamp adds the current local time to the logger context with the "time" key, formatted using zerolog.TimeFieldFormat. // To customize the key name, change zerolog.TimestampFieldName. +// To customize the time format, change zerolog.TimeFieldFormat. // // NOTE: It won't dedupe the "time" key if the *Context has one already. func (c Context) Timestamp() Context { diff --git a/vendor/github.com/rs/zerolog/encoder_cbor.go b/vendor/github.com/rs/zerolog/encoder_cbor.go index 7b0dafef..36cb994b 100644 --- a/vendor/github.com/rs/zerolog/encoder_cbor.go +++ b/vendor/github.com/rs/zerolog/encoder_cbor.go @@ -24,6 +24,9 @@ func init() { func appendJSON(dst []byte, j []byte) []byte { return cbor.AppendEmbeddedJSON(dst, j) } +func appendCBOR(dst []byte, c []byte) []byte { + return cbor.AppendEmbeddedCBOR(dst, c) +} // decodeIfBinaryToString - converts a binary formatted log msg to a // JSON formatted String Log message. diff --git a/vendor/github.com/rs/zerolog/encoder_json.go b/vendor/github.com/rs/zerolog/encoder_json.go index 0e0450e2..6f96c68a 100644 --- a/vendor/github.com/rs/zerolog/encoder_json.go +++ b/vendor/github.com/rs/zerolog/encoder_json.go @@ -6,6 +6,7 @@ package zerolog // JSON encoded byte stream. import ( + "encoding/base64" "github.com/rs/zerolog/internal/json" ) @@ -25,6 +26,17 @@ func init() { func appendJSON(dst []byte, j []byte) []byte { return append(dst, j...) } +func appendCBOR(dst []byte, cbor []byte) []byte { + dst = append(dst, []byte("\"data:application/cbor;base64,")...) + l := len(dst) + enc := base64.StdEncoding + n := enc.EncodedLen(len(cbor)) + for i := 0; i < n; i++ { + dst = append(dst, '.') + } + enc.Encode(dst[l:], cbor) + return append(dst, '"') +} func decodeIfBinaryToString(in []byte) string { return string(in) diff --git a/vendor/github.com/rs/zerolog/event.go b/vendor/github.com/rs/zerolog/event.go index 2e736c83..2a5d3b08 100644 --- a/vendor/github.com/rs/zerolog/event.go +++ b/vendor/github.com/rs/zerolog/event.go @@ -1,6 +1,7 @@ package zerolog import ( + "context" "fmt" "net" "os" @@ -24,9 +25,10 @@ type Event struct { w LevelWriter level Level done func(msg string) - stack bool // enable error stack trace - ch []Hook // hooks from context - skipFrame int // The number of additional frames to skip when printing the caller. + stack bool // enable error stack trace + ch []Hook // hooks from context + skipFrame int // The number of additional frames to skip when printing the caller. + ctx context.Context // Optional Go context for event } func putEvent(e *Event) { @@ -318,6 +320,18 @@ func (e *Event) RawJSON(key string, b []byte) *Event { return e } +// RawCBOR adds already encoded CBOR to the log line under key. +// +// No sanity check is performed on b +// Note: The full featureset of CBOR is supported as data will not be mapped to json but stored as data-url +func (e *Event) RawCBOR(key string, b []byte) *Event { + if e == nil { + return e + } + e.buf = appendCBOR(enc.AppendKey(e.buf, key), b) + return e +} + // AnErr adds the field key with serialized err to the *Event context. // If err is nil, no field is added. func (e *Event) AnErr(key string, err error) *Event { @@ -405,6 +419,28 @@ func (e *Event) Stack() *Event { return e } +// Ctx adds the Go Context to the *Event context. The context is not rendered +// in the output message, but is available to hooks and to Func() calls via the +// GetCtx() accessor. A typical use case is to extract tracing information from +// the Go Ctx. +func (e *Event) Ctx(ctx context.Context) *Event { + if e != nil { + e.ctx = ctx + } + return e +} + +// GetCtx retrieves the Go context.Context which is optionally stored in the +// Event. This allows Hooks and functions passed to Func() to retrieve values +// which are stored in the context.Context. This can be useful in tracing, +// where span information is commonly propagated in the context.Context. +func (e *Event) GetCtx() context.Context { + if e == nil || e.ctx == nil { + return context.Background() + } + return e.ctx +} + // Bool adds the field key with val as a bool to the *Event context. func (e *Event) Bool(key string, b bool) *Event { if e == nil { diff --git a/vendor/github.com/rs/zerolog/internal/cbor/cbor.go b/vendor/github.com/rs/zerolog/internal/cbor/cbor.go index bc54e37a..1bf14438 100644 --- a/vendor/github.com/rs/zerolog/internal/cbor/cbor.go +++ b/vendor/github.com/rs/zerolog/internal/cbor/cbor.go @@ -26,7 +26,8 @@ const ( additionalTypeBreak byte = 31 // Tag Sub-types. - additionalTypeTimestamp byte = 01 + additionalTypeTimestamp byte = 01 + additionalTypeEmbeddedCBOR byte = 63 // Extended Tags - from https://www.iana.org/assignments/cbor-tags/cbor-tags.xhtml additionalTypeTagNetworkAddr uint16 = 260 diff --git a/vendor/github.com/rs/zerolog/internal/cbor/decode_stream.go b/vendor/github.com/rs/zerolog/internal/cbor/decode_stream.go index fc16f98c..616bed65 100644 --- a/vendor/github.com/rs/zerolog/internal/cbor/decode_stream.go +++ b/vendor/github.com/rs/zerolog/internal/cbor/decode_stream.go @@ -5,6 +5,7 @@ package cbor import ( "bufio" "bytes" + "encoding/base64" "fmt" "io" "math" @@ -213,6 +214,31 @@ func decodeString(src *bufio.Reader, noQuotes bool) []byte { } return append(result, '"') } +func decodeStringToDataUrl(src *bufio.Reader, mimeType string) []byte { + pb := readByte(src) + major := pb & maskOutAdditionalType + minor := pb & maskOutMajorType + if major != majorTypeByteString { + panic(fmt.Errorf("Major type is: %d in decodeString", major)) + } + length := decodeIntAdditionalType(src, minor) + l := int(length) + enc := base64.StdEncoding + lEnc := enc.EncodedLen(l) + result := make([]byte, len("\"data:;base64,\"")+len(mimeType)+lEnc) + dest := result + u := copy(dest, "\"data:") + dest = dest[u:] + u = copy(dest, mimeType) + dest = dest[u:] + u = copy(dest, ";base64,") + dest = dest[u:] + pbs := readNBytes(src, l) + enc.Encode(dest, pbs) + dest = dest[lEnc:] + dest[0] = '"' + return result +} func decodeUTF8String(src *bufio.Reader) []byte { pb := readByte(src) @@ -349,6 +375,20 @@ func decodeTagData(src *bufio.Reader) []byte { switch minor { case additionalTypeTimestamp: return decodeTimeStamp(src) + case additionalTypeIntUint8: + val := decodeIntAdditionalType(src, minor) + switch byte(val) { + case additionalTypeEmbeddedCBOR: + pb := readByte(src) + dataMajor := pb & maskOutAdditionalType + if dataMajor != majorTypeByteString { + panic(fmt.Errorf("Unsupported embedded Type: %d in decodeEmbeddedCBOR", dataMajor)) + } + src.UnreadByte() + return decodeStringToDataUrl(src, "application/cbor") + default: + panic(fmt.Errorf("Unsupported Additional Tag Type: %d in decodeTagData", val)) + } // Tag value is larger than 256 (so uint16). case additionalTypeIntUint16: diff --git a/vendor/github.com/rs/zerolog/internal/cbor/string.go b/vendor/github.com/rs/zerolog/internal/cbor/string.go index a33890a5..9fc9a4f8 100644 --- a/vendor/github.com/rs/zerolog/internal/cbor/string.go +++ b/vendor/github.com/rs/zerolog/internal/cbor/string.go @@ -93,3 +93,25 @@ func AppendEmbeddedJSON(dst, s []byte) []byte { } return append(dst, s...) } + +// AppendEmbeddedCBOR adds a tag and embeds input CBOR as such. +func AppendEmbeddedCBOR(dst, s []byte) []byte { + major := majorTypeTags + minor := additionalTypeEmbeddedCBOR + + // Append the TAG to indicate this is Embedded JSON. + dst = append(dst, major|additionalTypeIntUint8) + dst = append(dst, minor) + + // Append the CBOR Object as Byte String. + major = majorTypeByteString + + l := len(s) + if l <= additionalMax { + lb := byte(l) + dst = append(dst, major|lb) + } else { + dst = appendCborTypePrefix(dst, major, uint64(l)) + } + return append(dst, s...) +} diff --git a/vendor/github.com/rs/zerolog/log.go b/vendor/github.com/rs/zerolog/log.go index 0b51676c..e7b5126e 100644 --- a/vendor/github.com/rs/zerolog/log.go +++ b/vendor/github.com/rs/zerolog/log.go @@ -82,8 +82,9 @@ // log.Warn().Msg("") // // Output: {"level":"warn","severity":"warn"} // +// # Caveats // -// Caveats +// Field duplication: // // There is no fields deduplication out-of-the-box. // Using the same key multiple times creates new key in final JSON each time. @@ -96,9 +97,24 @@ // // In this case, many consumers will take the last value, // but this is not guaranteed; check yours if in doubt. +// +// Concurrency safety: +// +// Be careful when calling UpdateContext. It is not concurrency safe. Use the With method to create a child logger: +// +// func handler(w http.ResponseWriter, r *http.Request) { +// // Create a child logger for concurrency safety +// logger := log.Logger.With().Logger() +// +// // Add context fields, for example User-Agent from HTTP headers +// logger.UpdateContext(func(c zerolog.Context) zerolog.Context { +// ... +// }) +// } package zerolog import ( + "context" "errors" "fmt" "io" @@ -218,6 +234,7 @@ type Logger struct { context []byte hooks []Hook stack bool + ctx context.Context } // New creates a root logger with given output writer. If the output writer implements @@ -275,7 +292,8 @@ func (l Logger) With() Context { // UpdateContext updates the internal logger's context. // -// Use this method with caution. If unsure, prefer the With method. +// Caution: This method is not concurrency safe. +// Use the With method to create a child logger before modifying the context from concurrent goroutines. func (l *Logger) UpdateContext(update func(c Context) Context) { if l == disabledLogger { return @@ -309,7 +327,9 @@ func (l Logger) Sample(s Sampler) Logger { // Hook returns a logger with the h Hook. func (l Logger) Hook(h Hook) Logger { - l.hooks = append(l.hooks, h) + newHooks := make([]Hook, len(l.hooks), len(l.hooks)+1) + copy(newHooks, l.hooks) + l.hooks = append(newHooks, h) return l } @@ -453,6 +473,7 @@ func (l *Logger) newEvent(level Level, done func(string)) *Event { e := newEvent(l.w, level) e.done = done e.ch = l.hooks + e.ctx = l.ctx if level != NoLevel && LevelFieldName != "" { e.Str(LevelFieldName, LevelFieldMarshalFunc(level)) } diff --git a/vendor/modules.txt b/vendor/modules.txt index d67bc35f..ac34e13c 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -27,7 +27,7 @@ github.com/mattn/go-colorable # github.com/mattn/go-isatty v0.0.19 ## explicit; go 1.15 github.com/mattn/go-isatty -# github.com/rs/zerolog v1.29.1 +# github.com/rs/zerolog v1.30.0 ## explicit; go 1.15 github.com/rs/zerolog github.com/rs/zerolog/internal/cbor