diff --git a/pkg/etw/eventdata.go b/pkg/etw/eventdata.go index 79dc10a..a524d89 100644 --- a/pkg/etw/eventdata.go +++ b/pkg/etw/eventdata.go @@ -3,6 +3,7 @@ package etw import ( "bytes" "encoding/binary" + "syscall" ) // eventData maintains a buffer which builds up the data for an ETW event. It @@ -63,3 +64,8 @@ func (ed *eventData) writeUint32(value uint32) { func (ed *eventData) writeUint64(value uint64) { binary.Write(&ed.buffer, binary.LittleEndian, value) } + +// writeFiletime appends a FILETIME to the buffer. +func (ed *eventData) writeFiletime(value syscall.Filetime) { + binary.Write(&ed.buffer, binary.LittleEndian, value) +} diff --git a/pkg/etw/fieldopt.go b/pkg/etw/fieldopt.go index c29c6bd..d544a29 100644 --- a/pkg/etw/fieldopt.go +++ b/pkg/etw/fieldopt.go @@ -4,6 +4,8 @@ import ( "fmt" "math" "reflect" + "syscall" + "time" "unsafe" ) @@ -380,6 +382,14 @@ func Struct(name string, opts ...FieldOpt) FieldOpt { } } +// Time adds a time to the event. +func Time(name string, value time.Time) FieldOpt { + return func(em *eventMetadata, ed *eventData) { + em.writeField(name, inTypeFileTime, outTypeDateTimeUTC, 0) + ed.writeFiletime(syscall.NsecToFiletime(value.UTC().UnixNano())) + } +} + // Currently, we support logging basic builtin types (int, string, etc), slices // of basic builtin types, error, types derived from the basic types (e.g. "type // foo int"), and structs (recursively logging their fields). We do not support @@ -454,6 +464,8 @@ func SmartField(name string, v interface{}) FieldOpt { return Float64Array(name, v) case error: return StringField(name, v.Error()) + case time.Time: + return Time(name, v) default: switch rv := reflect.ValueOf(v); rv.Kind() { case reflect.Bool: