in error.go [411:508]
func (b *exceptionDataBuilder) init(e *exceptionData, err error) bool {
b.errorCount++
reflectValue := reflect.ValueOf(err)
reflectType := reflectValue.Type()
switch reflectType.Kind() {
case reflect.Chan, reflect.Func, reflect.Map, reflect.Ptr, reflect.Slice, reflect.UnsafePointer:
// Prevent infinite recursion due to cyclic error causes.
ptrVal := reflectValue.Pointer()
if b.pointerErrors == nil {
b.pointerErrors = map[uintptr]struct{}{ptrVal: struct{}{}}
} else {
if _, ok := b.pointerErrors[ptrVal]; ok {
return false
}
b.pointerErrors[ptrVal] = struct{}{}
}
}
e.message = truncateString(err.Error())
if e.message == "" {
e.message = "[EMPTY]"
}
namedType := reflectType
if reflectType.Name() == "" && reflectType.Kind() == reflect.Ptr {
namedType = reflectType.Elem()
}
e.Type.Name = namedType.Name()
e.Type.PackagePath = namedType.PkgPath()
// If the error implements Type, use that to
// override the type name determined through
// reflection.
if err, ok := err.(interface {
Type() string
}); ok {
e.Type.Name = err.Type()
}
// If the error implements a Code method, use
// that to set the exception code.
switch err := err.(type) {
case interface {
Code() string
}:
e.Code.String = err.Code()
case interface {
Code() float64
}:
e.Code.Number = err.Code()
}
// If the error implements an Unwrap or Cause method, use that to set the cause error.
// Unwrap is defined by errors wrapped using fmt.Errorf, while Cause is defined by
// errors wrapped using pkg/errors.Wrap.
switch err := err.(type) {
case interface{ Unwrap() error }:
if cause := err.Unwrap(); cause != nil {
e.ErrorDetails.Cause = append(e.ErrorDetails.Cause, cause)
}
case interface{ Unwrap() []error }:
if causes := err.Unwrap(); causes != nil {
for _, cause := range causes {
if cause != nil {
e.ErrorDetails.Cause = append(e.ErrorDetails.Cause, cause)
}
}
}
case interface{ Cause() error }:
if cause := err.Cause(); cause != nil {
e.ErrorDetails.Cause = append(e.ErrorDetails.Cause, cause)
}
}
// Run registered ErrorDetailers over the error.
for _, ed := range typeErrorDetailers[reflectType] {
ed.ErrorDetails(err, &e.ErrorDetails)
}
for _, ed := range errorDetailers {
ed.ErrorDetails(err, &e.ErrorDetails)
}
e.Code.String = truncateString(e.Code.String)
e.Type.Name = truncateString(e.Type.Name)
e.Type.PackagePath = truncateString(e.Type.PackagePath)
e.stacktrace = stacktrace.AppendErrorStacktrace(e.stacktrace, err, b.stackTraceLimit)
for _, err := range e.ErrorDetails.Cause {
if b.errorCount >= maxErrorTreeNodes {
break
}
var data exceptionData
if b.init(&data, err) {
e.cause = append(e.cause, data)
}
}
return true
}