@@ -69,6 +69,11 @@ type ConsoleWriter struct {
69
69
// PartsExclude defines parts to not display in output.
70
70
PartsExclude []string
71
71
72
+ // FieldsOrder defines the order of contextual fields in output.
73
+ FieldsOrder []string
74
+
75
+ fieldIsOrdered map [string ]int
76
+
72
77
// FieldsExclude defines contextual fields to not display in output.
73
78
FieldsExclude []string
74
79
@@ -191,7 +196,12 @@ func (w ConsoleWriter) writeFields(evt map[string]interface{}, buf *bytes.Buffer
191
196
}
192
197
fields = append (fields , field )
193
198
}
194
- sort .Strings (fields )
199
+
200
+ if len (w .FieldsOrder ) > 0 {
201
+ w .orderFields (fields )
202
+ } else {
203
+ sort .Strings (fields )
204
+ }
195
205
196
206
// Write space only if something has already been written to the buffer, and if there are fields.
197
207
if buf .Len () > 0 && len (fields ) > 0 {
@@ -324,6 +334,32 @@ func (w ConsoleWriter) writePart(buf *bytes.Buffer, evt map[string]interface{},
324
334
}
325
335
}
326
336
337
+ // orderFields takes an array of field names and an array representing field order
338
+ // and returns an array with any ordered fields at the beginning, in order,
339
+ // and the remaining fields after in their original order.
340
+ func (w ConsoleWriter ) orderFields (fields []string ) {
341
+ if w .fieldIsOrdered == nil {
342
+ w .fieldIsOrdered = make (map [string ]int )
343
+ for i , fieldName := range w .FieldsOrder {
344
+ w .fieldIsOrdered [fieldName ] = i
345
+ }
346
+ }
347
+ sort .Slice (fields , func (i , j int ) bool {
348
+ ii , iOrdered := w.fieldIsOrdered [fields [i ]]
349
+ jj , jOrdered := w.fieldIsOrdered [fields [j ]]
350
+ if iOrdered && jOrdered {
351
+ return ii < jj
352
+ }
353
+ if iOrdered {
354
+ return true
355
+ }
356
+ if jOrdered {
357
+ return false
358
+ }
359
+ return fields [i ] < fields [j ]
360
+ })
361
+ }
362
+
327
363
// needsQuote returns true when the string s should be quoted in output.
328
364
func needsQuote (s string ) bool {
329
365
for i := range s {
0 commit comments