mirror of
https://github.com/rwinkhart/go-winio.git
synced 2026-09-05 16:47:31 -04:00
Add ETW support for arrays
This commit is contained in:
@@ -2,6 +2,7 @@ package etw
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"encoding/binary"
|
||||||
)
|
)
|
||||||
|
|
||||||
// EventData maintains a buffer which builds up the data for an ETW event. It
|
// EventData maintains a buffer which builds up the data for an ETW event. It
|
||||||
@@ -20,3 +21,10 @@ func (ed *EventData) AddString(data string) {
|
|||||||
ed.buffer.WriteString(data)
|
ed.buffer.WriteString(data)
|
||||||
ed.buffer.WriteByte(0)
|
ed.buffer.WriteByte(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This is mostly added for testing purposes, and will be removed later, as we
|
||||||
|
// shouldn't take a dependency on binary.Write knowing how to marshal values
|
||||||
|
// correctly for TraceLogging.
|
||||||
|
func (ed *EventData) AddSimple(data interface{}) {
|
||||||
|
binary.Write(&ed.buffer, binary.LittleEndian, data)
|
||||||
|
}
|
||||||
|
|||||||
@@ -37,6 +37,9 @@ const (
|
|||||||
InTypeCountedANSIString
|
InTypeCountedANSIString
|
||||||
InTypeStruct
|
InTypeStruct
|
||||||
InTypeCountedBinary
|
InTypeCountedBinary
|
||||||
|
|
||||||
|
InTypeCountedArray InType = 32
|
||||||
|
InTypeArray InType = 64
|
||||||
)
|
)
|
||||||
|
|
||||||
// OutType specifies a hint to the event decoder for how the value should be
|
// OutType specifies a hint to the event decoder for how the value should be
|
||||||
@@ -73,7 +76,7 @@ const (
|
|||||||
OutTypeDateTimeUTC OutType = 38
|
OutTypeDateTimeUTC OutType = 38
|
||||||
)
|
)
|
||||||
|
|
||||||
// EventMetadata maintains a buffer which builds up the metadatadata for an ETW
|
// EventMetadata maintains a buffer which builds up the metadata for an ETW
|
||||||
// event. It needs to be paired with EventData which describes the event.
|
// event. It needs to be paired with EventData which describes the event.
|
||||||
type EventMetadata struct {
|
type EventMetadata struct {
|
||||||
buffer bytes.Buffer
|
buffer bytes.Buffer
|
||||||
@@ -91,10 +94,11 @@ func NewEventMetadata(name string) *EventMetadata {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type field struct {
|
type field struct {
|
||||||
name string
|
name string
|
||||||
inType InType
|
inType InType
|
||||||
outType OutType
|
outType OutType
|
||||||
tags uint32
|
tags uint32
|
||||||
|
countedArraySize uint16
|
||||||
}
|
}
|
||||||
|
|
||||||
func (em *EventMetadata) writeField(f field) {
|
func (em *EventMetadata) writeField(f field) {
|
||||||
@@ -112,6 +116,10 @@ func (em *EventMetadata) writeField(f field) {
|
|||||||
em.writeTags(f.tags)
|
em.writeTags(f.tags)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if f.countedArraySize != 0 {
|
||||||
|
binary.Write(&em.buffer, binary.LittleEndian, f.countedArraySize)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// writeTags writes out the tags value to the event metadata. Tags is a 28-bit
|
// writeTags writes out the tags value to the event metadata. Tags is a 28-bit
|
||||||
@@ -163,6 +171,24 @@ func WithTags(tags uint32) fieldOpt {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WithCountedArray marks the field as being an array of a fixed number of
|
||||||
|
// elements. The number of elements is encoded directly into the field metadata.
|
||||||
|
func WithCountedArray(count uint16) fieldOpt {
|
||||||
|
return func(f *field) {
|
||||||
|
f.inType |= InTypeCountedArray
|
||||||
|
f.countedArraySize = count
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithArray marks the field as being an array of a dynamic number of elements.
|
||||||
|
// The number of elements must be written as a uint16 to the data block,
|
||||||
|
// immediately preceeding the array elements.
|
||||||
|
func WithArray() fieldOpt {
|
||||||
|
return func(f *field) {
|
||||||
|
f.inType |= InTypeArray
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// AddField appends a single field to the end of the event metadata buffer.
|
// AddField appends a single field to the end of the event metadata buffer.
|
||||||
func (em *EventMetadata) AddField(name string, inType InType, opts ...fieldOpt) {
|
func (em *EventMetadata) AddField(name string, inType InType, opts ...fieldOpt) {
|
||||||
f := field{
|
f := field{
|
||||||
|
|||||||
@@ -59,6 +59,13 @@ func main() {
|
|||||||
event.Data.AddString("Foo")
|
event.Data.AddString("Foo")
|
||||||
event.Metadata.AddField("TestField2", etw.InTypeANSIString)
|
event.Metadata.AddField("TestField2", etw.InTypeANSIString)
|
||||||
event.Data.AddString("Bar")
|
event.Data.AddString("Bar")
|
||||||
|
event.Metadata.AddField("TestArray", etw.InTypeANSIString, etw.WithArray())
|
||||||
|
event.Data.AddSimple(uint16(5))
|
||||||
|
event.Data.AddString("Item1")
|
||||||
|
event.Data.AddString("Item2")
|
||||||
|
event.Data.AddString("Item3")
|
||||||
|
event.Data.AddString("Item4")
|
||||||
|
event.Data.AddString("Item5")
|
||||||
|
|
||||||
if err := provider.WriteEvent(event); err != nil {
|
if err := provider.WriteEvent(event); err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
|
|||||||
Reference in New Issue
Block a user