mirror of
https://github.com/rwinkhart/go-winio.git
synced 2026-09-05 16:47:31 -04:00
Merge pull request #105 from kevpar/etw-activityid
Support ETW activity ID
This commit is contained in:
@@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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])
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user