Merge pull request #105 from kevpar/etw-activityid

Support ETW activity ID
This commit is contained in:
Kevin Parsons
2019-01-08 11:23:21 -08:00
committed by GitHub
3 changed files with 44 additions and 16 deletions
+30 -7
View File
@@ -1,9 +1,20 @@
package etw package etw
import (
"golang.org/x/sys/windows"
)
type eventOptions struct {
descriptor *EventDescriptor
activityID *windows.GUID
relatedActivityID *windows.GUID
tags uint32
}
// EventOpt defines the option function type that can be passed to // EventOpt defines the option function type that can be passed to
// Provider.WriteEvent to specify general event options, such as level and // Provider.WriteEvent to specify general event options, such as level and
// keyword. // keyword.
type EventOpt func(*EventDescriptor, *uint32) type EventOpt func(options *eventOptions)
// WithEventOpts returns the variadic arguments as a single slice. // WithEventOpts returns the variadic arguments as a single slice.
func WithEventOpts(opts ...EventOpt) []EventOpt { func WithEventOpts(opts ...EventOpt) []EventOpt {
@@ -12,23 +23,35 @@ func WithEventOpts(opts ...EventOpt) []EventOpt {
// WithLevel specifies the level of the event to be written. // WithLevel specifies the level of the event to be written.
func WithLevel(level Level) EventOpt { func WithLevel(level Level) EventOpt {
return func(descriptor *EventDescriptor, tags *uint32) { return func(options *eventOptions) {
descriptor.Level = level options.descriptor.Level = level
} }
} }
// WithKeyword specifies the keywords of the event to be written. Multiple uses // WithKeyword specifies the keywords of the event to be written. Multiple uses
// of this option are OR'd together. // of this option are OR'd together.
func WithKeyword(keyword uint64) EventOpt { func WithKeyword(keyword uint64) EventOpt {
return func(descriptor *EventDescriptor, tags *uint32) { return func(options *eventOptions) {
descriptor.Keyword |= keyword options.descriptor.Keyword |= keyword
} }
} }
// WithTags specifies the tags of the event to be written. Tags is a 28-bit // WithTags specifies the tags of the event to be written. Tags is a 28-bit
// value (top 4 bits are ignored) which are interpreted by the event consumer. // value (top 4 bits are ignored) which are interpreted by the event consumer.
func WithTags(newTags uint32) EventOpt { func WithTags(newTags uint32) EventOpt {
return func(descriptor *EventDescriptor, tags *uint32) { return func(options *eventOptions) {
*tags |= newTags options.tags |= newTags
}
}
func WithActivityID(activityID *windows.GUID) EventOpt {
return func(options *eventOptions) {
options.activityID = activityID
}
}
func WithRelatedActivityID(activityID *windows.GUID) EventOpt {
return func(options *eventOptions) {
options.relatedActivityID = activityID
} }
} }
+13 -8
View File
@@ -181,28 +181,27 @@ func (provider *Provider) IsEnabledForLevelAndKeywords(level Level, keywords uin
// constructed based on the EventOpt and FieldOpt values that are passed as // constructed based on the EventOpt and FieldOpt values that are passed as
// opts. // opts.
func (provider *Provider) WriteEvent(name string, eventOpts []EventOpt, fieldOpts []FieldOpt) error { func (provider *Provider) WriteEvent(name string, eventOpts []EventOpt, fieldOpts []FieldOpt) error {
tags := uint32(0) options := eventOptions{descriptor: NewEventDescriptor()}
descriptor := NewEventDescriptor()
em := &EventMetadata{} em := &EventMetadata{}
ed := &EventData{} ed := &EventData{}
// We need to evaluate the EventOpts first since they might change tags, and // We need to evaluate the EventOpts first since they might change tags, and
// we write out the tags before evaluating FieldOpts. // we write out the tags before evaluating FieldOpts.
for _, opt := range eventOpts { for _, opt := range eventOpts {
opt(descriptor, &tags) opt(&options)
} }
if !provider.IsEnabledForLevelAndKeywords(descriptor.Level, descriptor.Keyword) { if !provider.IsEnabledForLevelAndKeywords(options.descriptor.Level, options.descriptor.Keyword) {
return nil return nil
} }
em.WriteEventHeader(name, tags) em.WriteEventHeader(name, options.tags)
for _, opt := range fieldOpts { for _, opt := range fieldOpts {
opt(em, ed) opt(em, ed)
} }
return provider.WriteEventRaw(descriptor, [][]byte{em.Bytes()}, [][]byte{ed.Bytes()}) return provider.WriteEventRaw(options.descriptor, nil, nil, [][]byte{em.Bytes()}, [][]byte{ed.Bytes()})
} }
// WriteEventRaw writes a single ETW event from the provider. This function is // WriteEventRaw writes a single ETW event from the provider. This function is
@@ -212,7 +211,13 @@ func (provider *Provider) WriteEvent(name string, eventOpts []EventOpt, fieldOpt
// schema. The functions on EventMetadata and EventData can help with creating // schema. The functions on EventMetadata and EventData can help with creating
// these blobs. The blobs of each type are effectively concatenated together by // these blobs. The blobs of each type are effectively concatenated together by
// the ETW infrastructure. // the ETW infrastructure.
func (provider *Provider) WriteEventRaw(descriptor *EventDescriptor, metadataBlobs [][]byte, dataBlobs [][]byte) error { func (provider *Provider) WriteEventRaw(
descriptor *EventDescriptor,
activityID *windows.GUID,
relatedActivityID *windows.GUID,
metadataBlobs [][]byte,
dataBlobs [][]byte) error {
dataDescriptorCount := uint32(1 + len(metadataBlobs) + len(dataBlobs)) dataDescriptorCount := uint32(1 + len(metadataBlobs) + len(dataBlobs))
dataDescriptors := make([]eventDataDescriptor, 0, dataDescriptorCount) dataDescriptors := make([]eventDataDescriptor, 0, dataDescriptorCount)
@@ -224,5 +229,5 @@ func (provider *Provider) WriteEventRaw(descriptor *EventDescriptor, metadataBlo
dataDescriptors = append(dataDescriptors, newEventDataDescriptor(eventDataDescriptorTypeUserData, blob)) dataDescriptors = append(dataDescriptors, newEventDataDescriptor(eventDataDescriptorTypeUserData, blob))
} }
return eventWriteTransfer(provider.handle, descriptor, nil, nil, dataDescriptorCount, &dataDescriptors[0]) return eventWriteTransfer(provider.handle, descriptor, activityID, relatedActivityID, dataDescriptorCount, &dataDescriptors[0])
} }
+1 -1
View File
@@ -102,7 +102,7 @@ func main() {
ed.WriteString("Item3") ed.WriteString("Item3")
ed.WriteString("Item4") ed.WriteString("Item4")
ed.WriteString("Item5") ed.WriteString("Item5")
if err := provider.WriteEventRaw(descriptor, [][]byte{em.Bytes()}, [][]byte{ed.Bytes()}); err != nil { if err := provider.WriteEventRaw(descriptor, nil, nil, [][]byte{em.Bytes()}, [][]byte{ed.Bytes()}); err != nil {
logrus.Error(err) logrus.Error(err)
return return
} }