1package etw 2 3import ( 4 "math" 5 "unsafe" 6) 7 8// FieldOpt defines the option function type that can be passed to 9// Provider.WriteEvent to add fields to the event. 10type FieldOpt func(em *EventMetadata, ed *EventData) 11 12// WithFields returns the variadic arguments as a single slice. 13func WithFields(opts ...FieldOpt) []FieldOpt { 14 return opts 15} 16 17// BoolField adds a single bool field to the event. 18func BoolField(name string, value bool) FieldOpt { 19 return func(em *EventMetadata, ed *EventData) { 20 em.WriteField(name, InTypeUint8, OutTypeBoolean, 0) 21 bool8 := uint8(0) 22 if value { 23 bool8 = uint8(1) 24 } 25 ed.WriteUint8(bool8) 26 } 27} 28 29// BoolArray adds an array of bool to the event. 30func BoolArray(name string, values []bool) FieldOpt { 31 return func(em *EventMetadata, ed *EventData) { 32 em.WriteArray(name, InTypeUint8, OutTypeBoolean, 0) 33 ed.WriteUint16(uint16(len(values))) 34 for _, v := range values { 35 bool8 := uint8(0) 36 if v { 37 bool8 = uint8(1) 38 } 39 ed.WriteUint8(bool8) 40 } 41 } 42} 43 44// StringField adds a single string field to the event. 45func StringField(name string, value string) FieldOpt { 46 return func(em *EventMetadata, ed *EventData) { 47 em.WriteField(name, InTypeANSIString, OutTypeUTF8, 0) 48 ed.WriteString(value) 49 } 50} 51 52// StringArray adds an array of string to the event. 53func StringArray(name string, values []string) FieldOpt { 54 return func(em *EventMetadata, ed *EventData) { 55 em.WriteArray(name, InTypeANSIString, OutTypeUTF8, 0) 56 ed.WriteUint16(uint16(len(values))) 57 for _, v := range values { 58 ed.WriteString(v) 59 } 60 } 61} 62 63// IntField adds a single int field to the event. 64func IntField(name string, value int) FieldOpt { 65 switch unsafe.Sizeof(value) { 66 case 4: 67 return Int32Field(name, int32(value)) 68 case 8: 69 return Int64Field(name, int64(value)) 70 default: 71 panic("Unsupported int size") 72 } 73} 74 75// IntArray adds an array of int to the event. 76func IntArray(name string, values []int) FieldOpt { 77 inType := InTypeNull 78 var writeItem func(*EventData, int) 79 switch unsafe.Sizeof(values[0]) { 80 case 4: 81 inType = InTypeInt32 82 writeItem = func(ed *EventData, item int) { ed.WriteInt32(int32(item)) } 83 case 8: 84 inType = InTypeInt64 85 writeItem = func(ed *EventData, item int) { ed.WriteInt64(int64(item)) } 86 default: 87 panic("Unsupported int size") 88 } 89 90 return func(em *EventMetadata, ed *EventData) { 91 em.WriteArray(name, inType, OutTypeDefault, 0) 92 ed.WriteUint16(uint16(len(values))) 93 for _, v := range values { 94 writeItem(ed, v) 95 } 96 } 97} 98 99// Int8Field adds a single int8 field to the event. 100func Int8Field(name string, value int8) FieldOpt { 101 return func(em *EventMetadata, ed *EventData) { 102 em.WriteField(name, InTypeInt8, OutTypeDefault, 0) 103 ed.WriteInt8(value) 104 } 105} 106 107// Int8Array adds an array of int8 to the event. 108func Int8Array(name string, values []int8) FieldOpt { 109 return func(em *EventMetadata, ed *EventData) { 110 em.WriteArray(name, InTypeInt8, OutTypeDefault, 0) 111 ed.WriteUint16(uint16(len(values))) 112 for _, v := range values { 113 ed.WriteInt8(v) 114 } 115 } 116} 117 118// Int16Field adds a single int16 field to the event. 119func Int16Field(name string, value int16) FieldOpt { 120 return func(em *EventMetadata, ed *EventData) { 121 em.WriteField(name, InTypeInt16, OutTypeDefault, 0) 122 ed.WriteInt16(value) 123 } 124} 125 126// Int16Array adds an array of int16 to the event. 127func Int16Array(name string, values []int16) FieldOpt { 128 return func(em *EventMetadata, ed *EventData) { 129 em.WriteArray(name, InTypeInt16, OutTypeDefault, 0) 130 ed.WriteUint16(uint16(len(values))) 131 for _, v := range values { 132 ed.WriteInt16(v) 133 } 134 } 135} 136 137// Int32Field adds a single int32 field to the event. 138func Int32Field(name string, value int32) FieldOpt { 139 return func(em *EventMetadata, ed *EventData) { 140 em.WriteField(name, InTypeInt32, OutTypeDefault, 0) 141 ed.WriteInt32(value) 142 } 143} 144 145// Int32Array adds an array of int32 to the event. 146func Int32Array(name string, values []int32) FieldOpt { 147 return func(em *EventMetadata, ed *EventData) { 148 em.WriteArray(name, InTypeInt32, OutTypeDefault, 0) 149 ed.WriteUint16(uint16(len(values))) 150 for _, v := range values { 151 ed.WriteInt32(v) 152 } 153 } 154} 155 156// Int64Field adds a single int64 field to the event. 157func Int64Field(name string, value int64) FieldOpt { 158 return func(em *EventMetadata, ed *EventData) { 159 em.WriteField(name, InTypeInt64, OutTypeDefault, 0) 160 ed.WriteInt64(value) 161 } 162} 163 164// Int64Array adds an array of int64 to the event. 165func Int64Array(name string, values []int64) FieldOpt { 166 return func(em *EventMetadata, ed *EventData) { 167 em.WriteArray(name, InTypeInt64, OutTypeDefault, 0) 168 ed.WriteUint16(uint16(len(values))) 169 for _, v := range values { 170 ed.WriteInt64(v) 171 } 172 } 173} 174 175// UintField adds a single uint field to the event. 176func UintField(name string, value uint) FieldOpt { 177 switch unsafe.Sizeof(value) { 178 case 4: 179 return Uint32Field(name, uint32(value)) 180 case 8: 181 return Uint64Field(name, uint64(value)) 182 default: 183 panic("Unsupported uint size") 184 } 185} 186 187// UintArray adds an array of uint to the event. 188func UintArray(name string, values []uint) FieldOpt { 189 inType := InTypeNull 190 var writeItem func(*EventData, uint) 191 switch unsafe.Sizeof(values[0]) { 192 case 4: 193 inType = InTypeUint32 194 writeItem = func(ed *EventData, item uint) { ed.WriteUint32(uint32(item)) } 195 case 8: 196 inType = InTypeUint64 197 writeItem = func(ed *EventData, item uint) { ed.WriteUint64(uint64(item)) } 198 default: 199 panic("Unsupported uint size") 200 } 201 202 return func(em *EventMetadata, ed *EventData) { 203 em.WriteArray(name, inType, OutTypeDefault, 0) 204 ed.WriteUint16(uint16(len(values))) 205 for _, v := range values { 206 writeItem(ed, v) 207 } 208 } 209} 210 211// Uint8Field adds a single uint8 field to the event. 212func Uint8Field(name string, value uint8) FieldOpt { 213 return func(em *EventMetadata, ed *EventData) { 214 em.WriteField(name, InTypeUint8, OutTypeDefault, 0) 215 ed.WriteUint8(value) 216 } 217} 218 219// Uint8Array adds an array of uint8 to the event. 220func Uint8Array(name string, values []uint8) FieldOpt { 221 return func(em *EventMetadata, ed *EventData) { 222 em.WriteArray(name, InTypeUint8, OutTypeDefault, 0) 223 ed.WriteUint16(uint16(len(values))) 224 for _, v := range values { 225 ed.WriteUint8(v) 226 } 227 } 228} 229 230// Uint16Field adds a single uint16 field to the event. 231func Uint16Field(name string, value uint16) FieldOpt { 232 return func(em *EventMetadata, ed *EventData) { 233 em.WriteField(name, InTypeUint16, OutTypeDefault, 0) 234 ed.WriteUint16(value) 235 } 236} 237 238// Uint16Array adds an array of uint16 to the event. 239func Uint16Array(name string, values []uint16) FieldOpt { 240 return func(em *EventMetadata, ed *EventData) { 241 em.WriteArray(name, InTypeUint16, OutTypeDefault, 0) 242 ed.WriteUint16(uint16(len(values))) 243 for _, v := range values { 244 ed.WriteUint16(v) 245 } 246 } 247} 248 249// Uint32Field adds a single uint32 field to the event. 250func Uint32Field(name string, value uint32) FieldOpt { 251 return func(em *EventMetadata, ed *EventData) { 252 em.WriteField(name, InTypeUint32, OutTypeDefault, 0) 253 ed.WriteUint32(value) 254 } 255} 256 257// Uint32Array adds an array of uint32 to the event. 258func Uint32Array(name string, values []uint32) FieldOpt { 259 return func(em *EventMetadata, ed *EventData) { 260 em.WriteArray(name, InTypeUint32, OutTypeDefault, 0) 261 ed.WriteUint16(uint16(len(values))) 262 for _, v := range values { 263 ed.WriteUint32(v) 264 } 265 } 266} 267 268// Uint64Field adds a single uint64 field to the event. 269func Uint64Field(name string, value uint64) FieldOpt { 270 return func(em *EventMetadata, ed *EventData) { 271 em.WriteField(name, InTypeUint64, OutTypeDefault, 0) 272 ed.WriteUint64(value) 273 } 274} 275 276// Uint64Array adds an array of uint64 to the event. 277func Uint64Array(name string, values []uint64) FieldOpt { 278 return func(em *EventMetadata, ed *EventData) { 279 em.WriteArray(name, InTypeUint64, OutTypeDefault, 0) 280 ed.WriteUint16(uint16(len(values))) 281 for _, v := range values { 282 ed.WriteUint64(v) 283 } 284 } 285} 286 287// UintptrField adds a single uintptr field to the event. 288func UintptrField(name string, value uintptr) FieldOpt { 289 inType := InTypeNull 290 var writeItem func(*EventData, uintptr) 291 switch unsafe.Sizeof(value) { 292 case 4: 293 inType = InTypeHexInt32 294 writeItem = func(ed *EventData, item uintptr) { ed.WriteUint32(uint32(item)) } 295 case 8: 296 inType = InTypeHexInt64 297 writeItem = func(ed *EventData, item uintptr) { ed.WriteUint64(uint64(item)) } 298 default: 299 panic("Unsupported uintptr size") 300 } 301 302 return func(em *EventMetadata, ed *EventData) { 303 em.WriteField(name, inType, OutTypeDefault, 0) 304 writeItem(ed, value) 305 } 306} 307 308// UintptrArray adds an array of uintptr to the event. 309func UintptrArray(name string, values []uintptr) FieldOpt { 310 inType := InTypeNull 311 var writeItem func(*EventData, uintptr) 312 switch unsafe.Sizeof(values[0]) { 313 case 4: 314 inType = InTypeHexInt32 315 writeItem = func(ed *EventData, item uintptr) { ed.WriteUint32(uint32(item)) } 316 case 8: 317 inType = InTypeHexInt64 318 writeItem = func(ed *EventData, item uintptr) { ed.WriteUint64(uint64(item)) } 319 default: 320 panic("Unsupported uintptr size") 321 } 322 323 return func(em *EventMetadata, ed *EventData) { 324 em.WriteArray(name, inType, OutTypeDefault, 0) 325 ed.WriteUint16(uint16(len(values))) 326 for _, v := range values { 327 writeItem(ed, v) 328 } 329 } 330} 331 332// Float32Field adds a single float32 field to the event. 333func Float32Field(name string, value float32) FieldOpt { 334 return func(em *EventMetadata, ed *EventData) { 335 em.WriteField(name, InTypeFloat, OutTypeDefault, 0) 336 ed.WriteUint32(math.Float32bits(value)) 337 } 338} 339 340// Float32Array adds an array of float32 to the event. 341func Float32Array(name string, values []float32) FieldOpt { 342 return func(em *EventMetadata, ed *EventData) { 343 em.WriteArray(name, InTypeFloat, OutTypeDefault, 0) 344 ed.WriteUint16(uint16(len(values))) 345 for _, v := range values { 346 ed.WriteUint32(math.Float32bits(v)) 347 } 348 } 349} 350 351// Float64Field adds a single float64 field to the event. 352func Float64Field(name string, value float64) FieldOpt { 353 return func(em *EventMetadata, ed *EventData) { 354 em.WriteField(name, InTypeDouble, OutTypeDefault, 0) 355 ed.WriteUint64(math.Float64bits(value)) 356 } 357} 358 359// Float64Array adds an array of float64 to the event. 360func Float64Array(name string, values []float64) FieldOpt { 361 return func(em *EventMetadata, ed *EventData) { 362 em.WriteArray(name, InTypeDouble, OutTypeDefault, 0) 363 ed.WriteUint16(uint16(len(values))) 364 for _, v := range values { 365 ed.WriteUint64(math.Float64bits(v)) 366 } 367 } 368} 369 370// Struct adds a nested struct to the event, the FieldOpts in the opts argument 371// are used to specify the fields of the struct. 372func Struct(name string, opts ...FieldOpt) FieldOpt { 373 return func(em *EventMetadata, ed *EventData) { 374 em.WriteStruct(name, uint8(len(opts)), 0) 375 for _, opt := range opts { 376 opt(em, ed) 377 } 378 } 379} 380