github.com/Rookout/GoSDK@v0.1.48/pkg/processor/namespaces/serializer_utils.go (about) 1 package namespaces 2 3 import ( 4 "fmt" 5 "math" 6 "reflect" 7 "strconv" 8 "time" 9 "unsafe" 10 11 "github.com/Rookout/GoSDK/pkg/config" 12 "github.com/Rookout/GoSDK/pkg/logger" 13 pb "github.com/Rookout/GoSDK/pkg/protobuf" 14 "github.com/Rookout/GoSDK/pkg/rookoutErrors" 15 "github.com/Rookout/GoSDK/pkg/services/instrumentation/module" 16 ) 17 18 19 20 type hchan struct { 21 qcount uint 22 dataqsiz uint 23 buf unsafe.Pointer 24 } 25 26 type Namespace interface { 27 CallMethod(name string, args string) (Namespace, rookoutErrors.RookoutError) 28 29 WriteAttribute(name string, value Namespace) rookoutErrors.RookoutError 30 ReadAttribute(name string) (Namespace, rookoutErrors.RookoutError) 31 32 ReadKey(key interface{}) (Namespace, rookoutErrors.RookoutError) 33 GetObject() interface{} 34 Serialize(serializer Serializer) 35 } 36 37 type Serializer interface { 38 getCurrentDepth() int 39 40 dumpOriginalType(originalType string) 41 dumpType(t pb.Variant_Type) 42 dumpMaxDepth(maxDepth bool) 43 44 dumpTime(t time.Time, config config.ObjectDumpConfig) 45 dumpNamespace(getNamedValue func(i int) (string, Namespace), numOfValues int) 46 dumpTraceback(getFrame func(i int) (int, string, string), tracebackLen int) 47 dumpFunc(functionName string, filename string, lineno int) 48 dumpArray(getElem func(i int) (Namespace, bool), arrayLen int, config config.ObjectDumpConfig) 49 dumpBinary(b []byte, config config.ObjectDumpConfig) 50 dumpNil() 51 dumpUnsupported() 52 dumpRookoutError(err rookoutErrors.RookoutError) 53 dumpErrorMessage(msg string) 54 dumpEnum(desc string, ordinal int, typeName string) 55 dumpMap(getKeyValue func(i int) (Namespace, Namespace, bool), mapLen int, config config.ObjectDumpConfig) 56 dumpStruct(getField func(i int) (string, Namespace, bool), numOfFields int, config config.ObjectDumpConfig) 57 dumpInt(i int64) 58 dumpFloat(f float64) 59 dumpComplex(c complex128) 60 dumpBool(b bool) 61 dumpString(s string, config config.ObjectDumpConfig) 62 dumpStringLen(stringLen int) 63 dumpChan(value reflect.Value, config config.ObjectDumpConfig) 64 } 65 66 func dumpValue(s Serializer, value reflect.Value, config config.ObjectDumpConfig) { 67 defer func() { 68 defer func() { 69 recover() 70 }() 71 72 73 s.dumpOriginalType(value.Type().String()) 74 }() 75 s.dumpMaxDepth(s.getCurrentDepth() >= config.MaxDepth) 76 77 if !value.IsValid() { 78 s.dumpNil() 79 return 80 } 81 82 switch value.Kind() { 83 case reflect.Chan, reflect.Ptr, reflect.Array, reflect.Map, reflect.Slice, reflect.Func: 84 if value.IsNil() { 85 dumpUint(s, uint64(value.Pointer()), config) 86 return 87 } 88 } 89 90 switch value.Type() { 91 case reflect.TypeOf(time.Time{}): 92 dumpTimeValue(s, value, config) 93 return 94 case reflect.TypeOf(fmt.Errorf("")), reflect.TypeOf(&rookoutErrors.RookoutErrorImpl{}): 95 dumpErrorValue(s, value) 96 return 97 case reflect.TypeOf([]byte{}): 98 dumpBinaryValue(s, value, config) 99 return 100 } 101 102 switch value.Kind() { 103 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 104 s.dumpInt(value.Int()) 105 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: 106 dumpUint(s, value.Uint(), config) 107 case reflect.UnsafePointer: 108 dumpUint(s, value.Addr().Uint(), config) 109 case reflect.Float32, reflect.Float64: 110 s.dumpFloat(value.Float()) 111 case reflect.Complex64, reflect.Complex128: 112 s.dumpComplex(value.Complex()) 113 case reflect.String: 114 s.dumpString(value.String(), config) 115 case reflect.Bool: 116 s.dumpBool(value.Bool()) 117 case reflect.Struct: 118 dumpStructValue(s, value, config) 119 case reflect.Array, reflect.Slice: 120 dumpArrayValue(s, value, config) 121 case reflect.Map: 122 dumpMapValue(s, value, config) 123 case reflect.Ptr: 124 dumpValue(s, value.Elem(), config) 125 case reflect.Interface: 126 dumpValue(s, value.Elem(), config) 127 case reflect.Chan: 128 s.dumpChan(value, config) 129 case reflect.Func: 130 dumpFuncValue(s, value) 131 case reflect.Invalid: 132 s.dumpErrorMessage(fmt.Sprintf("Failed to dump type: %s", value.Type().String())) 133 default: 134 135 logger.Logger().Fatalf("Unknown kind: %s, type: %s", value.Kind().String(), value.Type().String()) 136 } 137 } 138 139 func dumpInterface(s Serializer, obj interface{}, config config.ObjectDumpConfig) { 140 if nil == obj { 141 s.dumpNil() 142 return 143 } 144 145 dumpValue(s, reflect.ValueOf(obj), config) 146 } 147 148 func dumpUint(s Serializer, u uint64, config config.ObjectDumpConfig) { 149 if u < math.MaxInt64 { 150 s.dumpInt(int64(u)) 151 } else { 152 s.dumpString(strconv.FormatUint(u, 10), config) 153 s.dumpType(pb.Variant_VARIANT_LARGE_INT) 154 } 155 } 156 157 var unixTimeMethod = func() reflect.Value { 158 f, _ := reflect.TypeOf(time.Time{}).MethodByName("Unix") 159 return f.Func 160 }() 161 var nsecTimeMethod = func() reflect.Value { 162 f, _ := reflect.TypeOf(time.Time{}).MethodByName("Nanosecond") 163 return f.Func 164 }() 165 166 func getTime(value reflect.Value) (t time.Time) { 167 i := func() (i interface{}) { 168 defer func() { 169 170 if recover() != nil { 171 unix := unixTimeMethod.Call([]reflect.Value{value})[0].Int() 172 nsec := nsecTimeMethod.Call([]reflect.Value{value})[0].Int() 173 i = time.Unix(unix, nsec) 174 } 175 }() 176 177 return value.Interface() 178 }() 179 180 if t, ok := i.(time.Time); ok { 181 return t 182 } 183 if t, ok := i.(*time.Time); ok { 184 return *t 185 } 186 return time.Time{} 187 } 188 189 func dumpTimeValue(s Serializer, value reflect.Value, config config.ObjectDumpConfig) { 190 s.dumpTime(getTime(value), config) 191 } 192 193 func dumpArrayValue(s Serializer, value reflect.Value, config config.ObjectDumpConfig) { 194 getElem := func(i int) (n Namespace, ok bool) { 195 defer func() { 196 if recover() != nil { 197 n = NewValueNamespace(value.Index(i)) 198 } 199 }() 200 v := reflect.NewAt(value.Type().Elem(), unsafe.Pointer(value.Index(i).Addr().Pointer())) 201 return NewGoObjectNamespace(v.Elem().Interface()), true 202 } 203 s.dumpArray(getElem, value.Len(), config) 204 } 205 206 func dumpBinaryValue(s Serializer, value reflect.Value, config config.ObjectDumpConfig) { 207 b := make([]byte, value.Len()) 208 for i := range b { 209 if i > config.MaxString { 210 break 211 } 212 213 b[i] = *(*byte)(unsafe.Pointer(value.Pointer() + uintptr(i))) 214 } 215 s.dumpBinary(b, config) 216 } 217 218 func dumpStructValue(s Serializer, value reflect.Value, config config.ObjectDumpConfig) { 219 numOfFields := value.NumField() 220 getField := func(i int) (string, Namespace, bool) { 221 fieldName := value.Type().Field(i).Name 222 fieldValue := NewValueNamespace(value.Field(i)) 223 return fieldName, fieldValue, true 224 } 225 s.dumpStruct(getField, numOfFields, config) 226 } 227 228 func dumpMapValue(s Serializer, value reflect.Value, config config.ObjectDumpConfig) { 229 mapKeys := value.MapKeys() 230 getKeyValue := func(i int) (Namespace, Namespace, bool) { 231 key := NewGoObjectNamespace(mapKeys[i].Interface()) 232 value := NewGoObjectNamespace(value.MapIndex(mapKeys[i]).Interface()) 233 return key, value, true 234 } 235 236 s.dumpMap(getKeyValue, value.Len(), config) 237 } 238 239 func dumpFuncValue(s Serializer, value reflect.Value) { 240 funcAddr := value.Pointer() 241 funcInfo := module.FindFunc(funcAddr) 242 functionName := module.FuncName(funcInfo) 243 244 245 s.dumpFunc(functionName, "", 0) 246 } 247 248 func dumpError(s Serializer, err error) { 249 if r, ok := err.(rookoutErrors.RookoutError); ok { 250 s.dumpRookoutError(r) 251 return 252 } 253 s.dumpErrorMessage(err.Error()) 254 } 255 256 func dumpErrorValue(s Serializer, value reflect.Value) { 257 if value.Type() == reflect.TypeOf(&rookoutErrors.RookoutErrorImpl{}) { 258 value = value.Elem() 259 } 260 261 if value.Type() == reflect.TypeOf(rookoutErrors.RookoutErrorImpl{}) { 262 err := &rookoutErrors.RookoutErrorImpl{ 263 ExternalError: value.FieldByName("ExternalError").Interface().(error), 264 Type: value.FieldByName("Type").Interface().(string), 265 Arguments: value.FieldByName("Arguments").Interface().(map[string]interface{}), 266 } 267 dumpError(s, err) 268 return 269 } 270 271 errorFunc := value.MethodByName("Error") 272 if !errorFunc.IsValid() { 273 s.dumpNil() 274 return 275 } 276 msg := errorFunc.Call([]reflect.Value{})[0] 277 s.dumpErrorMessage(msg.String()) 278 }