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  }