Skip to content

Commit

Permalink
Merge branch 'rs:master' into add-fields-order
Browse files Browse the repository at this point in the history
  • Loading branch information
madkins23 authored Mar 2, 2024
2 parents 51830d5 + 582007f commit e921ebf
Show file tree
Hide file tree
Showing 7 changed files with 433 additions and 23 deletions.
12 changes: 2 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ func main() {
// Output: {"time":1516134303,"level":"debug","message":"hello world"}
```
> Note: By default log writes to `os.Stderr`
> Note: The default log level for `log.Print` is *debug*
> Note: The default log level for `log.Print` is *trace*
### Contextual Logging

Expand Down Expand Up @@ -412,15 +412,7 @@ 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)
return filepath.Base(file) + ":" + strconv.Itoa(line)
}
log.Logger = log.With().Caller().Logger()
log.Info().Msg("hello world")
Expand Down
24 changes: 16 additions & 8 deletions console.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@ type ConsoleWriter struct {
// TimeFormat specifies the format for timestamp in output.
TimeFormat string

// TimeLocation tells ConsoleWriter’s default FormatTimestamp
// how to localize the time.
TimeLocation *time.Location

// PartsOrder defines the order of parts in output.
PartsOrder []string

Expand Down Expand Up @@ -88,9 +92,9 @@ type ConsoleWriter struct {
// NewConsoleWriter creates and initializes a new ConsoleWriter.
func NewConsoleWriter(options ...func(w *ConsoleWriter)) ConsoleWriter {
w := ConsoleWriter{
Out: os.Stdout,
TimeFormat: consoleDefaultTimeFormat,
PartsOrder: consoleDefaultPartsOrder(),
Out: os.Stdout,
TimeFormat: consoleDefaultTimeFormat,
PartsOrder: consoleDefaultPartsOrder(),
}

for _, opt := range options {
Expand Down Expand Up @@ -294,7 +298,7 @@ func (w ConsoleWriter) writePart(buf *bytes.Buffer, evt map[string]interface{},
}
case TimestampFieldName:
if w.FormatTimestamp == nil {
f = consoleDefaultFormatTimestamp(w.TimeFormat, w.NoColor)
f = consoleDefaultFormatTimestamp(w.TimeFormat, w.TimeLocation, w.NoColor)
} else {
f = w.FormatTimestamp
}
Expand Down Expand Up @@ -390,19 +394,23 @@ func consoleDefaultPartsOrder() []string {
}
}

func consoleDefaultFormatTimestamp(timeFormat string, noColor bool) Formatter {
func consoleDefaultFormatTimestamp(timeFormat string, location *time.Location, noColor bool) Formatter {
if timeFormat == "" {
timeFormat = consoleDefaultTimeFormat
}
if location == nil {
location = time.Local
}

return func(i interface{}) string {
t := "<nil>"
switch tt := i.(type) {
case string:
ts, err := time.ParseInLocation(TimeFieldFormat, tt, time.Local)
ts, err := time.ParseInLocation(TimeFieldFormat, tt, location)
if err != nil {
t = tt
} else {
t = ts.Local().Format(timeFormat)
t = ts.In(location).Format(timeFormat)
}
case json.Number:
i, err := tt.Int64()
Expand All @@ -423,7 +431,7 @@ func consoleDefaultFormatTimestamp(timeFormat string, noColor bool) Formatter {
}

ts := time.Unix(sec, nsec)
t = ts.Format(timeFormat)
t = ts.In(location).Format(timeFormat)
}
}
return colorize(t, colorDarkGray, noColor)
Expand Down
29 changes: 29 additions & 0 deletions console_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,35 @@ func TestConsoleWriterConfiguration(t *testing.T) {
}
})

t.Run("Sets TimeFormat and TimeLocation", func(t *testing.T) {
locs := []*time.Location{ time.Local, time.UTC }

for _, location := range locs {
buf := &bytes.Buffer{}
w := zerolog.ConsoleWriter{
Out: buf,
NoColor: true,
TimeFormat: time.RFC3339,
TimeLocation: location,
}

ts := time.Unix(0, 0)
d := ts.UTC().Format(time.RFC3339)
evt := `{"time": "` + d + `", "level": "info", "message": "Foobar"}`

_, err := w.Write([]byte(evt))
if err != nil {
t.Errorf("Unexpected error when writing output: %s", err)
}

expectedOutput := ts.In(location).Format(time.RFC3339) + " INF Foobar\n"
actualOutput := buf.String()
if actualOutput != expectedOutput {
t.Errorf("Unexpected output %q, want: %q (location=%s)", actualOutput, expectedOutput, location)
}
}
})

t.Run("Sets PartsOrder", func(t *testing.T) {
buf := &bytes.Buffer{}
w := zerolog.ConsoleWriter{Out: buf, NoColor: true, PartsOrder: []string{"message", "level"}}
Expand Down
19 changes: 17 additions & 2 deletions globals.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package zerolog

import (
"bytes"
"encoding/json"
"strconv"
"sync/atomic"
Expand Down Expand Up @@ -81,8 +82,22 @@ var (
}

// InterfaceMarshalFunc allows customization of interface marshaling.
// Default: "encoding/json.Marshal"
InterfaceMarshalFunc = json.Marshal
// Default: "encoding/json.Marshal" with disabled HTML escaping
InterfaceMarshalFunc = func(v interface{}) ([]byte, error) {
var buf bytes.Buffer
encoder := json.NewEncoder(&buf)
encoder.SetEscapeHTML(false)
err := encoder.Encode(v)
if err != nil {
return nil, err
}
b := buf.Bytes()
if len(b) > 0 {
// Remove trailing \n which is added by Encode.
return b[:len(b)-1], nil
}
return b, nil
}

// TimeFieldFormat defines the time format of the Time field type. If set to
// TimeFormatUnix, TimeFormatUnixMs, TimeFormatUnixMicro or TimeFormatUnixNano, the time is formatted as a UNIX
Expand Down
20 changes: 19 additions & 1 deletion internal/json/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,25 @@ func appendFloat(dst []byte, val float64, bitSize int) []byte {
case math.IsInf(val, -1):
return append(dst, `"-Inf"`...)
}
return strconv.AppendFloat(dst, val, 'f', -1, bitSize)
// convert as if by es6 number to string conversion
// see also https://cs.opensource.google/go/go/+/refs/tags/go1.20.3:src/encoding/json/encode.go;l=573
strFmt := byte('f')
// Use float32 comparisons for underlying float32 value to get precise cutoffs right.
if abs := math.Abs(val); abs != 0 {
if bitSize == 64 && (abs < 1e-6 || abs >= 1e21) || bitSize == 32 && (float32(abs) < 1e-6 || float32(abs) >= 1e21) {
strFmt = 'e'
}
}
dst = strconv.AppendFloat(dst, val, strFmt, -1, bitSize)
if strFmt == 'e' {
// Clean up e-09 to e-9
n := len(dst)
if n >= 4 && dst[n-4] == 'e' && dst[n-3] == '-' && dst[n-2] == '0' {
dst[n-2] = dst[n-1]
dst = dst[:n-1]
}
}
return dst
}

// AppendFloat32 converts the input float32 to a string and
Expand Down
Loading

0 comments on commit e921ebf

Please sign in to comment.