forked from romapres2010/httpserver
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy patherror.go
More file actions
126 lines (111 loc) · 3.61 KB
/
Copy patherror.go
File metadata and controls
126 lines (111 loc) · 3.61 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
package errors
import (
"fmt"
"runtime"
"strconv"
"strings"
"sync/atomic"
pkgerr "github.com/pkg/errors"
mylog "github.com/romapres2010/httpserver/log"
)
var errorID uint64 // уникальный номер ошибки
// Error represent custom error
type Error struct {
ID uint64 // уникальный номер ошибки
Code string // код ошибки
Msg string // текст ошибки
Caller string // файл, строка и наименование метода в котором произошла ошибка
Args string // строка аргументов
CauseErr error // ошибка - причина
CauseMsg string // текст ошибки - причины
Trace string // стек вызова
}
// getNextErrorID - запросить номер следующей ошибки
func getNextErrorID() uint64 {
return atomic.AddUint64(&errorID, 1)
}
// Format output
// %s print the error code, message, arguments, and cause message.
// %v in addition to %s, print caller
// %+v extended format. Each Frame of the error's StackTrace will be printed in detail.
func (e *Error) Format(s fmt.State, verb rune) {
switch verb {
case 'v':
fmt.Fprint(s, e.Error())
fmt.Fprintf(s, ", caller=[%s]", e.Caller)
if s.Flag('+') {
fmt.Fprintf(s, ", trace=%s", e.Trace)
return
}
case 's':
fmt.Fprint(s, e.Error())
case 'q':
fmt.Fprint(s, e.Error())
}
}
//Error print custom error
func (e *Error) Error() string {
mes := fmt.Sprintf("ErrID=[%v], code=[%s], mes=[%s]", e.ID, e.Code, e.Msg)
if e.Args != "" {
mes = fmt.Sprintf("%s, args=[%s]", mes, e.Args)
}
if e.CauseMsg != "" {
mes = fmt.Sprintf("%s, causemes=[%s]", mes, e.CauseMsg)
}
return mes
}
//PrintfInfo print custom error
func (e *Error) PrintfInfo(depths ...int) *Error {
depth := 1
if len(depths) == 1 {
depth = depth + depths[0]
}
mylog.PrintfMsg("[INFO]", depth, e.Error())
return e
}
// New - create new custom error
func New(code string, msg string, args ...interface{}) *Error {
err := Error{
ID: getNextErrorID(),
Code: code,
Msg: msg,
Caller: caller(2),
Args: getArgsString(args...), // get formated string with arguments
Trace: fmt.Sprintf("'%+v'", pkgerr.New("")), // create err and print it trace
}
return &err
}
// WithCause - create new custom error with cause
func WithCause(code string, msg string, causeErr error, args ...interface{}) *Error {
err := Error{
ID: getNextErrorID(),
Code: code,
Msg: msg,
Caller: caller(2),
Args: getArgsString(args...), // get formated string with arguments
Trace: fmt.Sprintf("'%+v'", pkgerr.New("")), // create err and print it trace
CauseMsg: fmt.Sprintf("'%+v'", causeErr), // get formated string from cause error
CauseErr: causeErr,
}
return &err
}
// getArgsString return formated string with arguments
func getArgsString(args ...interface{}) (argsStr string) {
for _, arg := range args {
if arg != nil {
argsStr = argsStr + fmt.Sprintf("'%v', ", arg)
}
}
argsStr = strings.TrimRight(argsStr, ", ")
return
}
// caller returns a Valuer that returns a file and line from a specified depth in the callstack.
func caller(depth int) string {
pc := make([]uintptr, 15)
n := runtime.Callers(depth+1, pc)
frame, _ := runtime.CallersFrames(pc[:n]).Next()
idxFile := strings.LastIndexByte(frame.File, '/')
idx := strings.LastIndexByte(frame.Function, '/')
idxName := strings.IndexByte(frame.Function[idx+1:], '.') + idx + 1
return frame.File[idxFile+1:] + ":[" + strconv.Itoa(frame.Line) + "] - " + frame.Function[idxName+1:] + "()"
}