diff -Nru golang-github-rs-zerolog-1.26.1/array.go golang-github-rs-zerolog-1.29.1/array.go --- golang-github-rs-zerolog-1.26.1/array.go 2021-12-15 23:37:18.000000000 +0000 +++ golang-github-rs-zerolog-1.29.1/array.go 2023-03-20 19:29:36.000000000 +0000 @@ -49,7 +49,7 @@ func (a *Array) write(dst []byte) []byte { dst = enc.AppendArrayStart(dst) if len(a.buf) > 0 { - dst = append(append(dst, a.buf...)) + dst = append(dst, a.buf...) } dst = enc.AppendArrayEnd(dst) putArray(a) @@ -57,7 +57,7 @@ } // Object marshals an object that implement the LogObjectMarshaler -// interface and append append it to the array. +// interface and appends it to the array. func (a *Array) Object(obj LogObjectMarshaler) *Array { e := Dict() obj.MarshalZerologObject(e) @@ -67,19 +67,19 @@ return a } -// Str append append the val as a string to the array. +// Str appends the val as a string to the array. func (a *Array) Str(val string) *Array { a.buf = enc.AppendString(enc.AppendArrayDelim(a.buf), val) return a } -// Bytes append append the val as a string to the array. +// Bytes appends the val as a string to the array. func (a *Array) Bytes(val []byte) *Array { a.buf = enc.AppendBytes(enc.AppendArrayDelim(a.buf), val) return a } -// Hex append append the val as a hex string to the array. +// Hex appends the val as a hex string to the array. func (a *Array) Hex(val []byte) *Array { a.buf = enc.AppendHex(enc.AppendArrayDelim(a.buf), val) return a @@ -115,97 +115,97 @@ return a } -// Bool append append the val as a bool to the array. +// Bool appends the val as a bool to the array. func (a *Array) Bool(b bool) *Array { a.buf = enc.AppendBool(enc.AppendArrayDelim(a.buf), b) return a } -// Int append append i as a int to the array. +// Int appends i as a int to the array. func (a *Array) Int(i int) *Array { a.buf = enc.AppendInt(enc.AppendArrayDelim(a.buf), i) return a } -// Int8 append append i as a int8 to the array. +// Int8 appends i as a int8 to the array. func (a *Array) Int8(i int8) *Array { a.buf = enc.AppendInt8(enc.AppendArrayDelim(a.buf), i) return a } -// Int16 append append i as a int16 to the array. +// Int16 appends i as a int16 to the array. func (a *Array) Int16(i int16) *Array { a.buf = enc.AppendInt16(enc.AppendArrayDelim(a.buf), i) return a } -// Int32 append append i as a int32 to the array. +// Int32 appends i as a int32 to the array. func (a *Array) Int32(i int32) *Array { a.buf = enc.AppendInt32(enc.AppendArrayDelim(a.buf), i) return a } -// Int64 append append i as a int64 to the array. +// Int64 appends i as a int64 to the array. func (a *Array) Int64(i int64) *Array { a.buf = enc.AppendInt64(enc.AppendArrayDelim(a.buf), i) return a } -// Uint append append i as a uint to the array. +// Uint appends i as a uint to the array. func (a *Array) Uint(i uint) *Array { a.buf = enc.AppendUint(enc.AppendArrayDelim(a.buf), i) return a } -// Uint8 append append i as a uint8 to the array. +// Uint8 appends i as a uint8 to the array. func (a *Array) Uint8(i uint8) *Array { a.buf = enc.AppendUint8(enc.AppendArrayDelim(a.buf), i) return a } -// Uint16 append append i as a uint16 to the array. +// Uint16 appends i as a uint16 to the array. func (a *Array) Uint16(i uint16) *Array { a.buf = enc.AppendUint16(enc.AppendArrayDelim(a.buf), i) return a } -// Uint32 append append i as a uint32 to the array. +// Uint32 appends i as a uint32 to the array. func (a *Array) Uint32(i uint32) *Array { a.buf = enc.AppendUint32(enc.AppendArrayDelim(a.buf), i) return a } -// Uint64 append append i as a uint64 to the array. +// Uint64 appends i as a uint64 to the array. func (a *Array) Uint64(i uint64) *Array { a.buf = enc.AppendUint64(enc.AppendArrayDelim(a.buf), i) return a } -// Float32 append append f as a float32 to the array. +// Float32 appends f as a float32 to the array. func (a *Array) Float32(f float32) *Array { a.buf = enc.AppendFloat32(enc.AppendArrayDelim(a.buf), f) return a } -// Float64 append append f as a float64 to the array. +// Float64 appends f as a float64 to the array. func (a *Array) Float64(f float64) *Array { a.buf = enc.AppendFloat64(enc.AppendArrayDelim(a.buf), f) return a } -// Time append append t formated as string using zerolog.TimeFieldFormat. +// Time appends t formatted as string using zerolog.TimeFieldFormat. func (a *Array) Time(t time.Time) *Array { a.buf = enc.AppendTime(enc.AppendArrayDelim(a.buf), t, TimeFieldFormat) return a } -// Dur append append d to the array. +// Dur appends d to the array. func (a *Array) Dur(d time.Duration) *Array { a.buf = enc.AppendDuration(enc.AppendArrayDelim(a.buf), d, DurationFieldUnit, DurationFieldInteger) return a } -// Interface append append i marshaled using reflection. +// Interface appends i marshaled using reflection. func (a *Array) Interface(i interface{}) *Array { if obj, ok := i.(LogObjectMarshaler); ok { return a.Object(obj) diff -Nru golang-github-rs-zerolog-1.26.1/cmd/lint/go.mod golang-github-rs-zerolog-1.29.1/cmd/lint/go.mod --- golang-github-rs-zerolog-1.26.1/cmd/lint/go.mod 1970-01-01 00:00:00.000000000 +0000 +++ golang-github-rs-zerolog-1.29.1/cmd/lint/go.mod 2023-03-20 19:29:36.000000000 +0000 @@ -0,0 +1,5 @@ +module github.com/rs/zerolog/cmd/lint + +go 1.15 + +require golang.org/x/tools v0.1.8 diff -Nru golang-github-rs-zerolog-1.26.1/cmd/lint/go.sum golang-github-rs-zerolog-1.29.1/cmd/lint/go.sum --- golang-github-rs-zerolog-1.26.1/cmd/lint/go.sum 1970-01-01 00:00:00.000000000 +0000 +++ golang-github-rs-zerolog-1.29.1/cmd/lint/go.sum 2023-03-20 19:29:36.000000000 +0000 @@ -0,0 +1,28 @@ +github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/mod v0.5.1 h1:OJxoQ/rynoF0dcCdI7cLPktw/hR2cueqYfjm43oqK38= +golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20211019181941-9d821ace8654 h1:id054HUawV2/6IGm2IV8KZQjqtwAOo2CYlOToYqa0d0= +golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.8 h1:P1HhGGuLW4aAclzjtmJdf0mJOjVUZUzOTqkAkWL+l6w= +golang.org/x/tools v0.1.8/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff -Nru golang-github-rs-zerolog-1.26.1/cmd/lint/readme.md golang-github-rs-zerolog-1.29.1/cmd/lint/readme.md --- golang-github-rs-zerolog-1.26.1/cmd/lint/readme.md 2021-12-15 23:37:18.000000000 +0000 +++ golang-github-rs-zerolog-1.29.1/cmd/lint/readme.md 1970-01-01 00:00:00.000000000 +0000 @@ -1,37 +0,0 @@ -# Zerolog Lint - -This is a basic linter that checks for missing log event finishers. Finds errors like: `log.Error().Int64("userID": 5)` - missing the `Msg`/`Msgf` finishers. - -## Problem - -When using zerolog it's easy to forget to finish the log event chain by calling a finisher - the `Msg` or `Msgf` function that will schedule the event for writing. The problem with this is that it doesn't warn/panic during compilation and it's not easily found by grep or other general tools. It's even prominently mentioned in the project's readme, that: - -> It is very important to note that when using the **zerolog** chaining API, as shown above (`log.Info().Msg("hello world"`), the chain must have either the `Msg` or `Msgf` method call. If you forget to add either of these, the log will not occur and there is no compile time error to alert you of this. - -## Solution - -A basic linter like this one here that looks for method invocations on `zerolog.Event` can examine the last call in a method call chain and check if it is a finisher, thus pointing out these errors. - -## Usage - -Just compile this and then run it. Or just run it via `go run` command via something like `go run cmd/lint/lint.go`. - -The command accepts only one argument - the package to be inspected - and 4 optional flags, all of which can occur multiple times. The standard synopsis of the command is: - -`lint [-finisher value] [-ignoreFile value] [-ignorePkg value] [-ignorePkgRecursively value] package` - -#### Flags - -- finisher - - specify which finishers to accept, defaults to `Msg` and `Msgf` -- ignoreFile - - which files to ignore, either by full path or by go path (package/file.go) -- ignorePkg - - do not inspect the specified package if found in the dependecy tree -- ignorePkgRecursively - - do not inspect the specified package or its subpackages if found in the dependency tree - -## Drawbacks - -As it is, linter can generate a false positives in a specific case. These false positives come from the fact that if you have a method that returns a `zerolog.Event` the linter will flag it because you are obviously not finishing the event. This will be solved in later release. - diff -Nru golang-github-rs-zerolog-1.26.1/cmd/lint/README.md golang-github-rs-zerolog-1.29.1/cmd/lint/README.md --- golang-github-rs-zerolog-1.26.1/cmd/lint/README.md 1970-01-01 00:00:00.000000000 +0000 +++ golang-github-rs-zerolog-1.29.1/cmd/lint/README.md 2023-03-20 19:29:36.000000000 +0000 @@ -0,0 +1,37 @@ +# Zerolog Lint + +This is a basic linter that checks for missing log event finishers. Finds errors like: `log.Error().Int64("userID": 5)` - missing the `Msg`/`Msgf` finishers. + +## Problem + +When using zerolog it's easy to forget to finish the log event chain by calling a finisher - the `Msg` or `Msgf` function that will schedule the event for writing. The problem with this is that it doesn't warn/panic during compilation and it's not easily found by grep or other general tools. It's even prominently mentioned in the project's readme, that: + +> It is very important to note that when using the **zerolog** chaining API, as shown above (`log.Info().Msg("hello world"`), the chain must have either the `Msg` or `Msgf` method call. If you forget to add either of these, the log will not occur and there is no compile time error to alert you of this. + +## Solution + +A basic linter like this one here that looks for method invocations on `zerolog.Event` can examine the last call in a method call chain and check if it is a finisher, thus pointing out these errors. + +## Usage + +Just compile this and then run it. Or just run it via `go run` command via something like `go run cmd/lint/lint.go`. + +The command accepts only one argument - the package to be inspected - and 4 optional flags, all of which can occur multiple times. The standard synopsis of the command is: + +`lint [-finisher value] [-ignoreFile value] [-ignorePkg value] [-ignorePkgRecursively value] package` + +#### Flags + +- finisher + - specify which finishers to accept, defaults to `Msg` and `Msgf` +- ignoreFile + - which files to ignore, either by full path or by go path (package/file.go) +- ignorePkg + - do not inspect the specified package if found in the dependency tree +- ignorePkgRecursively + - do not inspect the specified package or its subpackages if found in the dependency tree + +## Drawbacks + +As it is, linter can generate a false positives in a specific case. These false positives come from the fact that if you have a method that returns a `zerolog.Event` the linter will flag it because you are obviously not finishing the event. This will be solved in later release. + diff -Nru golang-github-rs-zerolog-1.26.1/cmd/prettylog/prettylog.go golang-github-rs-zerolog-1.29.1/cmd/prettylog/prettylog.go --- golang-github-rs-zerolog-1.26.1/cmd/prettylog/prettylog.go 1970-01-01 00:00:00.000000000 +0000 +++ golang-github-rs-zerolog-1.29.1/cmd/prettylog/prettylog.go 2023-03-20 19:29:36.000000000 +0000 @@ -0,0 +1,26 @@ +package main + +import ( + "fmt" + "io" + "os" + + "github.com/rs/zerolog" +) + +func isInputFromPipe() bool { + fileInfo, _ := os.Stdin.Stat() + return fileInfo.Mode()&os.ModeCharDevice == 0 +} + +func main() { + if !isInputFromPipe() { + fmt.Println("The command is intended to work with pipes.") + fmt.Println("Usage: app_with_zerolog | 2> >(prettylog)") + os.Exit(1) + return + } + + writer := zerolog.NewConsoleWriter() + _, _ = io.Copy(writer, os.Stdin) +} diff -Nru golang-github-rs-zerolog-1.26.1/cmd/prettylog/README.md golang-github-rs-zerolog-1.29.1/cmd/prettylog/README.md --- golang-github-rs-zerolog-1.26.1/cmd/prettylog/README.md 1970-01-01 00:00:00.000000000 +0000 +++ golang-github-rs-zerolog-1.29.1/cmd/prettylog/README.md 2023-03-20 19:29:36.000000000 +0000 @@ -0,0 +1,40 @@ +# Zerolog PrettyLog + +This is a basic CLI utility that will colorize and pretty print your structured JSON logs. + +## Usage + +You can compile it or run it directly. The only issue is that by default Zerolog does not output to `stdout` +but rather to `stderr` so we must pipe `stderr` stream to this CLI tool. + +### Linux + +These commands will redirect `stderr` to our `prettylog` tool and `stdout` will remain unaffected. + +1. Compiled version + +```shell +some_program_with_zerolog 2> >(prettylog) +``` + +2. Run it directly with `go run` + +```shell +some_program_with_zerolog 2> >(go run cmd/prettylog/prettylog.go) +``` + +### Windows + +These commands will redirect `stderr` to `stdout` and then pipe it to our `prettylog` tool. + +1. Compiled version + +```shell +some_program_with_zerolog 2>&1 | prettylog +``` + +2. Run it directly with `go run` + +```shell +some_program_with_zerolog 2>&1 | go run cmd/prettylog/prettylog.go +``` diff -Nru golang-github-rs-zerolog-1.26.1/console.go golang-github-rs-zerolog-1.29.1/console.go --- golang-github-rs-zerolog-1.26.1/console.go 2021-12-15 23:37:18.000000000 +0000 +++ golang-github-rs-zerolog-1.29.1/console.go 2023-03-20 19:29:36.000000000 +0000 @@ -12,6 +12,8 @@ "strings" "sync" "time" + + "github.com/mattn/go-colorable" ) const ( @@ -61,6 +63,9 @@ // PartsExclude defines parts to not display in output. PartsExclude []string + // FieldsExclude defines contextual fields to not display in output. + FieldsExclude []string + FormatTimestamp Formatter FormatLevel Formatter FormatCaller Formatter @@ -69,6 +74,8 @@ FormatFieldValue Formatter FormatErrFieldName Formatter FormatErrFieldValue Formatter + + FormatExtra func(map[string]interface{}, *bytes.Buffer) error } // NewConsoleWriter creates and initializes a new ConsoleWriter. @@ -83,11 +90,21 @@ opt(&w) } + // Fix color on Windows + if w.Out == os.Stdout || w.Out == os.Stderr { + w.Out = colorable.NewColorable(w.Out.(*os.File)) + } + return w } // Write transforms the JSON input with formatters and appends to w.Out. func (w ConsoleWriter) Write(p []byte) (n int, err error) { + // Fix color on Windows + if w.Out == os.Stdout || w.Out == os.Stderr { + w.Out = colorable.NewColorable(w.Out.(*os.File)) + } + if w.PartsOrder == nil { w.PartsOrder = consoleDefaultPartsOrder() } @@ -113,10 +130,18 @@ w.writeFields(evt, buf) + if w.FormatExtra != nil { + err = w.FormatExtra(evt, buf) + if err != nil { + return n, err + } + } + err = buf.WriteByte('\n') if err != nil { return n, err } + _, err = buf.WriteTo(w.Out) return len(p), err } @@ -125,6 +150,17 @@ func (w ConsoleWriter) writeFields(evt map[string]interface{}, buf *bytes.Buffer) { var fields = make([]string, 0, len(evt)) for field := range evt { + var isExcluded bool + for _, excluded := range w.FieldsExclude { + if field == excluded { + isExcluded = true + break + } + } + if isExcluded { + continue + } + switch field { case LevelFieldName, TimestampFieldName, MessageFieldName, CallerFieldName: continue @@ -133,7 +169,8 @@ } sort.Strings(fields) - if len(fields) > 0 { + // Write space only if something has already been written to the buffer, and if there are fields. + if buf.Len() > 0 && len(fields) > 0 { buf.WriteByte(' ') } @@ -194,7 +231,7 @@ case json.Number: buf.WriteString(fv(fValue)) default: - b, err := json.Marshal(fValue) + b, err := InterfaceMarshalFunc(fValue) if err != nil { fmt.Fprintf(buf, colorize("[error: %v]", colorRed, w.NoColor), err) } else { @@ -256,10 +293,10 @@ var s = f(evt[p]) if len(s) > 0 { - buf.WriteString(s) - if p != w.PartsOrder[len(w.PartsOrder)-1] { // Skip space for last part - buf.WriteByte(' ') + if buf.Len() > 0 { + buf.WriteByte(' ') // Write space only if not the first part } + buf.WriteString(s) } } @@ -300,27 +337,31 @@ t := "" switch tt := i.(type) { case string: - ts, err := time.Parse(TimeFieldFormat, tt) + ts, err := time.ParseInLocation(TimeFieldFormat, tt, time.Local) if err != nil { t = tt } else { - t = ts.Format(timeFormat) + t = ts.Local().Format(timeFormat) } case json.Number: i, err := tt.Int64() if err != nil { t = tt.String() } else { - var sec, nsec int64 = i, 0 + var sec, nsec int64 + switch TimeFieldFormat { - case TimeFormatUnixMs: - nsec = int64(time.Duration(i) * time.Millisecond) - sec = 0 + case TimeFormatUnixNano: + sec, nsec = 0, i case TimeFormatUnixMicro: - nsec = int64(time.Duration(i) * time.Microsecond) - sec = 0 + sec, nsec = 0, int64(time.Duration(i)*time.Microsecond) + case TimeFormatUnixMs: + sec, nsec = 0, int64(time.Duration(i)*time.Millisecond) + default: + sec, nsec = i, 0 } - ts := time.Unix(sec, nsec).UTC() + + ts := time.Unix(sec, nsec) t = ts.Format(timeFormat) } } @@ -348,7 +389,7 @@ case LevelPanicValue: l = colorize(colorize("PNC", colorRed, noColor), colorBold, noColor) default: - l = colorize("???", colorBold, noColor) + l = colorize(ll, colorBold, noColor) } } else { if i == nil { diff -Nru golang-github-rs-zerolog-1.26.1/console_test.go golang-github-rs-zerolog-1.29.1/console_test.go --- golang-github-rs-zerolog-1.26.1/console_test.go 2021-12-15 23:37:18.000000000 +0000 +++ golang-github-rs-zerolog-1.29.1/console_test.go 2023-03-20 19:29:36.000000000 +0000 @@ -108,13 +108,14 @@ buf := &bytes.Buffer{} w := zerolog.ConsoleWriter{Out: buf, NoColor: true} - d := time.Unix(0, 0).UTC().Format(time.RFC3339) + ts := time.Unix(0, 0) + d := ts.UTC().Format(time.RFC3339) _, err := w.Write([]byte(`{"time": "` + d + `", "level": "debug", "message": "Foobar", "foo": "bar"}`)) if err != nil { t.Errorf("Unexpected error when writing output: %s", err) } - expectedOutput := "12:00AM DBG Foobar foo=bar\n" + expectedOutput := ts.Format(time.Kitchen) + " DBG Foobar foo=bar\n" actualOutput := buf.String() if actualOutput != expectedOutput { t.Errorf("Unexpected output %q, want: %q", actualOutput, expectedOutput) @@ -136,7 +137,7 @@ t.Errorf("Unexpected error when writing output: %s", err) } - expectedOutput := "Jan 1 00:20:34.000 DBG Foobar foo=bar\n" + expectedOutput := time.Unix(1234, 0).Format(time.StampMilli) + " DBG Foobar foo=bar\n" actualOutput := buf.String() if actualOutput != expectedOutput { t.Errorf("Unexpected output %q, want: %q", actualOutput, expectedOutput) @@ -158,7 +159,7 @@ t.Errorf("Unexpected error when writing output: %s", err) } - expectedOutput := "Jan 1 00:20:34.567 DBG Foobar foo=bar\n" + expectedOutput := time.Unix(1234, 567000000).Format(time.StampMilli) + " DBG Foobar foo=bar\n" actualOutput := buf.String() if actualOutput != expectedOutput { t.Errorf("Unexpected output %q, want: %q", actualOutput, expectedOutput) @@ -180,7 +181,7 @@ t.Errorf("Unexpected error when writing output: %s", err) } - expectedOutput := "Jan 1 00:20:34.567891 DBG Foobar foo=bar\n" + expectedOutput := time.Unix(1234, 567891000).Format(time.StampMicro) + " DBG Foobar foo=bar\n" actualOutput := buf.String() if actualOutput != expectedOutput { t.Errorf("Unexpected output %q, want: %q", actualOutput, expectedOutput) @@ -196,7 +197,7 @@ t.Errorf("Unexpected error when writing output: %s", err) } - expectedOutput := " DBG foo=bar\n" + expectedOutput := " DBG foo=bar\n" actualOutput := buf.String() if actualOutput != expectedOutput { t.Errorf("Unexpected output %q, want: %q", actualOutput, expectedOutput) @@ -239,7 +240,8 @@ buf := &bytes.Buffer{} w := zerolog.ConsoleWriter{Out: buf, NoColor: true} - d := time.Unix(0, 0).UTC().Format(time.RFC3339) + ts := time.Unix(0, 0) + d := ts.UTC().Format(time.RFC3339) evt := `{"time": "` + d + `", "level": "error", "message": "Foobar", "aaa": "bbb", "error": "Error"}` // t.Log(evt) @@ -248,7 +250,7 @@ t.Errorf("Unexpected error when writing output: %s", err) } - expectedOutput := "12:00AM ERR Foobar error=Error aaa=bbb\n" + expectedOutput := ts.Format(time.Kitchen) + " ERR Foobar error=Error aaa=bbb\n" actualOutput := buf.String() if actualOutput != expectedOutput { t.Errorf("Unexpected output %q, want: %q", actualOutput, expectedOutput) @@ -264,7 +266,8 @@ t.Fatalf("Cannot get working directory: %s", err) } - d := time.Unix(0, 0).UTC().Format(time.RFC3339) + ts := time.Unix(0, 0) + d := ts.UTC().Format(time.RFC3339) evt := `{"time": "` + d + `", "level": "debug", "message": "Foobar", "foo": "bar", "caller": "` + cwd + `/foo/bar.go"}` // t.Log(evt) @@ -273,7 +276,7 @@ t.Errorf("Unexpected error when writing output: %s", err) } - expectedOutput := "12:00AM DBG foo/bar.go > Foobar foo=bar\n" + expectedOutput := ts.Format(time.Kitchen) + " DBG foo/bar.go > Foobar foo=bar\n" actualOutput := buf.String() if actualOutput != expectedOutput { t.Errorf("Unexpected output %q, want: %q", actualOutput, expectedOutput) @@ -305,7 +308,8 @@ buf := &bytes.Buffer{} w := zerolog.ConsoleWriter{Out: buf, NoColor: true, TimeFormat: time.RFC3339} - d := time.Unix(0, 0).UTC().Format(time.RFC3339) + ts := time.Unix(0, 0) + d := ts.UTC().Format(time.RFC3339) evt := `{"time": "` + d + `", "level": "info", "message": "Foobar"}` _, err := w.Write([]byte(evt)) @@ -313,7 +317,7 @@ t.Errorf("Unexpected error when writing output: %s", err) } - expectedOutput := "1970-01-01T00:00:00Z INF Foobar\n" + expectedOutput := ts.Format(time.RFC3339) + " INF Foobar\n" actualOutput := buf.String() if actualOutput != expectedOutput { t.Errorf("Unexpected output %q, want: %q", actualOutput, expectedOutput) @@ -352,6 +356,72 @@ actualOutput := buf.String() if actualOutput != expectedOutput { t.Errorf("Unexpected output %q, want: %q", actualOutput, expectedOutput) + } + }) + + t.Run("Sets FieldsExclude", func(t *testing.T) { + buf := &bytes.Buffer{} + w := zerolog.ConsoleWriter{Out: buf, NoColor: true, FieldsExclude: []string{"foo"}} + + evt := `{"level": "info", "message": "Foobar", "foo":"bar", "baz":"quux"}` + _, err := w.Write([]byte(evt)) + if err != nil { + t.Errorf("Unexpected error when writing output: %s", err) + } + + expectedOutput := " INF Foobar baz=quux\n" + actualOutput := buf.String() + if actualOutput != expectedOutput { + t.Errorf("Unexpected output %q, want: %q", actualOutput, expectedOutput) + } + }) + + t.Run("Sets FormatExtra", func(t *testing.T) { + buf := &bytes.Buffer{} + w := zerolog.ConsoleWriter{ + Out: buf, NoColor: true, PartsOrder: []string{"level", "message"}, + FormatExtra: func(evt map[string]interface{}, buf *bytes.Buffer) error { + buf.WriteString("\nAdditional stacktrace") + return nil + }, + } + + evt := `{"level": "info", "message": "Foobar"}` + _, err := w.Write([]byte(evt)) + if err != nil { + t.Errorf("Unexpected error when writing output: %s", err) + } + + expectedOutput := "INF Foobar\nAdditional stacktrace\n" + actualOutput := buf.String() + if actualOutput != expectedOutput { + t.Errorf("Unexpected output %q, want: %q", actualOutput, expectedOutput) + } + }) + + t.Run("Uses local time for console writer without time zone", func(t *testing.T) { + // Regression test for issue #483 (check there for more details) + + timeFormat := "2006-01-02 15:04:05" + expectedOutput := "2022-10-20 20:24:50 INF Foobar\n" + evt := `{"time": "2022-10-20 20:24:50", "level": "info", "message": "Foobar"}` + + of := zerolog.TimeFieldFormat + defer func() { + zerolog.TimeFieldFormat = of + }() + zerolog.TimeFieldFormat = timeFormat + + buf := &bytes.Buffer{} + w := zerolog.ConsoleWriter{Out: buf, NoColor: true, TimeFormat: timeFormat} + _, err := w.Write([]byte(evt)) + if err != nil { + t.Errorf("Unexpected error when writing output: %s", err) + } + + actualOutput := buf.String() + if actualOutput != expectedOutput { + t.Errorf("Unexpected output %q, want: %q", actualOutput, expectedOutput) } }) } diff -Nru golang-github-rs-zerolog-1.26.1/ctx.go golang-github-rs-zerolog-1.29.1/ctx.go --- golang-github-rs-zerolog-1.26.1/ctx.go 2021-12-15 23:37:18.000000000 +0000 +++ golang-github-rs-zerolog-1.29.1/ctx.go 2023-03-20 19:29:36.000000000 +0000 @@ -14,10 +14,15 @@ type ctxKey struct{} -// WithContext returns a copy of ctx with l associated. If an instance of Logger -// is already in the context, the context is not updated. +// WithContext returns a copy of ctx with the receiver attached. The Logger +// attached to the provided Context (if any) will not be effected. If the +// receiver's log level is Disabled it will only be attached to the returned +// Context if the provided Context has a previously attached Logger. If the +// provided Context has no attached Logger, a Disabled Logger will not be +// attached. // -// For instance, to add a field to an existing logger in the context, use this +// Note: to modify the existing Logger attached to a Context (instead of +// replacing it in a new Context), use UpdateContext with the following // notation: // // ctx := r.Context() @@ -25,17 +30,13 @@ // l.UpdateContext(func(c Context) Context { // return c.Str("bar", "baz") // }) -func (l *Logger) WithContext(ctx context.Context) context.Context { - if lp, ok := ctx.Value(ctxKey{}).(*Logger); ok { - if lp == l { - // Do not store same logger. - return ctx - } - } else if l.level == Disabled { +// +func (l Logger) WithContext(ctx context.Context) context.Context { + if _, ok := ctx.Value(ctxKey{}).(*Logger); !ok && l.level == Disabled { // Do not store disabled logger. return ctx } - return context.WithValue(ctx, ctxKey{}, l) + return context.WithValue(ctx, ctxKey{}, &l) } // Ctx returns the Logger associated with the ctx. If no logger diff -Nru golang-github-rs-zerolog-1.26.1/ctx_test.go golang-github-rs-zerolog-1.29.1/ctx_test.go --- golang-github-rs-zerolog-1.26.1/ctx_test.go 2021-12-15 23:37:18.000000000 +0000 +++ golang-github-rs-zerolog-1.29.1/ctx_test.go 2023-03-20 19:29:36.000000000 +0000 @@ -45,7 +45,7 @@ l := New(ioutil.Discard).With().Str("foo", "bar").Logger() ctx = l.WithContext(ctx) - if Ctx(ctx) != &l { + if !reflect.DeepEqual(Ctx(ctx), &l) { t.Error("WithContext did not store logger") } @@ -53,18 +53,18 @@ return c.Str("bar", "baz") }) ctx = l.WithContext(ctx) - if Ctx(ctx) != &l { + if !reflect.DeepEqual(Ctx(ctx), &l) { t.Error("WithContext did not store updated logger") } l = l.Level(DebugLevel) ctx = l.WithContext(ctx) - if Ctx(ctx) != &l { + if !reflect.DeepEqual(Ctx(ctx), &l) { t.Error("WithContext did not store copied logger") } ctx = dl.WithContext(ctx) - if Ctx(ctx) != &dl { - t.Error("WithContext did not overide logger with a disabled logger") + if !reflect.DeepEqual(Ctx(ctx), &dl) { + t.Error("WithContext did not override logger with a disabled logger") } } diff -Nru golang-github-rs-zerolog-1.26.1/debian/changelog golang-github-rs-zerolog-1.29.1/debian/changelog --- golang-github-rs-zerolog-1.26.1/debian/changelog 2022-11-21 06:45:10.000000000 +0000 +++ golang-github-rs-zerolog-1.29.1/debian/changelog 2023-06-25 07:17:44.000000000 +0000 @@ -1,3 +1,12 @@ +golang-github-rs-zerolog (1.29.1-1) unstable; urgency=medium + + * Team Upload. + * New upstream version 1.29.1 + * Bump Standards-Version to 4.6.2 (no changes needed) + * Update B-D and depends + + -- Nilesh Patra Sun, 25 Jun 2023 12:47:44 +0530 + golang-github-rs-zerolog (1.26.1-2) unstable; urgency=medium * Team upload. diff -Nru golang-github-rs-zerolog-1.26.1/debian/control golang-github-rs-zerolog-1.29.1/debian/control --- golang-github-rs-zerolog-1.26.1/debian/control 2022-11-21 06:45:10.000000000 +0000 +++ golang-github-rs-zerolog-1.29.1/debian/control 2023-06-25 07:17:44.000000000 +0000 @@ -7,10 +7,11 @@ dh-sequence-golang, golang-any, golang-github-coreos-go-systemd-dev, + golang-github-mattn-go-colorable-dev, golang-github-pkg-errors-dev, golang-github-rs-xid-dev, golang-golang-x-tools-dev, -Standards-Version: 4.6.1 +Standards-Version: 4.6.2 Homepage: https://github.com/rs/zerolog Vcs-Browser: https://salsa.debian.org/go-team/packages/golang-github-rs-zerolog Vcs-Git: https://salsa.debian.org/go-team/packages/golang-github-rs-zerolog.git @@ -21,6 +22,7 @@ Package: golang-github-rs-zerolog-dev Architecture: all Depends: golang-github-coreos-go-systemd-dev, + golang-github-mattn-go-colorable-dev, golang-github-pkg-errors-dev, golang-github-rs-xid-dev, golang-golang-x-tools-dev, diff -Nru golang-github-rs-zerolog-1.26.1/diode/diode_test.go golang-github-rs-zerolog-1.29.1/diode/diode_test.go --- golang-github-rs-zerolog-1.26.1/diode/diode_test.go 2021-12-15 23:37:18.000000000 +0000 +++ golang-github-rs-zerolog-1.29.1/diode/diode_test.go 2023-03-20 19:29:36.000000000 +0000 @@ -30,6 +30,14 @@ } } +func TestClose(t *testing.T) { + buf := bytes.Buffer{} + w := diode.NewWriter(&buf, 1000, 0, func(missed int) {}) + log := zerolog.New(w) + log.Print("test") + w.Close() +} + func Benchmark(b *testing.B) { log.SetOutput(ioutil.Discard) defer log.SetOutput(os.Stderr) diff -Nru golang-github-rs-zerolog-1.26.1/diode/internal/diodes/many_to_one.go golang-github-rs-zerolog-1.29.1/diode/internal/diodes/many_to_one.go --- golang-github-rs-zerolog-1.26.1/diode/internal/diodes/many_to_one.go 2021-12-15 23:37:18.000000000 +0000 +++ golang-github-rs-zerolog-1.29.1/diode/internal/diodes/many_to_one.go 2023-03-20 19:29:36.000000000 +0000 @@ -16,7 +16,7 @@ } // NewManyToOne creates a new diode (ring buffer). The ManyToOne diode -// is optimzed for many writers (on go-routines B-n) and a single reader +// is optimized for many writers (on go-routines B-n) and a single reader // (on go-routine A). The alerter is invoked on the read's go-routine. It is // called when it notices that the writer go-routine has passed it and wrote // over data. A nil can be used to ignore alerts. @@ -66,7 +66,7 @@ } // TryNext will attempt to read from the next slot of the ring buffer. -// If there is not data available, it will return (nil, false). +// If there is no data available, it will return (nil, false). func (d *ManyToOne) TryNext() (data GenericDataType, ok bool) { // Read a value from the ring buffer based on the readIndex. idx := d.readIndex % uint64(len(d.buffer)) @@ -80,7 +80,7 @@ } // When the seq value is less than the current read index that means a - // value was read from idx that was previously written but has since has + // value was read from idx that was previously written but since has // been dropped. This value must be ignored and the read head must not // increment. // diff -Nru golang-github-rs-zerolog-1.26.1/diode/internal/diodes/one_to_one.go golang-github-rs-zerolog-1.29.1/diode/internal/diodes/one_to_one.go --- golang-github-rs-zerolog-1.26.1/diode/internal/diodes/one_to_one.go 2021-12-15 23:37:18.000000000 +0000 +++ golang-github-rs-zerolog-1.29.1/diode/internal/diodes/one_to_one.go 2023-03-20 19:29:36.000000000 +0000 @@ -80,7 +80,7 @@ } // When the seq value is less than the current read index that means a - // value was read from idx that was previously written but has since has + // value was read from idx that was previously written but since has // been dropped. This value must be ignored and the read head must not // increment. // diff -Nru golang-github-rs-zerolog-1.26.1/diode/internal/diodes/poller.go golang-github-rs-zerolog-1.29.1/diode/internal/diodes/poller.go --- golang-github-rs-zerolog-1.26.1/diode/internal/diodes/poller.go 2021-12-15 23:37:18.000000000 +0000 +++ golang-github-rs-zerolog-1.29.1/diode/internal/diodes/poller.go 2023-03-20 19:29:36.000000000 +0000 @@ -24,18 +24,18 @@ // WithPollingInterval sets the interval at which the diode is queried // for new data. The default is 10ms. func WithPollingInterval(interval time.Duration) PollerConfigOption { - return PollerConfigOption(func(c *Poller) { + return func(c *Poller) { c.interval = interval - }) + } } // WithPollingContext sets the context to cancel any retrieval (Next()). It // will not change any results for adding data (Set()). Default is // context.Background(). func WithPollingContext(ctx context.Context) PollerConfigOption { - return PollerConfigOption(func(c *Poller) { + return func(c *Poller) { c.ctx = ctx - }) + } } // NewPoller returns a new Poller that wraps the given diode. diff -Nru golang-github-rs-zerolog-1.26.1/diode/internal/diodes/waiter.go golang-github-rs-zerolog-1.29.1/diode/internal/diodes/waiter.go --- golang-github-rs-zerolog-1.26.1/diode/internal/diodes/waiter.go 2021-12-15 23:37:18.000000000 +0000 +++ golang-github-rs-zerolog-1.29.1/diode/internal/diodes/waiter.go 2023-03-20 19:29:36.000000000 +0000 @@ -21,9 +21,9 @@ // will not change any results for adding data (Set()). Default is // context.Background(). func WithWaiterContext(ctx context.Context) WaiterConfigOption { - return WaiterConfigOption(func(c *Waiter) { + return func(c *Waiter) { c.ctx = ctx - }) + } } // NewWaiter returns a new Waiter that wraps the given diode. @@ -39,7 +39,12 @@ go func() { <-w.ctx.Done() + + // Mutex is strictly necessary here to avoid a race in Next() (between + // w.isDone() and w.c.Wait()) and w.c.Broadcast() here. + w.mu.Lock() w.c.Broadcast() + w.mu.Unlock() }() return w diff -Nru golang-github-rs-zerolog-1.26.1/event.go golang-github-rs-zerolog-1.29.1/event.go --- golang-github-rs-zerolog-1.26.1/event.go 2021-12-15 23:37:18.000000000 +0000 +++ golang-github-rs-zerolog-1.29.1/event.go 2023-03-20 19:29:36.000000000 +0000 @@ -129,6 +129,13 @@ e.msg(fmt.Sprintf(format, v...)) } +func (e *Event) MsgFunc(createMsg func() string) { + if e == nil { + return + } + e.msg(createMsg()) +} + func (e *Event) msg(msg string) { for _, hook := range e.ch { hook.Run(e, e.level, msg) @@ -645,7 +652,7 @@ return e } -// Time adds the field key with t formated as string using zerolog.TimeFieldFormat. +// Time adds the field key with t formatted as string using zerolog.TimeFieldFormat. func (e *Event) Time(key string, t time.Time) *Event { if e == nil { return e @@ -654,7 +661,7 @@ return e } -// Times adds the field key with t formated as string using zerolog.TimeFieldFormat. +// Times adds the field key with t formatted as string using zerolog.TimeFieldFormat. func (e *Event) Times(key string, t []time.Time) *Event { if e == nil { return e @@ -700,6 +707,11 @@ return e } +// Any is a wrapper around Event.Interface. +func (e *Event) Any(key string, i interface{}) *Event { + return e.Interface(key, i) +} + // Interface adds the field key with i marshaled using reflection. func (e *Event) Interface(key string, i interface{}) *Event { if e == nil { @@ -712,6 +724,15 @@ return e } +// Type adds the field key with val's type using reflection. +func (e *Event) Type(key string, val interface{}) *Event { + if e == nil { + return e + } + e.buf = enc.AppendType(enc.AppendKey(e.buf, key), val) + return e +} + // CallerSkipFrame instructs any future Caller calls to skip the specified number of frames. // This includes those added via hooks from the context. func (e *Event) CallerSkipFrame(skip int) *Event { @@ -737,11 +758,11 @@ if e == nil { return e } - _, file, line, ok := runtime.Caller(skip + e.skipFrame) + pc, file, line, ok := runtime.Caller(skip + e.skipFrame) if !ok { return e } - e.buf = enc.AppendString(enc.AppendKey(e.buf, CallerFieldName), CallerMarshalFunc(file, line)) + e.buf = enc.AppendString(enc.AppendKey(e.buf, CallerFieldName), CallerMarshalFunc(pc, file, line)) return e } diff -Nru golang-github-rs-zerolog-1.26.1/.github/dependabot.yml golang-github-rs-zerolog-1.29.1/.github/dependabot.yml --- golang-github-rs-zerolog-1.26.1/.github/dependabot.yml 2021-12-15 23:37:18.000000000 +0000 +++ golang-github-rs-zerolog-1.29.1/.github/dependabot.yml 1970-01-01 00:00:00.000000000 +0000 @@ -1,10 +0,0 @@ -version: 2 -updates: - - package-ecosystem: github-actions - directory: / - schedule: - interval: weekly - - package-ecosystem: gomod - directory: / - schedule: - interval: weekly diff -Nru golang-github-rs-zerolog-1.26.1/.github/workflows/test.yml golang-github-rs-zerolog-1.29.1/.github/workflows/test.yml --- golang-github-rs-zerolog-1.26.1/.github/workflows/test.yml 2021-12-15 23:37:18.000000000 +0000 +++ golang-github-rs-zerolog-1.29.1/.github/workflows/test.yml 1970-01-01 00:00:00.000000000 +0000 @@ -1,27 +0,0 @@ -on: [push, pull_request] -name: Test -jobs: - test: - strategy: - matrix: - go-version: [1.15.x, 1.16.x] - os: [ubuntu-latest, macos-latest] - runs-on: ${{ matrix.os }} - steps: - - name: Install Go - uses: actions/setup-go@v2 - with: - go-version: ${{ matrix.go-version }} - - name: Checkout code - uses: actions/checkout@v2 - - uses: actions/cache@v2 - with: - path: ~/go/pkg/mod - key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} - restore-keys: | - ${{ runner.os }}-go- - - name: Test - run: go test -race -bench . -benchmem ./... - - name: Test CBOR - run: go test -tags binary_log ./... - diff -Nru golang-github-rs-zerolog-1.26.1/globals.go golang-github-rs-zerolog-1.29.1/globals.go --- golang-github-rs-zerolog-1.26.1/globals.go 2021-12-15 23:37:18.000000000 +0000 +++ golang-github-rs-zerolog-1.29.1/globals.go 2023-03-20 19:29:36.000000000 +0000 @@ -19,6 +19,10 @@ // TimeFormatUnixMicro defines a time format that makes time fields to be // serialized as Unix timestamp integers in microseconds. TimeFormatUnixMicro = "UNIXMICRO" + + // TimeFormatUnixNano defines a time format that makes time fields to be + // serialized as Unix timestamp integers in nanoseconds. + TimeFormatUnixNano = "UNIXNANO" ) var ( @@ -61,7 +65,7 @@ CallerSkipFrameCount = 2 // CallerMarshalFunc allows customization of global caller marshaling - CallerMarshalFunc = func(file string, line int) string { + CallerMarshalFunc = func(pc uintptr, file string, line int) string { return file + ":" + strconv.Itoa(line) } @@ -81,7 +85,7 @@ InterfaceMarshalFunc = json.Marshal // TimeFieldFormat defines the time format of the Time field type. If set to - // TimeFormatUnix, TimeFormatUnixMs or TimeFormatUnixMicro, the time is formatted as an UNIX + // TimeFormatUnix, TimeFormatUnixMs, TimeFormatUnixMicro or TimeFormatUnixNano, the time is formatted as a UNIX // timestamp as integer. TimeFieldFormat = time.RFC3339 diff -Nru golang-github-rs-zerolog-1.26.1/go.mod golang-github-rs-zerolog-1.29.1/go.mod --- golang-github-rs-zerolog-1.26.1/go.mod 2021-12-15 23:37:18.000000000 +0000 +++ golang-github-rs-zerolog-1.29.1/go.mod 2023-03-20 19:29:36.000000000 +0000 @@ -3,9 +3,8 @@ go 1.15 require ( - github.com/coreos/go-systemd/v22 v22.3.2 + github.com/coreos/go-systemd/v22 v22.5.0 + github.com/mattn/go-colorable v0.1.12 github.com/pkg/errors v0.9.1 - github.com/rs/xid v1.3.0 - golang.org/x/crypto v0.0.0-20211215165025-cf75a172585e // indirect - golang.org/x/tools v0.1.7 + github.com/rs/xid v1.4.0 ) diff -Nru golang-github-rs-zerolog-1.26.1/go.sum golang-github-rs-zerolog-1.29.1/go.sum --- golang-github-rs-zerolog-1.26.1/go.sum 2021-12-15 23:37:18.000000000 +0000 +++ golang-github-rs-zerolog-1.29.1/go.sum 2023-03-20 19:29:36.000000000 +0000 @@ -1,37 +1,14 @@ -github.com/coreos/go-systemd/v22 v22.3.2 h1:D9/bQk5vlXQFZ6Kwuu6zaiXJ9oTPe68++AzAJc1DzSI= -github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= +github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40= +github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= +github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/rs/xid v1.3.0 h1:6NjYksEUlhurdVehpc7S7dk6DAmcKv8V9gG0FsVN2U4= -github.com/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= -github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20211215165025-cf75a172585e/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= -golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo= -golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e h1:WUoyKPm6nCo1BnNUvPGnFG3T5DUVem42yDJZZ4CNxMA= -golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.1.7 h1:6j8CgantCy3yc8JGBqkDLMKWqZ0RDU2g1HVgacojGWQ= -golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +github.com/rs/xid v1.4.0 h1:qd7wPTDkN6KQx2VmMBLrpHkiyQwgFXRnkOLacUiaSNY= +github.com/rs/xid v1.4.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6 h1:foEbQz/B0Oz6YIqu/69kfXPYeFQAuuMYFkjaqXzl5Wo= +golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff -Nru golang-github-rs-zerolog-1.26.1/hlog/hlog_example_test.go golang-github-rs-zerolog-1.29.1/hlog/hlog_example_test.go --- golang-github-rs-zerolog-1.26.1/hlog/hlog_example_test.go 2021-12-15 23:37:18.000000000 +0000 +++ golang-github-rs-zerolog-1.29.1/hlog/hlog_example_test.go 2023-03-20 19:29:36.000000000 +0000 @@ -48,8 +48,8 @@ // Install the logger handler with default output on the console c = c.Append(hlog.NewHandler(log)) - // Install some provided extra handler to set some request's context fields. - // Thanks to those handler, all our logs will come with some pre-populated fields. + // Install some provided extra handlers to set some request's context fields. + // Thanks to those handlers, all our logs will come with some pre-populated fields. c = c.Append(hlog.RemoteAddrHandler("ip")) c = c.Append(hlog.UserAgentHandler("user_agent")) c = c.Append(hlog.RefererHandler("referer")) @@ -63,11 +63,11 @@ hlog.FromRequest(r).Info(). Str("user", "current user"). Str("status", "ok"). - Msg("Something happend") + Msg("Something happened") })) http.Handle("/", h) h.ServeHTTP(httptest.NewRecorder(), &http.Request{}) - // Output: {"level":"info","role":"my-service","host":"local-hostname","user":"current user","status":"ok","time":"2001-02-03T04:05:06Z","message":"Something happend"} + // Output: {"level":"info","role":"my-service","host":"local-hostname","user":"current user","status":"ok","time":"2001-02-03T04:05:06Z","message":"Something happened"} } diff -Nru golang-github-rs-zerolog-1.26.1/hlog/hlog.go golang-github-rs-zerolog-1.29.1/hlog/hlog.go --- golang-github-rs-zerolog-1.26.1/hlog/hlog.go 2021-12-15 23:37:18.000000000 +0000 +++ golang-github-rs-zerolog-1.29.1/hlog/hlog.go 2023-03-20 19:29:36.000000000 +0000 @@ -121,6 +121,20 @@ } } +// ProtoHandler adds the requests protocol version as a field to the context logger +// using fieldKey as field Key. +func ProtoHandler(fieldKey string) func(next http.Handler) http.Handler { + return func(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + log := zerolog.Ctx(r.Context()) + log.UpdateContext(func(c zerolog.Context) zerolog.Context { + return c.Str(fieldKey, r.Proto) + }) + next.ServeHTTP(w, r) + }) + } +} + type idKey struct{} // IDFromRequest returns the unique id associated to the request if any. diff -Nru golang-github-rs-zerolog-1.26.1/hlog/hlog_test.go golang-github-rs-zerolog-1.29.1/hlog/hlog_test.go --- golang-github-rs-zerolog-1.26.1/hlog/hlog_test.go 2021-12-15 23:37:18.000000000 +0000 +++ golang-github-rs-zerolog-1.29.1/hlog/hlog_test.go 2023-03-20 19:29:36.000000000 +0000 @@ -1,3 +1,4 @@ +//go:build go1.7 // +build go1.7 package hlog @@ -199,6 +200,22 @@ t.Errorf("Invalid log output, got: %s, want: %s", got, want) } } + +func TestProtoHandler(t *testing.T) { + out := &bytes.Buffer{} + r := &http.Request{ + Proto: "test", + } + h := ProtoHandler("proto")(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + l := FromRequest(r) + l.Log().Msg("") + })) + h = NewHandler(zerolog.New(out))(h) + h.ServeHTTP(nil, r) + if want, got := `{"proto":"test"}`+"\n", decodeIfBinary(out); want != got { + t.Errorf("Invalid log output, got: %s, want: %s", got, want) + } +} func TestCombinedHandlers(t *testing.T) { out := &bytes.Buffer{} diff -Nru golang-github-rs-zerolog-1.26.1/internal/cbor/cbor.go golang-github-rs-zerolog-1.29.1/internal/cbor/cbor.go --- golang-github-rs-zerolog-1.26.1/internal/cbor/cbor.go 2021-12-15 23:37:18.000000000 +0000 +++ golang-github-rs-zerolog-1.29.1/internal/cbor/cbor.go 2023-03-20 19:29:36.000000000 +0000 @@ -67,7 +67,7 @@ var IntegerTimeFieldFormat = time.RFC3339 // NanoTimeFieldFormat indicates the format of timestamp decoded -// from a float value (time in seconds and nano seconds). +// from a float value (time in seconds and nanoseconds). var NanoTimeFieldFormat = time.RFC3339Nano func appendCborTypePrefix(dst []byte, major byte, number uint64) []byte { @@ -91,7 +91,8 @@ minor = additionalTypeIntUint64 } - dst = append(dst, byte(major|minor)) + + dst = append(dst, major|minor) byteCount-- for ; byteCount >= 0; byteCount-- { dst = append(dst, byte(number>>(uint(byteCount)*8))) diff -Nru golang-github-rs-zerolog-1.26.1/internal/cbor/decode_stream.go golang-github-rs-zerolog-1.29.1/internal/cbor/decode_stream.go --- golang-github-rs-zerolog-1.26.1/internal/cbor/decode_stream.go 2021-12-15 23:37:18.000000000 +0000 +++ golang-github-rs-zerolog-1.29.1/internal/cbor/decode_stream.go 2023-03-20 19:29:36.000000000 +0000 @@ -43,7 +43,7 @@ return b } -func decodeIntAdditonalType(src *bufio.Reader, minor byte) int64 { +func decodeIntAdditionalType(src *bufio.Reader, minor byte) int64 { val := int64(0) if minor <= 23 { val = int64(minor) @@ -77,7 +77,7 @@ if major != majorTypeUnsignedInt && major != majorTypeNegativeInt { panic(fmt.Errorf("Major type is: %d in decodeInteger!! (expected 0 or 1)", major)) } - val := decodeIntAdditonalType(src, minor) + val := decodeIntAdditionalType(src, minor) if major == 0 { return val } @@ -204,7 +204,7 @@ if !noQuotes { result = append(result, '"') } - length := decodeIntAdditonalType(src, minor) + length := decodeIntAdditionalType(src, minor) len := int(length) pbs := readNBytes(src, len) result = append(result, pbs...) @@ -222,7 +222,7 @@ panic(fmt.Errorf("Major type is: %d in decodeUTF8String", major)) } result := []byte{'"'} - length := decodeIntAdditonalType(src, minor) + length := decodeIntAdditionalType(src, minor) len := int(length) pbs := readNBytes(src, len) @@ -238,7 +238,7 @@ return append(dst, '"') } } - // The string has no need for encoding an therefore is directly + // The string has no need for encoding and therefore is directly // appended to the byte slice. result = append(result, pbs...) return append(result, '"') @@ -257,7 +257,7 @@ if minor == additionalTypeInfiniteCount { unSpecifiedCount = true } else { - length := decodeIntAdditonalType(src, minor) + length := decodeIntAdditionalType(src, minor) len = int(length) } for i := 0; unSpecifiedCount || i < len; i++ { @@ -266,7 +266,7 @@ if e != nil { panic(e) } - if pb[0] == byte(majorTypeSimpleAndFloat|additionalTypeBreak) { + if pb[0] == majorTypeSimpleAndFloat|additionalTypeBreak { readByte(src) break } @@ -277,7 +277,7 @@ if e != nil { panic(e) } - if pb[0] == byte(majorTypeSimpleAndFloat|additionalTypeBreak) { + if pb[0] == majorTypeSimpleAndFloat|additionalTypeBreak { readByte(src) break } @@ -301,7 +301,7 @@ if minor == additionalTypeInfiniteCount { unSpecifiedCount = true } else { - length := decodeIntAdditonalType(src, minor) + length := decodeIntAdditionalType(src, minor) len = int(length) } dst.Write([]byte{'{'}) @@ -311,7 +311,7 @@ if e != nil { panic(e) } - if pb[0] == byte(majorTypeSimpleAndFloat|additionalTypeBreak) { + if pb[0] == majorTypeSimpleAndFloat|additionalTypeBreak { readByte(src) break } @@ -326,7 +326,7 @@ if e != nil { panic(e) } - if pb[0] == byte(majorTypeSimpleAndFloat|additionalTypeBreak) { + if pb[0] == majorTypeSimpleAndFloat|additionalTypeBreak { readByte(src) break } @@ -352,7 +352,7 @@ // Tag value is larger than 256 (so uint16). case additionalTypeIntUint16: - val := decodeIntAdditonalType(src, minor) + val := decodeIntAdditionalType(src, minor) switch uint16(val) { case additionalTypeEmbeddedJSON: @@ -383,7 +383,7 @@ case additionalTypeTagNetworkPrefix: pb := readByte(src) - if pb != byte(majorTypeMap|0x1) { + if pb != majorTypeMap|0x1 { panic(fmt.Errorf("IP Prefix is NOT of MAP of 1 elements as expected")) } octets := decodeString(src, true) diff -Nru golang-github-rs-zerolog-1.26.1/internal/cbor/string.go golang-github-rs-zerolog-1.29.1/internal/cbor/string.go --- golang-github-rs-zerolog-1.26.1/internal/cbor/string.go 2021-12-15 23:37:18.000000000 +0000 +++ golang-github-rs-zerolog-1.29.1/internal/cbor/string.go 2023-03-20 19:29:36.000000000 +0000 @@ -8,7 +8,7 @@ l := len(vals) if l <= additionalMax { lb := byte(l) - dst = append(dst, byte(major|lb)) + dst = append(dst, major|lb) } else { dst = appendCborTypePrefix(dst, major, uint64(l)) } @@ -25,7 +25,7 @@ l := len(s) if l <= additionalMax { lb := byte(l) - dst = append(dst, byte(major|lb)) + dst = append(dst, major|lb) } else { dst = appendCborTypePrefix(dst, majorTypeUtf8String, uint64(l)) } @@ -64,7 +64,7 @@ l := len(s) if l <= additionalMax { lb := byte(l) - dst = append(dst, byte(major|lb)) + dst = append(dst, major|lb) } else { dst = appendCborTypePrefix(dst, major, uint64(l)) } @@ -77,7 +77,7 @@ minor := additionalTypeEmbeddedJSON // Append the TAG to indicate this is Embedded JSON. - dst = append(dst, byte(major|additionalTypeIntUint16)) + dst = append(dst, major|additionalTypeIntUint16) dst = append(dst, byte(minor>>8)) dst = append(dst, byte(minor&0xff)) @@ -87,7 +87,7 @@ l := len(s) if l <= additionalMax { lb := byte(l) - dst = append(dst, byte(major|lb)) + dst = append(dst, major|lb) } else { dst = appendCborTypePrefix(dst, major, uint64(l)) } diff -Nru golang-github-rs-zerolog-1.26.1/internal/cbor/time.go golang-github-rs-zerolog-1.29.1/internal/cbor/time.go --- golang-github-rs-zerolog-1.26.1/internal/cbor/time.go 2021-12-15 23:37:18.000000000 +0000 +++ golang-github-rs-zerolog-1.29.1/internal/cbor/time.go 2023-03-20 19:29:36.000000000 +0000 @@ -7,7 +7,7 @@ func appendIntegerTimestamp(dst []byte, t time.Time) []byte { major := majorTypeTags minor := additionalTypeTimestamp - dst = append(dst, byte(major|minor)) + dst = append(dst, major|minor) secs := t.Unix() var val uint64 if secs < 0 { @@ -17,18 +17,18 @@ major = majorTypeUnsignedInt val = uint64(secs) } - dst = appendCborTypePrefix(dst, major, uint64(val)) + dst = appendCborTypePrefix(dst, major, val) return dst } func (e Encoder) appendFloatTimestamp(dst []byte, t time.Time) []byte { major := majorTypeTags minor := additionalTypeTimestamp - dst = append(dst, byte(major|minor)) + dst = append(dst, major|minor) secs := t.Unix() nanos := t.Nanosecond() var val float64 - val = float64(secs)*1.0 + float64(nanos)*1E-9 + val = float64(secs)*1.0 + float64(nanos)*1e-9 return e.AppendFloat64(dst, val) } @@ -50,7 +50,7 @@ } if l <= additionalMax { lb := byte(l) - dst = append(dst, byte(major|lb)) + dst = append(dst, major|lb) } else { dst = appendCborTypePrefix(dst, major, uint64(l)) } @@ -82,7 +82,7 @@ } if l <= additionalMax { lb := byte(l) - dst = append(dst, byte(major|lb)) + dst = append(dst, major|lb) } else { dst = appendCborTypePrefix(dst, major, uint64(l)) } diff -Nru golang-github-rs-zerolog-1.26.1/internal/cbor/types.go golang-github-rs-zerolog-1.29.1/internal/cbor/types.go --- golang-github-rs-zerolog-1.26.1/internal/cbor/types.go 2021-12-15 23:37:18.000000000 +0000 +++ golang-github-rs-zerolog-1.29.1/internal/cbor/types.go 2023-03-20 19:29:36.000000000 +0000 @@ -4,21 +4,22 @@ "fmt" "math" "net" + "reflect" ) // AppendNil inserts a 'Nil' object into the dst byte array. func (Encoder) AppendNil(dst []byte) []byte { - return append(dst, byte(majorTypeSimpleAndFloat|additionalTypeNull)) + return append(dst, majorTypeSimpleAndFloat|additionalTypeNull) } // AppendBeginMarker inserts a map start into the dst byte array. func (Encoder) AppendBeginMarker(dst []byte) []byte { - return append(dst, byte(majorTypeMap|additionalTypeInfiniteCount)) + return append(dst, majorTypeMap|additionalTypeInfiniteCount) } // AppendEndMarker inserts a map end into the dst byte array. func (Encoder) AppendEndMarker(dst []byte) []byte { - return append(dst, byte(majorTypeSimpleAndFloat|additionalTypeBreak)) + return append(dst, majorTypeSimpleAndFloat|additionalTypeBreak) } // AppendObjectData takes an object in form of a byte array and appends to dst. @@ -30,12 +31,12 @@ // AppendArrayStart adds markers to indicate the start of an array. func (Encoder) AppendArrayStart(dst []byte) []byte { - return append(dst, byte(majorTypeArray|additionalTypeInfiniteCount)) + return append(dst, majorTypeArray|additionalTypeInfiniteCount) } // AppendArrayEnd adds markers to indicate the end of an array. func (Encoder) AppendArrayEnd(dst []byte) []byte { - return append(dst, byte(majorTypeSimpleAndFloat|additionalTypeBreak)) + return append(dst, majorTypeSimpleAndFloat|additionalTypeBreak) } // AppendArrayDelim adds markers to indicate end of a particular array element. @@ -56,7 +57,7 @@ if val { b = additionalTypeBoolTrue } - return append(dst, byte(majorTypeSimpleAndFloat|b)) + return append(dst, majorTypeSimpleAndFloat|b) } // AppendBools encodes and inserts an array of boolean values into the dst byte array. @@ -68,7 +69,7 @@ } if l <= additionalMax { lb := byte(l) - dst = append(dst, byte(major|lb)) + dst = append(dst, major|lb) } else { dst = appendCborTypePrefix(dst, major, uint64(l)) } @@ -88,7 +89,7 @@ } if contentVal <= additionalMax { lb := byte(contentVal) - dst = append(dst, byte(major|lb)) + dst = append(dst, major|lb) } else { dst = appendCborTypePrefix(dst, major, uint64(contentVal)) } @@ -104,7 +105,7 @@ } if l <= additionalMax { lb := byte(l) - dst = append(dst, byte(major|lb)) + dst = append(dst, major|lb) } else { dst = appendCborTypePrefix(dst, major, uint64(l)) } @@ -128,7 +129,7 @@ } if l <= additionalMax { lb := byte(l) - dst = append(dst, byte(major|lb)) + dst = append(dst, major|lb) } else { dst = appendCborTypePrefix(dst, major, uint64(l)) } @@ -152,7 +153,7 @@ } if l <= additionalMax { lb := byte(l) - dst = append(dst, byte(major|lb)) + dst = append(dst, major|lb) } else { dst = appendCborTypePrefix(dst, major, uint64(l)) } @@ -176,7 +177,7 @@ } if l <= additionalMax { lb := byte(l) - dst = append(dst, byte(major|lb)) + dst = append(dst, major|lb) } else { dst = appendCborTypePrefix(dst, major, uint64(l)) } @@ -196,7 +197,7 @@ } if contentVal <= additionalMax { lb := byte(contentVal) - dst = append(dst, byte(major|lb)) + dst = append(dst, major|lb) } else { dst = appendCborTypePrefix(dst, major, uint64(contentVal)) } @@ -212,7 +213,7 @@ } if l <= additionalMax { lb := byte(l) - dst = append(dst, byte(major|lb)) + dst = append(dst, major|lb) } else { dst = appendCborTypePrefix(dst, major, uint64(l)) } @@ -236,7 +237,7 @@ } if l <= additionalMax { lb := byte(l) - dst = append(dst, byte(major|lb)) + dst = append(dst, major|lb) } else { dst = appendCborTypePrefix(dst, major, uint64(l)) } @@ -260,7 +261,7 @@ } if l <= additionalMax { lb := byte(l) - dst = append(dst, byte(major|lb)) + dst = append(dst, major|lb) } else { dst = appendCborTypePrefix(dst, major, uint64(l)) } @@ -284,7 +285,7 @@ } if l <= additionalMax { lb := byte(l) - dst = append(dst, byte(major|lb)) + dst = append(dst, major|lb) } else { dst = appendCborTypePrefix(dst, major, uint64(l)) } @@ -308,7 +309,7 @@ } if l <= additionalMax { lb := byte(l) - dst = append(dst, byte(major|lb)) + dst = append(dst, major|lb) } else { dst = appendCborTypePrefix(dst, major, uint64(l)) } @@ -324,9 +325,9 @@ contentVal := val if contentVal <= additionalMax { lb := byte(contentVal) - dst = append(dst, byte(major|lb)) + dst = append(dst, major|lb) } else { - dst = appendCborTypePrefix(dst, major, uint64(contentVal)) + dst = appendCborTypePrefix(dst, major, contentVal) } return dst } @@ -340,7 +341,7 @@ } if l <= additionalMax { lb := byte(l) - dst = append(dst, byte(major|lb)) + dst = append(dst, major|lb) } else { dst = appendCborTypePrefix(dst, major, uint64(l)) } @@ -367,7 +368,7 @@ for i := uint(0); i < 4; i++ { buf[i] = byte(n >> ((3 - i) * 8)) } - return append(append(dst, byte(major|subType)), buf[0], buf[1], buf[2], buf[3]) + return append(append(dst, major|subType), buf[0], buf[1], buf[2], buf[3]) } // AppendFloats32 encodes and inserts an array of single precision float value into the dst byte array. @@ -379,7 +380,7 @@ } if l <= additionalMax { lb := byte(l) - dst = append(dst, byte(major|lb)) + dst = append(dst, major|lb) } else { dst = appendCborTypePrefix(dst, major, uint64(l)) } @@ -402,7 +403,7 @@ major := majorTypeSimpleAndFloat subType := additionalTypeFloat64 n := math.Float64bits(val) - dst = append(dst, byte(major|subType)) + dst = append(dst, major|subType) for i := uint(1); i <= 8; i++ { b := byte(n >> ((8 - i) * 8)) dst = append(dst, b) @@ -419,7 +420,7 @@ } if l <= additionalMax { lb := byte(l) - dst = append(dst, byte(major|lb)) + dst = append(dst, major|lb) } else { dst = appendCborTypePrefix(dst, major, uint64(l)) } @@ -438,9 +439,17 @@ return AppendEmbeddedJSON(dst, marshaled) } +// AppendType appends the parameter type (as a string) to the input byte slice. +func (e Encoder) AppendType(dst []byte, i interface{}) []byte { + if i == nil { + return e.AppendString(dst, "") + } + return e.AppendString(dst, reflect.TypeOf(i).String()) +} + // AppendIPAddr encodes and inserts an IP Address (IPv4 or IPv6). func (e Encoder) AppendIPAddr(dst []byte, ip net.IP) []byte { - dst = append(dst, byte(majorTypeTags|additionalTypeIntUint16)) + dst = append(dst, majorTypeTags|additionalTypeIntUint16) dst = append(dst, byte(additionalTypeTagNetworkAddr>>8)) dst = append(dst, byte(additionalTypeTagNetworkAddr&0xff)) return e.AppendBytes(dst, ip) @@ -448,21 +457,21 @@ // AppendIPPrefix encodes and inserts an IP Address Prefix (Address + Mask Length). func (e Encoder) AppendIPPrefix(dst []byte, pfx net.IPNet) []byte { - dst = append(dst, byte(majorTypeTags|additionalTypeIntUint16)) + dst = append(dst, majorTypeTags|additionalTypeIntUint16) dst = append(dst, byte(additionalTypeTagNetworkPrefix>>8)) dst = append(dst, byte(additionalTypeTagNetworkPrefix&0xff)) // Prefix is a tuple (aka MAP of 1 pair of elements) - // first element is prefix, second is mask length. - dst = append(dst, byte(majorTypeMap|0x1)) + dst = append(dst, majorTypeMap|0x1) dst = e.AppendBytes(dst, pfx.IP) maskLen, _ := pfx.Mask.Size() return e.AppendUint8(dst, uint8(maskLen)) } -// AppendMACAddr encodes and inserts an Hardware (MAC) address. +// AppendMACAddr encodes and inserts a Hardware (MAC) address. func (e Encoder) AppendMACAddr(dst []byte, ha net.HardwareAddr) []byte { - dst = append(dst, byte(majorTypeTags|additionalTypeIntUint16)) + dst = append(dst, majorTypeTags|additionalTypeIntUint16) dst = append(dst, byte(additionalTypeTagNetworkAddr>>8)) dst = append(dst, byte(additionalTypeTagNetworkAddr&0xff)) return e.AppendBytes(dst, ha) @@ -470,7 +479,7 @@ // AppendHex adds a TAG and inserts a hex bytes as a string. func (e Encoder) AppendHex(dst []byte, val []byte) []byte { - dst = append(dst, byte(majorTypeTags|additionalTypeIntUint16)) + dst = append(dst, majorTypeTags|additionalTypeIntUint16) dst = append(dst, byte(additionalTypeTagHexString>>8)) dst = append(dst, byte(additionalTypeTagHexString&0xff)) return e.AppendBytes(dst, val) diff -Nru golang-github-rs-zerolog-1.26.1/internal/cbor/types_test.go golang-github-rs-zerolog-1.29.1/internal/cbor/types_test.go --- golang-github-rs-zerolog-1.26.1/internal/cbor/types_test.go 2021-12-15 23:37:18.000000000 +0000 +++ golang-github-rs-zerolog-1.29.1/internal/cbor/types_test.go 2023-03-20 19:29:36.000000000 +0000 @@ -115,7 +115,6 @@ {-0x10001, "\x3a\x00\x01\x00\x00"}, {-0x7FFFFFFE, "\x3a\x7f\xff\xff\xfd"}, {-1000000, "\x3a\x00\x0f\x42\x3f"}, - } func TestAppendInt(t *testing.T) { @@ -212,7 +211,7 @@ {net.HardwareAddr{0x20, 0x01, 0x0d, 0xb8, 0x85, 0xa3}, "\"20:01:0d:b8:85:a3\"", "\xd9\x01\x04\x46\x20\x01\x0d\xb8\x85\xa3"}, } -func TestAppendMacAddr(t *testing.T) { +func TestAppendMACAddr(t *testing.T) { for _, tc := range macAddrTestCases { s := enc.AppendMACAddr([]byte{}, tc.macaddr) got := string(s) diff -Nru golang-github-rs-zerolog-1.26.1/internal/json/string.go golang-github-rs-zerolog-1.29.1/internal/json/string.go --- golang-github-rs-zerolog-1.26.1/internal/json/string.go 2021-12-15 23:37:18.000000000 +0000 +++ golang-github-rs-zerolog-1.29.1/internal/json/string.go 2023-03-20 19:29:36.000000000 +0000 @@ -37,7 +37,7 @@ // // The operation loops though each byte in the string looking // for characters that need json or utf8 encoding. If the string -// does not need encoding, then the string is appended in it's +// does not need encoding, then the string is appended in its // entirety to the byte slice. // If we encounter a byte that does need encoding, switch up // the operation and perform a byte-by-byte read-encode-append. @@ -56,7 +56,7 @@ return append(dst, '"') } } - // The string has no need for encoding an therefore is directly + // The string has no need for encoding and therefore is directly // appended to the byte slice. dst = append(dst, s...) // End with a double quote @@ -99,7 +99,7 @@ r, size := utf8.DecodeRuneInString(s[i:]) if r == utf8.RuneError && size == 1 { // In case of error, first append previous simple characters to - // the byte slice if any and append a remplacement character code + // the byte slice if any and append a replacement character code // in place of the invalid sequence. if start < i { dst = append(dst, s[start:i]...) diff -Nru golang-github-rs-zerolog-1.26.1/internal/json/time.go golang-github-rs-zerolog-1.29.1/internal/json/time.go --- golang-github-rs-zerolog-1.26.1/internal/json/time.go 2021-12-15 23:37:18.000000000 +0000 +++ golang-github-rs-zerolog-1.29.1/internal/json/time.go 2023-03-20 19:29:36.000000000 +0000 @@ -7,9 +7,10 @@ const ( // Import from zerolog/global.go - timeFormatUnix = "" - timeFormatUnixMs = "UNIXMS" + timeFormatUnix = "" + timeFormatUnixMs = "UNIXMS" timeFormatUnixMicro = "UNIXMICRO" + timeFormatUnixNano = "UNIXNANO" ) // AppendTime formats the input time with the given format @@ -22,6 +23,8 @@ return e.AppendInt64(dst, t.UnixNano()/1000000) case timeFormatUnixMicro: return e.AppendInt64(dst, t.UnixNano()/1000) + case timeFormatUnixNano: + return e.AppendInt64(dst, t.UnixNano()) } return append(t.AppendFormat(append(dst, '"'), format), '"') } @@ -33,7 +36,11 @@ case timeFormatUnix: return appendUnixTimes(dst, vals) case timeFormatUnixMs: - return appendUnixMsTimes(dst, vals) + return appendUnixNanoTimes(dst, vals, 1000000) + case timeFormatUnixMicro: + return appendUnixNanoTimes(dst, vals, 1000) + case timeFormatUnixNano: + return appendUnixNanoTimes(dst, vals, 1) } if len(vals) == 0 { return append(dst, '[', ']') @@ -64,15 +71,15 @@ return dst } -func appendUnixMsTimes(dst []byte, vals []time.Time) []byte { +func appendUnixNanoTimes(dst []byte, vals []time.Time, div int64) []byte { if len(vals) == 0 { return append(dst, '[', ']') } dst = append(dst, '[') - dst = strconv.AppendInt(dst, vals[0].UnixNano()/1000000, 10) + dst = strconv.AppendInt(dst, vals[0].UnixNano()/div, 10) if len(vals) > 1 { for _, t := range vals[1:] { - dst = strconv.AppendInt(append(dst, ','), t.UnixNano()/1000000, 10) + dst = strconv.AppendInt(append(dst, ','), t.UnixNano()/div, 10) } } dst = append(dst, ']') diff -Nru golang-github-rs-zerolog-1.26.1/internal/json/types.go golang-github-rs-zerolog-1.29.1/internal/json/types.go --- golang-github-rs-zerolog-1.26.1/internal/json/types.go 2021-12-15 23:37:18.000000000 +0000 +++ golang-github-rs-zerolog-1.29.1/internal/json/types.go 2023-03-20 19:29:36.000000000 +0000 @@ -4,6 +4,7 @@ "fmt" "math" "net" + "reflect" "strconv" ) @@ -278,7 +279,7 @@ // AppendUint64 converts the input uint64 to a string and // appends the encoded string to the input byte slice. func (Encoder) AppendUint64(dst []byte, val uint64) []byte { - return strconv.AppendUint(dst, uint64(val), 10) + return strconv.AppendUint(dst, val, 10) } // AppendUints64 encodes the input uint64s to json and @@ -300,7 +301,7 @@ func appendFloat(dst []byte, val float64, bitSize int) []byte { // JSON does not permit NaN or Infinity. A typical JSON encoder would fail - // with an error, but a logging library wants the data to get thru so we + // with an error, but a logging library wants the data to get through so we // make a tradeoff and store those types as string. switch { case math.IsNaN(val): @@ -369,6 +370,14 @@ return append(dst, marshaled...) } +// AppendType appends the parameter type (as a string) to the input byte slice. +func (e Encoder) AppendType(dst []byte, i interface{}) []byte { + if i == nil { + return e.AppendString(dst, "") + } + return e.AppendString(dst, reflect.TypeOf(i).String()) +} + // AppendObjectData takes in an object that is already in a byte array // and adds it to the dst. func (Encoder) AppendObjectData(dst []byte, o []byte) []byte { diff -Nru golang-github-rs-zerolog-1.26.1/internal/json/types_test.go golang-github-rs-zerolog-1.29.1/internal/json/types_test.go --- golang-github-rs-zerolog-1.26.1/internal/json/types_test.go 2021-12-15 23:37:18.000000000 +0000 +++ golang-github-rs-zerolog-1.29.1/internal/json/types_test.go 2023-03-20 19:29:36.000000000 +0000 @@ -166,6 +166,28 @@ } } +func Test_appendType(t *testing.T) { + typeTests := []struct { + label string + input interface{} + want []byte + }{ + {"int", 42, []byte(`"int"`)}, + {"MAC", net.HardwareAddr{0x12, 0x34, 0x00, 0x00, 0x90, 0xab}, []byte(`"net.HardwareAddr"`)}, + {"float64", float64(2.50), []byte(`"float64"`)}, + {"nil", nil, []byte(`""`)}, + {"bool", true, []byte(`"bool"`)}, + } + + for _, tt := range typeTests { + t.Run(tt.label, func(t *testing.T) { + if got := enc.AppendType([]byte{}, tt.input); !reflect.DeepEqual(got, tt.want) { + t.Errorf("appendType() = %s, want %s", got, tt.want) + } + }) + } +} + func Test_appendObjectData(t *testing.T) { tests := []struct { dst []byte diff -Nru golang-github-rs-zerolog-1.26.1/journald/journald.go golang-github-rs-zerolog-1.29.1/journald/journald.go --- golang-github-rs-zerolog-1.26.1/journald/journald.go 2021-12-15 23:37:18.000000000 +0000 +++ golang-github-rs-zerolog-1.29.1/journald/journald.go 2023-03-20 19:29:36.000000000 +0000 @@ -1,3 +1,4 @@ +//go:build !windows // +build !windows // Package journald provides a io.Writer to send the logs @@ -69,11 +70,6 @@ } func (w journalWriter) Write(p []byte) (n int, err error) { - if !journal.Enabled() { - err = fmt.Errorf("cannot connect to journalD") - return - } - var event map[string]interface{} origPLen := len(p) p = cbor.DecodeIfBinaryToBytes(p) @@ -81,7 +77,7 @@ d.UseNumber() err = d.Decode(&event) jPrio := defaultJournalDPrio - args := make(map[string]string, 0) + args := make(map[string]string) if err != nil { return } @@ -100,13 +96,13 @@ continue } - switch value.(type) { + switch v := value.(type) { case string: - args[jKey], _ = value.(string) + args[jKey] = v case json.Number: args[jKey] = fmt.Sprint(value) default: - b, err := json.Marshal(value) + b, err := zerolog.InterfaceMarshalFunc(value) if err != nil { args[jKey] = fmt.Sprintf("[error: %v]", err) } else { diff -Nru golang-github-rs-zerolog-1.26.1/log_example_test.go golang-github-rs-zerolog-1.29.1/log_example_test.go --- golang-github-rs-zerolog-1.26.1/log_example_test.go 2021-12-15 23:37:18.000000000 +0000 +++ golang-github-rs-zerolog-1.29.1/log_example_test.go 2023-03-20 19:29:36.000000000 +0000 @@ -311,7 +311,7 @@ } func ExampleEvent_Dur() { - d := time.Duration(10 * time.Second) + d := 10 * time.Second log := zerolog.New(os.Stdout) @@ -325,8 +325,8 @@ func ExampleEvent_Durs() { d := []time.Duration{ - time.Duration(10 * time.Second), - time.Duration(20 * time.Second), + 10 * time.Second, + 20 * time.Second, } log := zerolog.New(os.Stdout) @@ -460,7 +460,7 @@ } func ExampleContext_Dur() { - d := time.Duration(10 * time.Second) + d := 10 * time.Second log := zerolog.New(os.Stdout).With(). Str("foo", "bar"). @@ -474,8 +474,8 @@ func ExampleContext_Durs() { d := []time.Duration{ - time.Duration(10 * time.Second), - time.Duration(20 * time.Second), + 10 * time.Second, + 20 * time.Second, } log := zerolog.New(os.Stdout).With(). @@ -510,7 +510,7 @@ // Output: {"Route":"192.168.0.0/24","message":"hello world"} } -func ExampleContext_MacAddr() { +func ExampleContext_MACAddr() { mac := net.HardwareAddr{0x00, 0x14, 0x22, 0x01, 0x23, 0x45} log := zerolog.New(os.Stdout).With(). MACAddr("hostMAC", mac). diff -Nru golang-github-rs-zerolog-1.26.1/log.go golang-github-rs-zerolog-1.29.1/log.go --- golang-github-rs-zerolog-1.26.1/log.go 2021-12-15 23:37:18.000000000 +0000 +++ golang-github-rs-zerolog-1.29.1/log.go 2023-03-20 19:29:36.000000000 +0000 @@ -99,11 +99,13 @@ package zerolog import ( + "errors" "fmt" "io" "io/ioutil" "os" "strconv" + "strings" ) // Level defines log levels. @@ -159,24 +161,24 @@ // ParseLevel converts a level string into a zerolog Level value. // returns an error if the input string does not match known values. func ParseLevel(levelStr string) (Level, error) { - switch levelStr { - case LevelFieldMarshalFunc(TraceLevel): + switch { + case strings.EqualFold(levelStr, LevelFieldMarshalFunc(TraceLevel)): return TraceLevel, nil - case LevelFieldMarshalFunc(DebugLevel): + case strings.EqualFold(levelStr, LevelFieldMarshalFunc(DebugLevel)): return DebugLevel, nil - case LevelFieldMarshalFunc(InfoLevel): + case strings.EqualFold(levelStr, LevelFieldMarshalFunc(InfoLevel)): return InfoLevel, nil - case LevelFieldMarshalFunc(WarnLevel): + case strings.EqualFold(levelStr, LevelFieldMarshalFunc(WarnLevel)): return WarnLevel, nil - case LevelFieldMarshalFunc(ErrorLevel): + case strings.EqualFold(levelStr, LevelFieldMarshalFunc(ErrorLevel)): return ErrorLevel, nil - case LevelFieldMarshalFunc(FatalLevel): + case strings.EqualFold(levelStr, LevelFieldMarshalFunc(FatalLevel)): return FatalLevel, nil - case LevelFieldMarshalFunc(PanicLevel): + case strings.EqualFold(levelStr, LevelFieldMarshalFunc(PanicLevel)): return PanicLevel, nil - case LevelFieldMarshalFunc(Disabled): + case strings.EqualFold(levelStr, LevelFieldMarshalFunc(Disabled)): return Disabled, nil - case LevelFieldMarshalFunc(NoLevel): + case strings.EqualFold(levelStr, LevelFieldMarshalFunc(NoLevel)): return NoLevel, nil } i, err := strconv.Atoi(levelStr) @@ -189,6 +191,21 @@ return Level(i), nil } +// UnmarshalText implements encoding.TextUnmarshaler to allow for easy reading from toml/yaml/json formats +func (l *Level) UnmarshalText(text []byte) error { + if l == nil { + return errors.New("can't unmarshal a nil *Level") + } + var err error + *l, err = ParseLevel(string(text)) + return err +} + +// MarshalText implements encoding.TextMarshaler to allow for easy writing into toml/yaml/json formats +func (l Level) MarshalText() ([]byte, error) { + return []byte(LevelFieldMarshalFunc(l)), nil +} + // A Logger represents an active logging object that generates lines // of JSON output to an io.Writer. Each logging operation makes a single // call to the Writer's Write method. There is no guarantee on access @@ -361,7 +378,7 @@ // WithLevel starts a new message with level. Unlike Fatal and Panic // methods, WithLevel does not terminate the program or stop the ordinary -// flow of a gourotine when used with their respective levels. +// flow of a goroutine when used with their respective levels. // // You must call Msg on the returned event in order to send the event. func (l *Logger) WithLevel(level Level) *Event { @@ -428,6 +445,9 @@ func (l *Logger) newEvent(level Level, done func(string)) *Event { enabled := l.should(level) if !enabled { + if done != nil { + done("") + } return nil } e := newEvent(l.w, level) diff -Nru golang-github-rs-zerolog-1.26.1/log_test.go golang-github-rs-zerolog-1.29.1/log_test.go --- golang-github-rs-zerolog-1.26.1/log_test.go 2021-12-15 23:37:18.000000000 +0000 +++ golang-github-rs-zerolog-1.29.1/log_test.go 2023-03-20 19:29:36.000000000 +0000 @@ -782,7 +782,7 @@ // test default behaviour this is really brittle due to the line numbers // actually mattering for validation - _, file, line, _ := runtime.Caller(0) + pc, file, line, _ := runtime.Caller(0) caller := fmt.Sprintf("%s:%d", file, line+2) log.Log().Caller().Msg("msg") if got, want := decodeIfBinaryToString(out.Bytes()), `{"caller":"`+caller+`","message":"msg"}`+"\n"; got != want { @@ -793,16 +793,16 @@ // test custom behavior. In this case we'll take just the last directory origCallerMarshalFunc := CallerMarshalFunc defer func() { CallerMarshalFunc = origCallerMarshalFunc }() - CallerMarshalFunc = func(file string, line int) string { + CallerMarshalFunc = func(pc uintptr, file string, line int) string { parts := strings.Split(file, "/") if len(parts) > 1 { return strings.Join(parts[len(parts)-2:], "/") + ":" + strconv.Itoa(line) } - return file + ":" + strconv.Itoa(line) + return runtime.FuncForPC(pc).Name() + ":" + file + ":" + strconv.Itoa(line) } - _, file, line, _ = runtime.Caller(0) - caller = CallerMarshalFunc(file, line+2) + pc, file, line, _ = runtime.Caller(0) + caller = CallerMarshalFunc(pc, file, line+2) log.Log().Caller().Msg("msg") if got, want := decodeIfBinaryToString(out.Bytes()), `{"caller":"`+caller+`","message":"msg"}`+"\n"; got != want { t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want) @@ -907,6 +907,33 @@ } } +func TestLevel_MarshalText(t *testing.T) { + tests := []struct { + name string + l Level + want string + }{ + {"trace", TraceLevel, "trace"}, + {"debug", DebugLevel, "debug"}, + {"info", InfoLevel, "info"}, + {"warn", WarnLevel, "warn"}, + {"error", ErrorLevel, "error"}, + {"fatal", FatalLevel, "fatal"}, + {"panic", PanicLevel, "panic"}, + {"disabled", Disabled, "disabled"}, + {"nolevel", NoLevel, ""}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got, err := tt.l.MarshalText(); err != nil { + t.Errorf("MarshalText couldn't marshal: %v", tt.l) + } else if string(got) != tt.want { + t.Errorf("String() = %v, want %v", string(got), tt.want) + } + }) + } +} + func TestParseLevel(t *testing.T) { type args struct { levelStr string @@ -942,4 +969,42 @@ } }) } +} + +func TestUnmarshalTextLevel(t *testing.T) { + type args struct { + levelStr string + } + tests := []struct { + name string + args args + want Level + wantErr bool + }{ + {"trace", args{"trace"}, TraceLevel, false}, + {"debug", args{"debug"}, DebugLevel, false}, + {"info", args{"info"}, InfoLevel, false}, + {"warn", args{"warn"}, WarnLevel, false}, + {"error", args{"error"}, ErrorLevel, false}, + {"fatal", args{"fatal"}, FatalLevel, false}, + {"panic", args{"panic"}, PanicLevel, false}, + {"disabled", args{"disabled"}, Disabled, false}, + {"nolevel", args{""}, NoLevel, false}, + {"-1", args{"-1"}, TraceLevel, false}, + {"-2", args{"-2"}, Level(-2), false}, + {"-3", args{"-3"}, Level(-3), false}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + var l Level + err := l.UnmarshalText([]byte(tt.args.levelStr)) + if (err != nil) != tt.wantErr { + t.Errorf("UnmarshalText() error = %v, wantErr %v", err, tt.wantErr) + return + } + if l != tt.want { + t.Errorf("UnmarshalText() got = %v, want %v", l, tt.want) + } + }) + } } diff -Nru golang-github-rs-zerolog-1.26.1/README.md golang-github-rs-zerolog-1.29.1/README.md --- golang-github-rs-zerolog-1.26.1/README.md 2021-12-15 23:37:18.000000000 +0000 +++ golang-github-rs-zerolog-1.29.1/README.md 2023-03-20 19:29:36.000000000 +0000 @@ -399,6 +399,8 @@ ### Add file and line number to log +Equivalent of `Llongfile`: + ```go log.Logger = log.With().Caller().Logger() log.Info().Msg("hello world") @@ -406,10 +408,29 @@ // Output: {"level": "info", "message": "hello world", "caller": "/go/src/your_project/some_file:21"} ``` +Equivalent of `Lshortfile`: + +```go +zerolog.CallerMarshalFunc = func(pc uintptr, file string, line int) string { + short := file + for i := len(file) - 1; i > 0; i-- { + if file[i] == '/' { + short = file[i+1:] + break + } + } + file = short + return file + ":" + strconv.Itoa(line) +} +log.Logger = log.With().Caller().Logger() +log.Info().Msg("hello world") + +// Output: {"level": "info", "message": "hello world", "caller": "some_file:21"} +``` ### Thread-safe, lock-free, non-blocking writer -If your writer might be slow or not thread-safe and you need your log producers to never get slowed down by a slow writer, you can use a `diode.Writer` as follow: +If your writer might be slow or not thread-safe and you need your log producers to never get slowed down by a slow writer, you can use a `diode.Writer` as follows: ```go wr := diode.NewWriter(os.Stdout, 1000, 10*time.Millisecond, func(missed int) { @@ -560,11 +581,11 @@ // Output (Line 1: Console; Line 2: Stdout) // 12:36PM INF Hello World! // {"level":"info","time":"2019-11-07T12:36:38+03:00","message":"Hello World!"} -``` +``` ## Global Settings -Some settings can be changed and will by applied to all loggers: +Some settings can be changed and will be applied to all loggers: * `log.Logger`: You can set this value to customize the global logger (the one used by package level methods). * `zerolog.SetGlobalLevel`: Can raise the minimum level of all loggers. Call this with `zerolog.Disabled` to disable logging altogether (quiet mode). @@ -604,7 +625,7 @@ ## Binary Encoding -In addition to the default JSON encoding, `zerolog` can produce binary logs using [CBOR](http://cbor.io) encoding. The choice of encoding can be decided at compile time using the build tag `binary_log` as follows: +In addition to the default JSON encoding, `zerolog` can produce binary logs using [CBOR](https://cbor.io) encoding. The choice of encoding can be decided at compile time using the build tag `binary_log` as follows: ```bash go build -tags binary_log .