mirror of
https://github.com/rwinkhart/go-winio.git
synced 2026-09-06 00:57:19 -04:00
Move smart ETW field logging to base etw library
This commit is contained in:
@@ -1,7 +1,9 @@
|
|||||||
package etw
|
package etw
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"math"
|
"math"
|
||||||
|
"reflect"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -377,3 +379,124 @@ func Struct(name string, opts ...FieldOpt) FieldOpt {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Currently, we support logging basic builtin types (int, string, etc), slices
|
||||||
|
// of basic builtin types, error, types derived from the basic types (e.g. "type
|
||||||
|
// foo int"), and structs (recursively logging their fields). We do not support
|
||||||
|
// slices of derived types (e.g. "[]foo").
|
||||||
|
//
|
||||||
|
// For types that we don't support, the value is formatted via fmt.Sprint, and
|
||||||
|
// we also log a message that the type is unsupported along with the formatted
|
||||||
|
// type. The intent of this is to make it easier to see which types are not
|
||||||
|
// supported in traces, so we can evaluate adding support for more types in the
|
||||||
|
// future.
|
||||||
|
func SmartField(name string, v interface{}) FieldOpt {
|
||||||
|
switch v := v.(type) {
|
||||||
|
case bool:
|
||||||
|
return BoolField(name, v)
|
||||||
|
case []bool:
|
||||||
|
return BoolArray(name, v)
|
||||||
|
case string:
|
||||||
|
return StringField(name, v)
|
||||||
|
case []string:
|
||||||
|
return StringArray(name, v)
|
||||||
|
case int:
|
||||||
|
return IntField(name, v)
|
||||||
|
case []int:
|
||||||
|
return IntArray(name, v)
|
||||||
|
case int8:
|
||||||
|
return Int8Field(name, v)
|
||||||
|
case []int8:
|
||||||
|
return Int8Array(name, v)
|
||||||
|
case int16:
|
||||||
|
return Int16Field(name, v)
|
||||||
|
case []int16:
|
||||||
|
return Int16Array(name, v)
|
||||||
|
case int32:
|
||||||
|
return Int32Field(name, v)
|
||||||
|
case []int32:
|
||||||
|
return Int32Array(name, v)
|
||||||
|
case int64:
|
||||||
|
return Int64Field(name, v)
|
||||||
|
case []int64:
|
||||||
|
return Int64Array(name, v)
|
||||||
|
case uint:
|
||||||
|
return UintField(name, v)
|
||||||
|
case []uint:
|
||||||
|
return UintArray(name, v)
|
||||||
|
case uint8:
|
||||||
|
return Uint8Field(name, v)
|
||||||
|
case []uint8:
|
||||||
|
return Uint8Array(name, v)
|
||||||
|
case uint16:
|
||||||
|
return Uint16Field(name, v)
|
||||||
|
case []uint16:
|
||||||
|
return Uint16Array(name, v)
|
||||||
|
case uint32:
|
||||||
|
return Uint32Field(name, v)
|
||||||
|
case []uint32:
|
||||||
|
return Uint32Array(name, v)
|
||||||
|
case uint64:
|
||||||
|
return Uint64Field(name, v)
|
||||||
|
case []uint64:
|
||||||
|
return Uint64Array(name, v)
|
||||||
|
case uintptr:
|
||||||
|
return UintptrField(name, v)
|
||||||
|
case []uintptr:
|
||||||
|
return UintptrArray(name, v)
|
||||||
|
case float32:
|
||||||
|
return Float32Field(name, v)
|
||||||
|
case []float32:
|
||||||
|
return Float32Array(name, v)
|
||||||
|
case float64:
|
||||||
|
return Float64Field(name, v)
|
||||||
|
case []float64:
|
||||||
|
return Float64Array(name, v)
|
||||||
|
case error:
|
||||||
|
return StringField(name, v.Error())
|
||||||
|
default:
|
||||||
|
switch rv := reflect.ValueOf(v); rv.Kind() {
|
||||||
|
case reflect.Bool:
|
||||||
|
return SmartField(name, rv.Bool())
|
||||||
|
case reflect.Int:
|
||||||
|
return SmartField(name, int(rv.Int()))
|
||||||
|
case reflect.Int8:
|
||||||
|
return SmartField(name, int8(rv.Int()))
|
||||||
|
case reflect.Int16:
|
||||||
|
return SmartField(name, int16(rv.Int()))
|
||||||
|
case reflect.Int32:
|
||||||
|
return SmartField(name, int32(rv.Int()))
|
||||||
|
case reflect.Int64:
|
||||||
|
return SmartField(name, int64(rv.Int()))
|
||||||
|
case reflect.Uint:
|
||||||
|
return SmartField(name, uint(rv.Uint()))
|
||||||
|
case reflect.Uint8:
|
||||||
|
return SmartField(name, uint8(rv.Uint()))
|
||||||
|
case reflect.Uint16:
|
||||||
|
return SmartField(name, uint16(rv.Uint()))
|
||||||
|
case reflect.Uint32:
|
||||||
|
return SmartField(name, uint32(rv.Uint()))
|
||||||
|
case reflect.Uint64:
|
||||||
|
return SmartField(name, uint64(rv.Uint()))
|
||||||
|
case reflect.Uintptr:
|
||||||
|
return SmartField(name, uintptr(rv.Uint()))
|
||||||
|
case reflect.Float32:
|
||||||
|
return SmartField(name, float32(rv.Float()))
|
||||||
|
case reflect.Float64:
|
||||||
|
return SmartField(name, float64(rv.Float()))
|
||||||
|
case reflect.String:
|
||||||
|
return SmartField(name, rv.String())
|
||||||
|
case reflect.Struct:
|
||||||
|
fields := make([]FieldOpt, 0, rv.NumField())
|
||||||
|
for i := 0; i < rv.NumField(); i++ {
|
||||||
|
field := rv.Field(i)
|
||||||
|
if field.CanInterface() {
|
||||||
|
fields = append(fields, SmartField(name, field.Interface()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Struct(name, fields...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return StringField(name, fmt.Sprintf("(Unsupported: %T) %v", v, v))
|
||||||
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/Microsoft/go-winio/internal/etw"
|
"github.com/Microsoft/go-winio/pkg/etw"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
|
|
||||||
"golang.org/x/sys/windows"
|
"golang.org/x/sys/windows"
|
||||||
|
|||||||
+1
-125
@@ -1,9 +1,6 @@
|
|||||||
package etwlogrus
|
package etwlogrus
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"reflect"
|
|
||||||
|
|
||||||
"github.com/Microsoft/go-winio/pkg/etw"
|
"github.com/Microsoft/go-winio/pkg/etw"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
@@ -71,7 +68,7 @@ func (h *Hook) Fire(e *logrus.Entry) error {
|
|||||||
fields = append(fields, etw.StringField("Message", e.Message))
|
fields = append(fields, etw.StringField("Message", e.Message))
|
||||||
|
|
||||||
for k, v := range e.Data {
|
for k, v := range e.Data {
|
||||||
fields = append(fields, getFieldOpt(k, v))
|
fields = append(fields, etw.SmartField(k, v))
|
||||||
}
|
}
|
||||||
|
|
||||||
return h.provider.WriteEvent(
|
return h.provider.WriteEvent(
|
||||||
@@ -80,127 +77,6 @@ func (h *Hook) Fire(e *logrus.Entry) error {
|
|||||||
fields)
|
fields)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Currently, we support logging basic builtin types (int, string, etc), slices
|
|
||||||
// of basic builtin types, error, types derived from the basic types (e.g. "type
|
|
||||||
// foo int"), and structs (recursively logging their fields). We do not support
|
|
||||||
// slices of derived types (e.g. "[]foo").
|
|
||||||
//
|
|
||||||
// For types that we don't support, the value is formatted via fmt.Sprint, and
|
|
||||||
// we also log a message that the type is unsupported along with the formatted
|
|
||||||
// type. The intent of this is to make it easier to see which types are not
|
|
||||||
// supported in traces, so we can evaluate adding support for more types in the
|
|
||||||
// future.
|
|
||||||
func getFieldOpt(k string, v interface{}) etw.FieldOpt {
|
|
||||||
switch v := v.(type) {
|
|
||||||
case bool:
|
|
||||||
return etw.BoolField(k, v)
|
|
||||||
case []bool:
|
|
||||||
return etw.BoolArray(k, v)
|
|
||||||
case string:
|
|
||||||
return etw.StringField(k, v)
|
|
||||||
case []string:
|
|
||||||
return etw.StringArray(k, v)
|
|
||||||
case int:
|
|
||||||
return etw.IntField(k, v)
|
|
||||||
case []int:
|
|
||||||
return etw.IntArray(k, v)
|
|
||||||
case int8:
|
|
||||||
return etw.Int8Field(k, v)
|
|
||||||
case []int8:
|
|
||||||
return etw.Int8Array(k, v)
|
|
||||||
case int16:
|
|
||||||
return etw.Int16Field(k, v)
|
|
||||||
case []int16:
|
|
||||||
return etw.Int16Array(k, v)
|
|
||||||
case int32:
|
|
||||||
return etw.Int32Field(k, v)
|
|
||||||
case []int32:
|
|
||||||
return etw.Int32Array(k, v)
|
|
||||||
case int64:
|
|
||||||
return etw.Int64Field(k, v)
|
|
||||||
case []int64:
|
|
||||||
return etw.Int64Array(k, v)
|
|
||||||
case uint:
|
|
||||||
return etw.UintField(k, v)
|
|
||||||
case []uint:
|
|
||||||
return etw.UintArray(k, v)
|
|
||||||
case uint8:
|
|
||||||
return etw.Uint8Field(k, v)
|
|
||||||
case []uint8:
|
|
||||||
return etw.Uint8Array(k, v)
|
|
||||||
case uint16:
|
|
||||||
return etw.Uint16Field(k, v)
|
|
||||||
case []uint16:
|
|
||||||
return etw.Uint16Array(k, v)
|
|
||||||
case uint32:
|
|
||||||
return etw.Uint32Field(k, v)
|
|
||||||
case []uint32:
|
|
||||||
return etw.Uint32Array(k, v)
|
|
||||||
case uint64:
|
|
||||||
return etw.Uint64Field(k, v)
|
|
||||||
case []uint64:
|
|
||||||
return etw.Uint64Array(k, v)
|
|
||||||
case uintptr:
|
|
||||||
return etw.UintptrField(k, v)
|
|
||||||
case []uintptr:
|
|
||||||
return etw.UintptrArray(k, v)
|
|
||||||
case float32:
|
|
||||||
return etw.Float32Field(k, v)
|
|
||||||
case []float32:
|
|
||||||
return etw.Float32Array(k, v)
|
|
||||||
case float64:
|
|
||||||
return etw.Float64Field(k, v)
|
|
||||||
case []float64:
|
|
||||||
return etw.Float64Array(k, v)
|
|
||||||
case error:
|
|
||||||
return etw.StringField(k, v.Error())
|
|
||||||
default:
|
|
||||||
switch rv := reflect.ValueOf(v); rv.Kind() {
|
|
||||||
case reflect.Bool:
|
|
||||||
return getFieldOpt(k, rv.Bool())
|
|
||||||
case reflect.Int:
|
|
||||||
return getFieldOpt(k, int(rv.Int()))
|
|
||||||
case reflect.Int8:
|
|
||||||
return getFieldOpt(k, int8(rv.Int()))
|
|
||||||
case reflect.Int16:
|
|
||||||
return getFieldOpt(k, int16(rv.Int()))
|
|
||||||
case reflect.Int32:
|
|
||||||
return getFieldOpt(k, int32(rv.Int()))
|
|
||||||
case reflect.Int64:
|
|
||||||
return getFieldOpt(k, int64(rv.Int()))
|
|
||||||
case reflect.Uint:
|
|
||||||
return getFieldOpt(k, uint(rv.Uint()))
|
|
||||||
case reflect.Uint8:
|
|
||||||
return getFieldOpt(k, uint8(rv.Uint()))
|
|
||||||
case reflect.Uint16:
|
|
||||||
return getFieldOpt(k, uint16(rv.Uint()))
|
|
||||||
case reflect.Uint32:
|
|
||||||
return getFieldOpt(k, uint32(rv.Uint()))
|
|
||||||
case reflect.Uint64:
|
|
||||||
return getFieldOpt(k, uint64(rv.Uint()))
|
|
||||||
case reflect.Uintptr:
|
|
||||||
return getFieldOpt(k, uintptr(rv.Uint()))
|
|
||||||
case reflect.Float32:
|
|
||||||
return getFieldOpt(k, float32(rv.Float()))
|
|
||||||
case reflect.Float64:
|
|
||||||
return getFieldOpt(k, float64(rv.Float()))
|
|
||||||
case reflect.String:
|
|
||||||
return getFieldOpt(k, rv.String())
|
|
||||||
case reflect.Struct:
|
|
||||||
fields := make([]etw.FieldOpt, 0, rv.NumField())
|
|
||||||
for i := 0; i < rv.NumField(); i++ {
|
|
||||||
field := rv.Field(i)
|
|
||||||
if field.CanInterface() {
|
|
||||||
fields = append(fields, getFieldOpt(k, field.Interface()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return etw.Struct(k, fields...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return etw.StringField(k, fmt.Sprintf("(Unsupported: %T) %v", v, v))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Close cleans up the hook and closes the ETW provider. If the provder was
|
// Close cleans up the hook and closes the ETW provider. If the provder was
|
||||||
// registered by etwlogrus, it will be closed as part of `Close`. If the
|
// registered by etwlogrus, it will be closed as part of `Close`. If the
|
||||||
// provider was passed in, it will not be closed.
|
// provider was passed in, it will not be closed.
|
||||||
|
|||||||
Reference in New Issue
Block a user