github.com/jurado-dev/errors@v1.2.10/error.go (about)

     1  package errors
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"regexp"
     7  	"runtime"
     8  )
     9  
    10  type Err struct {
    11  	Cause        string     `json:"cause"`
    12  	Message      string     `json:"message"`
    13  	StackMessage string     `json:"stack_message"`
    14  	Trace        ErrTrace   `json:"trace"`
    15  	Stack        []ErrTrace `json:"stack"`
    16  	Wrapped      error      `json:"-"`
    17  	Code         int        `json:"code"`
    18  }
    19  
    20  type ErrTrace struct {
    21  	File     string `json:"file"`
    22  	Function string `json:"function"`
    23  	Line     int    `json:"line"`
    24  }
    25  
    26  //	Error implements the interface
    27  func (e *Err) Error() string {
    28  
    29  	output := fmt.Sprintf("Info: %s", e.Message)
    30  	if e.Trace.Line != 0 {
    31  
    32  		cause := e.Cause
    33  		if len(cause) > 200 {
    34  			cause = cause[:200] + "..."
    35  		}
    36  
    37  		output = fmt.Sprintf("Cause: %s | Info: %s | Line: %d | Function: %s", cause, e.Message, e.Trace.Line, e.Trace.Function)
    38  	}
    39  
    40  	return output
    41  }
    42  
    43  func extractErr(err error) Err {
    44  
    45  	switch e := err.(type) {
    46  	case *Internal:
    47  		return e.Err
    48  	case *NotFound:
    49  		return e.Err
    50  	case *Conflict:
    51  		return e.Err
    52  	case *BadRequest:
    53  		return e.Err
    54  	case *Unauthorized:
    55  		return e.Err
    56  	case *Fatal:
    57  		return e.Err
    58  	case *NoContent:
    59  		return e.Err
    60  	case *Timeout:
    61  		return e.Err
    62  	}
    63  
    64  	return Err{}
    65  }
    66  
    67  //	Stack adds a trace to the stack slice
    68  func Stack(err error, trace ErrTrace) error {
    69  
    70  	if err == nil {
    71  		return err
    72  	}
    73  
    74  	switch e := err.(type) {
    75  	case *Internal:
    76  		e.Err.Stack = append(e.Err.Stack, trace)
    77  		return e
    78  	case *NotFound:
    79  		e.Err.Stack = append(e.Err.Stack, trace)
    80  		return e
    81  	case *Conflict:
    82  		e.Err.Stack = append(e.Err.Stack, trace)
    83  		return e
    84  	case *BadRequest:
    85  		e.Err.Stack = append(e.Err.Stack, trace)
    86  		return e
    87  	case *Unauthorized:
    88  		e.Err.Stack = append(e.Err.Stack, trace)
    89  		return e
    90  	case *Fatal:
    91  		e.Err.Stack = append(e.Err.Stack, trace)
    92  		return e
    93  	case *NoContent:
    94  		e.Err.Stack = append(e.Err.Stack, trace)
    95  		return e
    96  	case *Timeout:
    97  		e.Err.Stack = append(e.Err.Stack, trace)
    98  		return e
    99  	}
   100  
   101  	return err
   102  }
   103  
   104  func StackMsg(err error, msg string, trace ErrTrace) error {
   105  	if err == nil {
   106  		return err
   107  	}
   108  
   109  	switch e := err.(type) {
   110  	case *Internal:
   111  		e.Err.Stack = append(e.Err.Stack, trace)
   112  		e.StackMessage = msg
   113  		return e
   114  	case *NotFound:
   115  		e.Err.Stack = append(e.Err.Stack, trace)
   116  		e.StackMessage = msg
   117  		return e
   118  	case *Conflict:
   119  		e.Err.Stack = append(e.Err.Stack, trace)
   120  		e.StackMessage = msg
   121  		return e
   122  	case *BadRequest:
   123  		e.Err.Stack = append(e.Err.Stack, trace)
   124  		e.StackMessage = msg
   125  		return e
   126  	case *Unauthorized:
   127  		e.Err.Stack = append(e.Err.Stack, trace)
   128  		e.StackMessage = msg
   129  		return e
   130  	case *Fatal:
   131  		e.Err.Stack = append(e.Err.Stack, trace)
   132  		e.StackMessage = msg
   133  		return e
   134  	case *NoContent:
   135  		e.Err.Stack = append(e.Err.Stack, trace)
   136  		e.StackMessage = msg
   137  		return e
   138  	case *Timeout:
   139  		e.Err.Stack = append(e.Err.Stack, trace)
   140  		e.StackMessage = msg
   141  		return e
   142  	}
   143  	return err
   144  }
   145  
   146  //	ErrorF returns the full error information
   147  func ErrorF(err error) string {
   148  
   149  	if err == nil {
   150  		return ""
   151  	}
   152  
   153  	e := extractErr(err)
   154  	if e.Cause == "" && e.Message == "" {
   155  		return err.Error()
   156  	}
   157  
   158  	var stackTrace string
   159  
   160  	traceFormat := "> Line=%-4d | Function=%-40s | File=%-30s"
   161  
   162  	for _, stack := range e.Stack {
   163  		stackTrace += fmt.Sprintf("\n"+traceFormat, stack.Line, stack.Function, stack.File)
   164  	}
   165  
   166  	return fmt.Sprintf("\n Full error information:\n- Cause: %s\n- Info: %s\n- Stack msg: %s\n- Error code: %d\n- Stack trace: %s", e.Cause, e.Message, e.StackMessage, e.Code, stackTrace)
   167  }
   168  
   169  // Unwrap returns the original error
   170  func Unwrap(err error) error {
   171  
   172  	if err == nil {
   173  		return err
   174  	}
   175  
   176  	e := extractErr(err)
   177  	if e.Cause == "" && e.Message == "" {
   178  		return err
   179  	}
   180  
   181  	return e.Wrapped
   182  }
   183  
   184  func GetCause(err error) string {
   185  	if err == nil {
   186  		return ""
   187  	}
   188  	e := extractErr(err)
   189  	if e.Cause == "" && e.Message != "" {
   190  		return e.Message
   191  	} else if e.Cause == "" && e.Message == "" {
   192  		return err.Error()
   193  	}
   194  	return e.Cause
   195  }
   196  
   197  func GetMessage(err error) string {
   198  	if err == nil {
   199  		return ""
   200  	}
   201  	e := extractErr(err)
   202  	if e.Message == "" {
   203  		return err.Error()
   204  	}
   205  	return e.Message
   206  }
   207  
   208  func GetTrace(err error) ErrTrace {
   209  	if err == nil {
   210  		return ErrTrace{}
   211  	}
   212  	e := extractErr(err)
   213  	if e.Trace.File == "" {
   214  		return ErrTrace{}
   215  	}
   216  	return e.Trace
   217  }
   218  
   219  func GetStack(err error) []ErrTrace {
   220  	if err == nil {
   221  		return nil
   222  	}
   223  	e := extractErr(err)
   224  	if len(e.Stack) == 0 {
   225  		return []ErrTrace{}
   226  	}
   227  	return e.Stack
   228  }
   229  
   230  func GetStackJson(err error) string {
   231  	if err == nil {
   232  		return ""
   233  	}
   234  	e := extractErr(err)
   235  	if len(e.Stack) == 0 {
   236  		return "{}"
   237  	}
   238  
   239  	encoded, _ := json.Marshal(e.Stack)
   240  
   241  	return string(encoded)
   242  }
   243  
   244  func GetWrapped(err error) error {
   245  	if err == nil {
   246  		return nil
   247  	}
   248  	e := extractErr(err)
   249  	if e.Wrapped == nil {
   250  		return err
   251  	}
   252  	return e.Wrapped
   253  }
   254  
   255  func GetCode(err error) int {
   256  	if err == nil {
   257  		return 0
   258  	}
   259  	e := extractErr(err)
   260  	if e.Code == 0 {
   261  		if IsNotFound(err) {
   262  			return 404
   263  		}
   264  		if IsUnauthorized(err) {
   265  			return 403
   266  		}
   267  		if IsBadRequest(err) {
   268  			return 400
   269  		}
   270  		if IsInternal(err) || IsFatal(err) {
   271  			return 500
   272  		}
   273  		if IsConflict(err) {
   274  			return 409
   275  		}
   276  		if IsNoContent(err) {
   277  			return 204
   278  		}
   279  	}
   280  	return e.Code
   281  }
   282  
   283  func Trace() ErrTrace {
   284  	pc := make([]uintptr, 10)
   285  	runtime.Callers(2, pc)
   286  	function := runtime.FuncForPC(pc[0])
   287  	file, line := function.FileLine(pc[0])
   288  
   289  	// matching only the file name
   290  	rgx, err := regexp.Compile(`(?i)/([\w\d_+*()\[\]%=\-]+\.\w+)$`)
   291  	if err == nil {
   292  		matches := rgx.FindStringSubmatch(file)
   293  		if len(matches) > 0 {
   294  			file = matches[1]
   295  		}
   296  	}
   297  
   298  	funcName := function.Name()
   299  	rgx, err = regexp.Compile(`(?i)(/[\w\d_*().\-]+$)`)
   300  	if err == nil {
   301  		matches := rgx.FindStringSubmatch(funcName)
   302  		if len(matches) > 0 {
   303  			funcName = matches[1]
   304  		}
   305  	}
   306  	return ErrTrace{Line: line, File: file, Function: funcName}
   307  }