Skip to content

Commit

Permalink
Add a time.Location to ConsoleWriter. (This allows UTC timestamps.) (#…
Browse files Browse the repository at this point in the history
…531)

* Add a time.Location to ConsoleWriter. (This allows UTC timestamps.)

* add test
  • Loading branch information
FGasper committed Mar 2, 2024
1 parent 54ebf46 commit 582007f
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 8 deletions.
24 changes: 16 additions & 8 deletions console.go
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 All @@ -83,9 +87,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 @@ -284,7 +288,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 @@ -352,19 +356,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 @@ -385,7 +393,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
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

0 comments on commit 582007f

Please sign in to comment.