From 664840fcdbd3b8ae41c0dbe2dce485923cd245f7 Mon Sep 17 00:00:00 2001 From: John Starks Date: Sun, 5 May 2019 00:37:35 +0000 Subject: [PATCH] pkg/etwlogrus: Ensure stable event field order This change updates the logrus hook to sort the incoming logrus data before passing it to the tracelogging code. This is useful because it ensures that two instances of the same event have the fields in the same order, which is necessary to get WPA to line the fields up. --- pkg/etwlogrus/hook.go | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/pkg/etwlogrus/hook.go b/pkg/etwlogrus/hook.go index 3476f7a..e296727 100644 --- a/pkg/etwlogrus/hook.go +++ b/pkg/etwlogrus/hook.go @@ -1,6 +1,8 @@ package etwlogrus import ( + "sort" + "github.com/Microsoft/go-winio/pkg/etw" "github.com/sirupsen/logrus" ) @@ -62,13 +64,29 @@ func (h *Hook) Fire(e *logrus.Entry) error { return nil } + // Sort the fields by name so they are consistent in each instance + // of an event. Otherwise, the fields don't line up in WPA. + names := make([]string, 0, len(e.Data)) + hasError := false + for k := range e.Data { + names := make([]string, 0, len(e.Data)) + if k == logrus.ErrorKey { + // Always put the error last because it is optional in some events. + hasError = true + } else { + names = append(names, k) + } + } + sort.Strings(names) + // Reserve extra space for the message field. fields := make([]etw.FieldOpt, 0, len(e.Data)+1) - fields = append(fields, etw.StringField("Message", e.Message)) - - for k, v := range e.Data { - fields = append(fields, etw.SmartField(k, v)) + for _, k := range names { + fields = append(fields, etw.SmartField(k, e.Data[k])) + } + if hasError { + fields = append(fields, etw.SmartField(logrus.ErrorKey, e.Data[logrus.ErrorKey])) } return h.provider.WriteEvent(