Skip to content

Commit

Permalink
Move FieldsOrder work to separate method and only call if necessary
Browse files Browse the repository at this point in the history
  • Loading branch information
mAdkins committed Mar 2, 2024
1 parent 0566de1 commit 1d95235
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 21 deletions.
59 changes: 40 additions & 19 deletions console.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import (
"strings"
"sync"
"time"

"github.com/mattn/go-colorable"
)

const (
Expand Down Expand Up @@ -64,6 +66,8 @@ type ConsoleWriter struct {
// FieldsOrder defines the order of contextual fields in output.
FieldsOrder []string

fieldIsOrdered map[string]bool

// FieldsExclude defines contextual fields to not display in output.
FieldsExclude []string

Expand Down Expand Up @@ -167,15 +171,6 @@ func (w ConsoleWriter) Close() error {

// writeFields appends formatted key-value pairs to buf.
func (w ConsoleWriter) writeFields(evt map[string]interface{}, buf *bytes.Buffer) {
var isOrderedField = make(map[string]bool)
var orderedFields = make([]string, 0, len(w.FieldsOrder))
for _, fieldName := range w.FieldsOrder {
if evt[fieldName] != nil {
orderedFields = append(orderedFields, fieldName)
isOrderedField[fieldName] = true
}
}

var fields = make([]string, 0, len(evt))
for field := range evt {
var isExcluded bool
Expand All @@ -194,26 +189,24 @@ func (w ConsoleWriter) writeFields(evt map[string]interface{}, buf *bytes.Buffer
continue
}

if isOrderedField[field] {
continue
}

fields = append(fields, field)
}
sort.Strings(fields)

totalFields := len(orderedFields) + len(fields)
if len(w.FieldsOrder) > 0 {
fields = w.orderFields(fields)
}

// Write space only if something has already been written to the buffer, and if there are fields.
if buf.Len() > 0 && totalFields > 0 {
if buf.Len() > 0 && len(fields) > 0 {
buf.WriteByte(' ')
}

// Move the "error" field to the front of the orderedFields list
// Move the "error" field to the front
ei := sort.Search(len(fields), func(i int) bool { return fields[i] >= ErrorFieldName })
if ei < len(fields) && fields[ei] == ErrorFieldName {
fields[ei] = ""
orderedFields = append([]string{ErrorFieldName}, orderedFields...)
fields = append([]string{ErrorFieldName}, fields...)
var xfields = make([]string, 0, len(fields))
for _, field := range fields {
if field == "" { // Skip empty fields
Expand All @@ -224,7 +217,7 @@ func (w ConsoleWriter) writeFields(evt map[string]interface{}, buf *bytes.Buffer
fields = xfields
}

for i, field := range append(orderedFields, fields...) {
for i, field := range fields {
var fn Formatter
var fv Formatter

Expand Down Expand Up @@ -274,7 +267,7 @@ func (w ConsoleWriter) writeFields(evt map[string]interface{}, buf *bytes.Buffer
}
}

if i < totalFields-1 { // Skip space for last field
if i < len(fields)-1 { // Skip space for last field
buf.WriteByte(' ')
}
}
Expand Down Expand Up @@ -335,6 +328,34 @@ func (w ConsoleWriter) writePart(buf *bytes.Buffer, evt map[string]interface{},
}
}

// orderFields takes an array of field names and an array representing field order
// and returns an array with any ordered fields at the beginning, in order,
// and the remaining fields after in their original order.
func (w ConsoleWriter) orderFields(fields []string) []string {
if w.fieldIsOrdered == nil {
w.fieldIsOrdered = make(map[string]bool)
for _, fieldName := range w.FieldsOrder {
w.fieldIsOrdered[fieldName] = true
}
}
hasOrderedField := make(map[string]bool)
otherFields := make([]string, 0, len(fields))
for _, fieldName := range fields {
if w.fieldIsOrdered[fieldName] {
hasOrderedField[fieldName] = true
} else {
otherFields = append(otherFields, fieldName)
}
}
result := make([]string, 0, len(fields))
for _, fieldName := range w.FieldsOrder {
if hasOrderedField[fieldName] {
result = append(result, fieldName)
}
}
return append(result, otherFields...)
}

// needsQuote returns true when the string s should be quoted in output.
func needsQuote(s string) bool {
for i := range s {
Expand Down
4 changes: 2 additions & 2 deletions console_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -382,13 +382,13 @@ func TestConsoleWriterConfiguration(t *testing.T) {
buf := &bytes.Buffer{}
w := zerolog.ConsoleWriter{Out: buf, NoColor: true, FieldsOrder: []string{"zebra", "aardvark"}}

evt := `{"level": "info", "message": "Zoo", "aardvark": "Able", "zebra": "Zulu"}`
evt := `{"level": "info", "message": "Zoo", "aardvark": "Able", "mussel": "Mountain", "zebra": "Zulu"}`
_, err := w.Write([]byte(evt))
if err != nil {
t.Errorf("Unexpected error when writing output: %s", err)
}

expectedOutput := "<nil> INF Zoo zebra=Zulu aardvark=Able\n"
expectedOutput := "<nil> INF Zoo zebra=Zulu aardvark=Able mussel=Mountain\n"
actualOutput := buf.String()
if actualOutput != expectedOutput {
t.Errorf("Unexpected output %q, want: %q", actualOutput, expectedOutput)
Expand Down

0 comments on commit 1d95235

Please sign in to comment.