github.com/Rookout/GoSDK@v0.1.48/pkg/processor/namespaces/namespace_serializer.go (about) 1 package namespaces 2 3 import ( 4 "reflect" 5 "time" 6 "unicode/utf8" 7 "unsafe" 8 9 "github.com/Rookout/GoSDK/pkg/config" 10 pb "github.com/Rookout/GoSDK/pkg/protobuf" 11 "github.com/Rookout/GoSDK/pkg/rookoutErrors" 12 "github.com/Rookout/GoSDK/pkg/utils" 13 "google.golang.org/protobuf/types/known/timestamppb" 14 ) 15 16 type NamespaceSerializer struct { 17 *pb.Variant 18 logErrors bool 19 currentDepth int 20 } 21 22 func NewNamespaceSerializer(fromNamespace Namespace, logErrors bool) *NamespaceSerializer { 23 g := &NamespaceSerializer{Variant: &pb.Variant{}, logErrors: logErrors} 24 fromNamespace.Serialize(g) 25 return g 26 } 27 28 func (n *NamespaceSerializer) getCurrentDepth() int { 29 return n.currentDepth 30 } 31 32 func (n *NamespaceSerializer) spawn(fromNamespace Namespace) *NamespaceSerializer { 33 spawned := &NamespaceSerializer{Variant: &pb.Variant{}, logErrors: n.logErrors, currentDepth: n.currentDepth + 1} 34 35 fromNamespace.Serialize(spawned) 36 return spawned 37 } 38 39 func (n *NamespaceSerializer) spawnAtSameDepth(fromNamespace Namespace) *NamespaceSerializer { 40 spawned := &NamespaceSerializer{Variant: &pb.Variant{}, logErrors: n.logErrors, currentDepth: n.currentDepth} 41 fromNamespace.Serialize(spawned) 42 return spawned 43 } 44 45 func (n *NamespaceSerializer) dumpOriginalType(originalType string) { 46 n.OriginalType = originalType 47 } 48 49 func (n *NamespaceSerializer) dumpType(variantType pb.Variant_Type) { 50 n.VariantType = variantType 51 } 52 53 func (n *NamespaceSerializer) dumpMaxDepth(maxDepth bool) { 54 n.MaxDepth = maxDepth 55 } 56 57 func (n *NamespaceSerializer) dumpComplex(c complex128) { 58 n.dumpType(pb.Variant_VARIANT_COMPLEX) 59 n.Value = &pb.Variant_ComplexValue{ComplexValue: &pb.Variant_Complex{Real: float64(real(c)), Imaginary: float64(imag(c))}} 60 } 61 62 func (n *NamespaceSerializer) dumpFloat(f float64) { 63 n.dumpType(pb.Variant_VARIANT_DOUBLE) 64 n.Value = &pb.Variant_DoubleValue{DoubleValue: float64(f)} 65 } 66 67 func (n *NamespaceSerializer) dumpString(s string, config config.ObjectDumpConfig) { 68 if !utf8.ValidString(s) { 69 n.dumpBinary([]byte(s), config) 70 return 71 } 72 73 n.dumpType(pb.Variant_VARIANT_STRING) 74 originalSize := len(s) 75 if len(s) > config.MaxString { 76 s = s[:config.MaxString] 77 } 78 n.Value = &pb.Variant_StringValue{ 79 StringValue: &pb.Variant_String{ 80 OriginalSize: int32(originalSize), 81 Value: s, 82 }, 83 } 84 } 85 86 func (n *NamespaceSerializer) dumpStringLen(stringLen int) { 87 if _, ok := n.Value.(*pb.Variant_StringValue); ok { 88 n.Value.(*pb.Variant_StringValue).StringValue.OriginalSize = int32(stringLen) 89 } 90 if _, ok := n.Value.(*pb.Variant_BinaryValue); ok { 91 n.Value.(*pb.Variant_BinaryValue).BinaryValue.OriginalSize = int32(stringLen) 92 } 93 } 94 95 func (n *NamespaceSerializer) dumpEnum(desc string, ordinal int, typeName string) { 96 n.dumpType(pb.Variant_VARIANT_ENUM) 97 n.Value = &pb.Variant_EnumValue{EnumValue: &pb.Variant_Enumeration{ 98 StringValue: desc, 99 OrdinalValue: int32(ordinal), 100 TypeName: typeName, 101 }} 102 } 103 104 func (n *NamespaceSerializer) dumpBinary(b []byte, config config.ObjectDumpConfig) { 105 n.dumpType(pb.Variant_VARIANT_BINARY) 106 originalSize := len(b) 107 if len(b) > config.MaxString { 108 b = b[:config.MaxString] 109 } 110 n.Value = &pb.Variant_BinaryValue{ 111 BinaryValue: &pb.Variant_Binary{ 112 OriginalSize: int32(originalSize), 113 Value: b, 114 }, 115 } 116 } 117 118 func (n *NamespaceSerializer) dumpInt(i int64) { 119 n.dumpType(pb.Variant_VARIANT_LONG) 120 n.Value = &pb.Variant_LongValue{LongValue: i} 121 } 122 123 func (n *NamespaceSerializer) dumpBool(b bool) { 124 n.dumpType(pb.Variant_VARIANT_INT) 125 boolAsInt := int32(0) 126 if b { 127 boolAsInt = 1 128 } 129 n.Value = &pb.Variant_IntValue{IntValue: boolAsInt} 130 } 131 132 func (n *NamespaceSerializer) dumpTime(t time.Time, config config.ObjectDumpConfig) { 133 n.dumpType(pb.Variant_VARIANT_TIME) 134 n.Value = &pb.Variant_TimeValue{ 135 TimeValue: ×tamppb.Timestamp{ 136 Seconds: t.Unix(), 137 Nanos: (int32)(t.Nanosecond()), 138 }, 139 } 140 } 141 142 func (n *NamespaceSerializer) dumpArray(getElem func(i int) (Namespace, bool), arrayLen int, config config.ObjectDumpConfig) { 143 n.dumpType(pb.Variant_VARIANT_LIST) 144 if n.getCurrentDepth() >= config.MaxCollectionDepth { 145 n.dumpMaxDepth(true) 146 return 147 } 148 149 listVariant := &pb.Variant_List{ 150 Type: "list", 151 OriginalSize: int32(arrayLen), 152 } 153 154 for i := 0; i < arrayLen; i++ { 155 if i >= config.MaxWidth { 156 break 157 } 158 159 e, ok := getElem(i) 160 if !ok { 161 break 162 } 163 164 listVariant.Values = append(listVariant.Values, n.spawn(e).Variant) 165 } 166 n.Value = &pb.Variant_ListValue{ListValue: listVariant} 167 } 168 169 func (n *NamespaceSerializer) dumpUnsupported() { 170 n.dumpType(pb.Variant_VARIANT_UKNOWN_OBJECT) 171 } 172 173 func (n *NamespaceSerializer) dumpStruct(getField func(i int) (string, Namespace, bool), numOfFields int, config config.ObjectDumpConfig) { 174 n.dumpType(pb.Variant_VARIANT_OBJECT) 175 176 if n.getCurrentDepth()+1 >= config.MaxDepth { 177 n.dumpMaxDepth(true) 178 return 179 } 180 181 n.Attributes = make([]*pb.Variant_NamedValue, 0, numOfFields) 182 for i := 0; i < numOfFields; i++ { 183 fieldName, fieldValue, ok := getField(i) 184 if !ok { 185 continue 186 } 187 n.Attributes = append(n.Attributes, &pb.Variant_NamedValue{Name: fieldName, Value: n.spawn(fieldValue).Variant}) 188 } 189 } 190 191 func (n *NamespaceSerializer) dumpMap(getKeyValue func(i int) (Namespace, Namespace, bool), mapLen int, config config.ObjectDumpConfig) { 192 n.dumpType(pb.Variant_VARIANT_MAP) 193 if n.getCurrentDepth() >= config.MaxCollectionDepth { 194 n.dumpMaxDepth(true) 195 return 196 } 197 198 pairs := make([]*pb.Variant_Pair, 0) 199 for i := 0; i < mapLen; i++ { 200 if len(pairs) >= config.MaxWidth { 201 break 202 } 203 204 key, value, ok := getKeyValue(i) 205 if !ok { 206 continue 207 } 208 pairs = append(pairs, &pb.Variant_Pair{ 209 First: n.spawn(key).Variant, 210 Second: n.spawn(value).Variant, 211 }) 212 } 213 214 n.Value = &pb.Variant_MapValue{ 215 MapValue: &pb.Variant_Map{ 216 OriginalSize: int32(mapLen), 217 Pairs: pairs, 218 }, 219 } 220 } 221 222 func (n *NamespaceSerializer) dumpNil() { 223 n.dumpType(pb.Variant_VARIANT_NONE) 224 } 225 226 func (n *NamespaceSerializer) dumpFunc(functionName string, filename string, lineno int) { 227 n.dumpType(pb.Variant_VARIANT_CODE_OBJECT) 228 n.Value = &pb.Variant_CodeValue{ 229 CodeValue: &pb.Variant_CodeObject{ 230 Name: functionName, 231 Filename: filename, 232 Lineno: uint32(lineno), 233 }, 234 } 235 } 236 237 func (n *NamespaceSerializer) dumpChan(value reflect.Value, config config.ObjectDumpConfig) { 238 n.dumpType(pb.Variant_VARIANT_LIST) 239 240 if n.getCurrentDepth() >= config.MaxCollectionDepth { 241 n.dumpMaxDepth(true) 242 return 243 } 244 245 addr := utils.UnsafePointer(value) 246 chanStruct := *(*hchan)(addr) 247 elemType := value.Type().Elem() 248 bufSize := value.Len() * int(elemType.Size()) 249 250 listVariant := &pb.Variant_List{ 251 Type: "list", 252 OriginalSize: int32(value.Len()), 253 } 254 255 for i := 0; i < bufSize; i += int(elemType.Size()) { 256 if len(listVariant.Values) >= config.MaxWidth { 257 break 258 } 259 260 ptr := unsafe.Pointer(uintptr(chanStruct.buf) + uintptr(i)) 261 val := reflect.NewAt(elemType, ptr).Elem() 262 valVariant := &NamespaceSerializer{Variant: &pb.Variant{}, logErrors: n.logErrors, currentDepth: n.currentDepth + 1} 263 dumpValue(valVariant, val, config) 264 listVariant.Values = append(listVariant.Values, valVariant.Variant) 265 } 266 n.Value = &pb.Variant_ListValue{ListValue: listVariant} 267 } 268 269 func (n *NamespaceSerializer) dumpRookoutError(r rookoutErrors.RookoutError) { 270 n.dumpType(pb.Variant_VARIANT_ERROR) 271 272 stackFramesObj := NewGoObjectNamespace(string(r.Stack())) 273 stackFramesObj.ObjectDumpConf = config.TailorObjectDumpConfig(reflect.String, len(r.Stack())) 274 275 n.Value = &pb.Variant_ErrorValue{ 276 ErrorValue: &pb.Error{ 277 Message: r.Error(), 278 Type: r.GetType(), 279 Parameters: n.spawn(NewGoObjectNamespace(r.GetArguments())).Variant, 280 Traceback: n.spawn(stackFramesObj).Variant, 281 }, 282 } 283 } 284 285 func (n *NamespaceSerializer) dumpErrorMessage(msg string) { 286 n.dumpType(pb.Variant_VARIANT_ERROR) 287 n.Value = &pb.Variant_ErrorValue{ 288 ErrorValue: &pb.Error{ 289 Message: msg, 290 }, 291 } 292 } 293 294 func (n *NamespaceSerializer) dumpNamespace(getNamedValue func(i int) (string, Namespace), numOfValues int) { 295 n.dumpType(pb.Variant_VARIANT_NAMESPACE) 296 297 if n.MaxDepth { 298 return 299 } 300 301 attributes := make([]*pb.Variant_NamedValue, 0, numOfValues) 302 for i := 0; i < numOfValues; i++ { 303 name, value := getNamedValue(i) 304 attributes = append(attributes, &pb.Variant_NamedValue{ 305 Name: name, 306 Value: n.spawnAtSameDepth(value).Variant, 307 }) 308 } 309 n.Value = &pb.Variant_NamespaceValue{ 310 NamespaceValue: &pb.Variant_Namespace{ 311 Attributes: attributes, 312 }, 313 } 314 } 315 316 func (n *NamespaceSerializer) dumpTraceback(getFrame func(i int) (int, string, string), tracebackLen int) { 317 n.dumpType(pb.Variant_VARIANT_TRACEBACK) 318 319 tracebackVariant := &pb.Variant_Traceback{} 320 for i := 0; i < tracebackLen; i++ { 321 lineno, filename, functionName := getFrame(i) 322 tracebackVariant.Locations = append(tracebackVariant.Locations, &pb.Variant_CodeObject{ 323 Lineno: uint32(lineno), 324 Filename: filename, 325 Name: functionName, 326 Module: filename, 327 }) 328 } 329 330 n.Value = &pb.Variant_Traceback_{ 331 Traceback: tracebackVariant, 332 } 333 }