mirror of
https://github.com/rwinkhart/go-winio.git
synced 2026-09-05 16:47:31 -04:00
Add comments
This commit is contained in:
+43
-10
@@ -1,13 +1,23 @@
|
|||||||
package etw
|
package etw
|
||||||
|
|
||||||
|
// Channel represents the ETW logging channel that is used. It can be used by
|
||||||
|
// event consumers to give an event special treatment.
|
||||||
type Channel uint8
|
type Channel uint8
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
// ChannelTracelogging is the default channel for tracelogging events. It is
|
||||||
|
// not required to be used for tracelogging, but will prevent decoding
|
||||||
|
// issues for these events on older operating systems.
|
||||||
ChannelTracelogging Channel = 11
|
ChannelTracelogging Channel = 11
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Level represents the ETW logging level. There are several predefined levels
|
||||||
|
// that are commonly used, but technically anything from 0-255 is allowed.
|
||||||
|
// Lower levels indicate more important events, and 0 indicates an event that
|
||||||
|
// will always be collected.
|
||||||
type Level uint8
|
type Level uint8
|
||||||
|
|
||||||
|
// Predefined ETW log levels.
|
||||||
const (
|
const (
|
||||||
LevelAlways Level = iota
|
LevelAlways Level = iota
|
||||||
LevelCritical
|
LevelCritical
|
||||||
@@ -17,15 +27,27 @@ const (
|
|||||||
LevelVerbose
|
LevelVerbose
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Event represents a single ETW event. It can have field metadata and data
|
||||||
|
// added to it, and then be logged via a provider to actually send it to ETW.
|
||||||
type Event struct {
|
type Event struct {
|
||||||
Descriptor *EventDescriptor
|
Descriptor *EventDescriptor
|
||||||
Metadata *EventMetadata
|
Metadata *EventMetadata
|
||||||
Data *EventData
|
Data *EventData
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewEvent returns a new instance of an event object.
|
||||||
|
func NewEvent(name string, descriptor *EventDescriptor) *Event {
|
||||||
|
return &Event{
|
||||||
|
Descriptor: descriptor,
|
||||||
|
Metadata: NewEventMetadata(name),
|
||||||
|
Data: &EventData{},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// EventDescriptor represents various metadata for an ETW event.
|
||||||
type EventDescriptor struct {
|
type EventDescriptor struct {
|
||||||
ID uint16
|
id uint16
|
||||||
Version uint8
|
version uint8
|
||||||
Channel Channel
|
Channel Channel
|
||||||
Level Level
|
Level Level
|
||||||
Opcode uint8
|
Opcode uint8
|
||||||
@@ -33,10 +55,12 @@ type EventDescriptor struct {
|
|||||||
Keyword uint64
|
Keyword uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewEventDescriptor returns an EventDescriptor initialized for use with
|
||||||
|
// tracelogging.
|
||||||
func NewEventDescriptor() *EventDescriptor {
|
func NewEventDescriptor() *EventDescriptor {
|
||||||
return &EventDescriptor{
|
return &EventDescriptor{
|
||||||
ID: 0,
|
id: 0,
|
||||||
Version: 0,
|
version: 0,
|
||||||
Channel: ChannelTracelogging,
|
Channel: ChannelTracelogging,
|
||||||
Level: LevelVerbose,
|
Level: LevelVerbose,
|
||||||
Opcode: 0,
|
Opcode: 0,
|
||||||
@@ -45,10 +69,19 @@ func NewEventDescriptor() *EventDescriptor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewEvent(name string, descriptor *EventDescriptor) *Event {
|
// Identity returns the identity of the event. If the identity is not 0, it
|
||||||
return &Event{
|
// should uniquely identify the other event metadata (contained in
|
||||||
Descriptor: descriptor,
|
// EventDescriptor, and field metadata). Only the lower 24 bits of this value
|
||||||
Metadata: NewEventMetadata(name),
|
// are relevant.
|
||||||
Data: &EventData{},
|
func (ed *EventDescriptor) Identity() uint32 {
|
||||||
}
|
return (uint32(ed.version) << 16) & uint32(ed.id)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetIdentity sets the identity of the event. If the identity is not 0, it
|
||||||
|
// should uniquely identify the other event metadata (contained in
|
||||||
|
// EventDescriptor, and field metadata). Only the lower 24 bits of this value
|
||||||
|
// are relevant.
|
||||||
|
func (ed *EventDescriptor) SetIdentity(identity uint32) {
|
||||||
|
ed.id = uint16(identity)
|
||||||
|
ed.version = uint8(identity >> 16)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,10 +5,18 @@ import (
|
|||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// EventData maintains a buffer which builds up the data for an ETW event. It
|
||||||
|
// needs to be paired with EventMetadata which describes the event.
|
||||||
type EventData struct {
|
type EventData struct {
|
||||||
buffer bytes.Buffer
|
buffer bytes.Buffer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewEventData returns a new EventData with an empty buffer.
|
||||||
|
func NewEventData() *EventData {
|
||||||
|
return &EventData{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddString appends the data for a string to the end of the buffer.
|
||||||
func (ed *EventData) AddString(data string) {
|
func (ed *EventData) AddString(data string) {
|
||||||
binary.Write(&ed.buffer, binary.LittleEndian, []byte(data))
|
binary.Write(&ed.buffer, binary.LittleEndian, []byte(data))
|
||||||
binary.Write(&ed.buffer, binary.LittleEndian, byte(0))
|
binary.Write(&ed.buffer, binary.LittleEndian, byte(0))
|
||||||
|
|||||||
@@ -5,8 +5,10 @@ import (
|
|||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// InType indicates the type of data contained in the ETW event.
|
||||||
type InType byte
|
type InType byte
|
||||||
|
|
||||||
|
// Various InType definitions for tracelogging.
|
||||||
const (
|
const (
|
||||||
InTypeNull InType = iota
|
InTypeNull InType = iota
|
||||||
InTypeUnicodeString
|
InTypeUnicodeString
|
||||||
@@ -24,10 +26,14 @@ const (
|
|||||||
InTypeBool32
|
InTypeBool32
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// EventMetadata maintains a buffer which builds up the metadatadata for an ETW
|
||||||
|
// event. It needs to be paired with EventData which describes the event.
|
||||||
type EventMetadata struct {
|
type EventMetadata struct {
|
||||||
buffer bytes.Buffer
|
buffer bytes.Buffer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewEventMetadata returns a new EventMetadata with event name and initial
|
||||||
|
// metadata written to the buffer.
|
||||||
func NewEventMetadata(name string) *EventMetadata {
|
func NewEventMetadata(name string) *EventMetadata {
|
||||||
em := EventMetadata{}
|
em := EventMetadata{}
|
||||||
binary.Write(&em.buffer, binary.LittleEndian, uint16(0)) // Length placeholder
|
binary.Write(&em.buffer, binary.LittleEndian, uint16(0)) // Length placeholder
|
||||||
@@ -37,6 +43,7 @@ func NewEventMetadata(name string) *EventMetadata {
|
|||||||
return &em
|
return &em
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AddField appends a single field to the end of the event metadata buffer.
|
||||||
func (em *EventMetadata) AddField(name string, inType InType) {
|
func (em *EventMetadata) AddField(name string, inType InType) {
|
||||||
binary.Write(&em.buffer, binary.LittleEndian, []byte(name)) // Field name
|
binary.Write(&em.buffer, binary.LittleEndian, []byte(name)) // Field name
|
||||||
binary.Write(&em.buffer, binary.LittleEndian, byte(0)) // Null terminator for name
|
binary.Write(&em.buffer, binary.LittleEndian, byte(0)) // Null terminator for name
|
||||||
|
|||||||
+12
-6
@@ -16,6 +16,9 @@ const (
|
|||||||
eventDataDescriptorTypeProviderMetadata
|
eventDataDescriptorTypeProviderMetadata
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Provider represents an ETW event provider. It is identified by a provider
|
||||||
|
// name and ID (GUID), which should always have a 1:1 mapping to each other
|
||||||
|
// (e.g. don't use multiple provider names with the same ID, or vice versa).
|
||||||
type Provider struct {
|
type Provider struct {
|
||||||
handle providerHandle
|
handle providerHandle
|
||||||
metadata *bytes.Buffer
|
metadata *bytes.Buffer
|
||||||
@@ -23,6 +26,8 @@ type Provider struct {
|
|||||||
|
|
||||||
type providerHandle windows.Handle
|
type providerHandle windows.Handle
|
||||||
|
|
||||||
|
// EnableCallback is the form of the callback function that receives provider
|
||||||
|
// enable/disable notifications from ETW.
|
||||||
type EnableCallback func(*windows.GUID, uint32, byte, uint64, uint64, uintptr)
|
type EnableCallback func(*windows.GUID, uint32, byte, uint64, uint64, uintptr)
|
||||||
|
|
||||||
type eventDataDescriptor struct {
|
type eventDataDescriptor struct {
|
||||||
@@ -34,8 +39,9 @@ type eventDataDescriptor struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (descriptor *eventDataDescriptor) set(dataType eventDataDescriptorType, buffer *bytes.Buffer) {
|
func (descriptor *eventDataDescriptor) set(dataType eventDataDescriptorType, buffer *bytes.Buffer) {
|
||||||
// Passing a pointer to Go-managed memory as part of a block of memory is risky since the GC doesn't know about it.
|
// Passing a pointer to Go-managed memory as part of a block of memory is
|
||||||
// If we find a better way to do this we should use it instead.
|
// risky since the GC doesn't know about it. If we find a better way to do
|
||||||
|
// this we should use it instead.
|
||||||
descriptor.ptr = uint64(uintptr(unsafe.Pointer(&buffer.Bytes()[0])))
|
descriptor.ptr = uint64(uintptr(unsafe.Pointer(&buffer.Bytes()[0])))
|
||||||
descriptor.size = uint32(buffer.Len())
|
descriptor.size = uint32(buffer.Len())
|
||||||
descriptor.dataType = dataType
|
descriptor.dataType = dataType
|
||||||
@@ -56,10 +62,10 @@ func NewProvider(name string, id *windows.GUID, callback EnableCallback) (*Provi
|
|||||||
}
|
}
|
||||||
|
|
||||||
var metadataBuffer bytes.Buffer
|
var metadataBuffer bytes.Buffer
|
||||||
binary.Write(&metadataBuffer, binary.LittleEndian, uint16(0))
|
binary.Write(&metadataBuffer, binary.LittleEndian, uint16(0)) // Write empty size for buffer (to update later)
|
||||||
binary.Write(&metadataBuffer, binary.LittleEndian, []byte(name))
|
binary.Write(&metadataBuffer, binary.LittleEndian, []byte(name)) // Provider name
|
||||||
binary.Write(&metadataBuffer, binary.LittleEndian, byte(0))
|
binary.Write(&metadataBuffer, binary.LittleEndian, byte(0)) // Null terminator for name
|
||||||
binary.LittleEndian.PutUint16(metadataBuffer.Bytes(), uint16(metadataBuffer.Len()))
|
binary.LittleEndian.PutUint16(metadataBuffer.Bytes(), uint16(metadataBuffer.Len())) // Update the size at the beginning of the buffer
|
||||||
|
|
||||||
return &Provider{
|
return &Provider{
|
||||||
handle: providerHandle,
|
handle: providerHandle,
|
||||||
|
|||||||
Reference in New Issue
Block a user