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: &timestamppb.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  }