1 package shared
2
3 import (
4 goerrors "errors"
5 "fmt"
6 "reflect"
7 "strings"
8
9 "github.com/golang/protobuf/proto"
10 "golang.conradwood.net/apis/common"
11 fw "golang.conradwood.net/apis/framework"
12 "golang.conradwood.net/apis/goeasyops"
13 goe "golang.conradwood.net/apis/goeasyops"
14 "google.golang.org/grpc/status"
15 proto2 "google.golang.org/protobuf/proto"
16 "google.golang.org/protobuf/protoadapt"
17 )
18
19
20
21
22
23
24 func ErrorString(err error) string {
25 st := status.Convert(err)
26 s := "[STATUS] "
27 deli := ""
28 var cstatus *common.Status
29 var gel *goe.GRPCErrorList
30 for _, a := range st.Details() {
31 unknown := true
32
33 st, ok := a.(*common.Status)
34 if ok {
35 cstatus = st
36 continue
37 }
38 lgel, ok := a.(*goeasyops.GRPCErrorList)
39 if ok {
40 gel = lgel
41 s = s + deli + ge2string(lgel)
42 continue
43 }
44
45
46 proto2m, okconv := a.(proto2.Message)
47 if !okconv {
48 z := fmt.Sprintf("[type=%v]", reflect.TypeOf(a))
49 fmt.Printf("[go-easyops] Failed to convert error message (%v %v)\n", a, z)
50 s = s + fmt.Sprintf(" =%v= ", a)
51 continue
52 }
53 msgname := proto2.MessageName(proto2m)
54
55 pv1 := protoadapt.MessageV1Of(proto2m)
56
57 if msgname == "goeasyops.GRPCErrorList" {
58 xgel, ok := pv1.(*goe.GRPCErrorList)
59 if ok {
60 gel = xgel
61 s = s + deli + ge2string(xgel)
62 continue
63 }
64 } else if msgname == "common.Status" {
65 st, ok := pv1.(*common.Status)
66 if ok {
67 cstatus = st
68 continue
69 }
70 }
71
72 fmd, ok := a.(*fw.FrameworkMessageDetail)
73 if ok {
74 unknown = false
75 s = s + deli + fmd2string(fmd)
76 }
77
78 ge, ok := a.(*goe.GRPCErrorList)
79 if unknown && ok {
80 unknown = false
81 s = s + deli + ge2string(ge)
82 }
83
84 ge2, ok := a.(goe.GRPCErrorList)
85 if unknown && ok {
86 unknown = false
87 s = s + deli + ge2string(&ge2)
88 }
89
90 x, ok := a.(goe.GRPCError)
91 if unknown && ok {
92 unknown = false
93 s = s + deli + fmt.Sprintf("CALLTRACE: %v", x)
94 }
95
96 x2, ok := a.(*fw.CallTrace)
97 if unknown && ok {
98 unknown = false
99 s = s + deli + fmt.Sprintf("CALLTRACE: %v", x2)
100 }
101
102 proto, ok := a.(proto.Message)
103 if unknown && ok {
104 unknown = false
105 s = s + deli + "proto:" + proto.String()
106 }
107
108 deli = "->"
109
110 }
111 s = s + ": " + st.Message() + " [/STATUS]"
112
113 if cstatus == nil && gel == nil {
114 return s
115 }
116 gel_s := ""
117 if gel != nil {
118 gel_s = ge2string(gel)
119 }
120 cs_s := ""
121 if cstatus != nil {
122 cs_s = fmt.Sprintf("code=%d(%s)", cstatus.ErrorCode, cstatus.ErrorDescription)
123 }
124
125 s = fmt.Sprintf("(N) %s %s", cs_s, gel_s)
126 return s
127
128 }
129
130 func fmd2string(fmd *fw.FrameworkMessageDetail) string {
131 s := ""
132 for _, ct := range fmd.CallTraces {
133 if ct.Service != "" {
134 spl := strings.SplitN(ct.Service, ".", 2)
135 sn := ct.Service
136 if len(spl) == 2 {
137 sn = spl[1]
138 }
139 s = fmt.Sprintf("(1 %s.%s)", sn, ct.Method)
140 } else {
141 s = fmt.Sprintf("(2 %s)", ct.Message)
142 }
143 }
144 return s
145 }
146
147 func ge2string(fmd *goe.GRPCErrorList) string {
148 s := ""
149 for _, ct := range fmd.Errors {
150 if ct.ServiceName != "" {
151 spl := strings.SplitN(ct.ServiceName, ".", 2)
152 sn := ct.ServiceName
153 if len(spl) == 2 {
154 sn = spl[1]
155 }
156 s = fmt.Sprintf("(3 %s.%s)", sn, ct.MethodName)
157 } else {
158 s = fmt.Sprintf("(4 %s)", ct.LogMessage)
159 }
160 }
161 return s
162 }
163
164 func ErrorStringWithStackTrace(err error) string {
165
166 var stacks []StackError
167 e := err
168 for {
169 if e == nil {
170 break
171 }
172 est, ok := e.(*MyError)
173 if ok {
174 stacks = append(stacks, est)
175 e = est.err
176 continue
177 }
178 wst, ok := e.(*WrappedError)
179 if ok {
180 stacks = append(stacks, wst)
181 e = wst.err
182 continue
183 }
184 e = goerrors.Unwrap(e)
185 }
186 has_stacktrace := false
187 st := "(no stacktrace)"
188 if len(stacks) > 0 {
189 has_stacktrace = true
190 stack := stacks[len(stacks)-1]
191 st = stackToString(stack.Stack())
192 }
193
194 s := fmt.Sprintf("Error (no stacktrace): \"%s\", Log: \"%s\"", err, ErrorString(err))
195 if has_stacktrace {
196 s = fmt.Sprintf("Error: \"%s\", Log: \"%s\"\nStackTrace:\n%s", err, ErrorString(err), st)
197 }
198 return s
199 }
200
201 func stackToString(stack ErrorStackTrace) string {
202 res := ""
203 starting := true
204 for _, pos := range stack.Positions() {
205 if starting {
206 if pos.IsFiltered() {
207 continue
208 }
209 }
210 starting = false
211 res = res + fmt.Sprintf("%s:%d\n", pos.Filename, pos.Line)
212 if pos.Function == "main.main" {
213 break
214 }
215 }
216 return res
217
218 }
219
220 func ShortMessage(err error) string {
221 e1, ok := err.(*MyError)
222 if ok {
223 return fmt.Sprintf("%s", e1.err)
224 }
225 e2, ok := err.(*WrappedError)
226 if ok {
227
228 unwrap := e2
229 for i := 0; i < 10; i++ {
230 fmt.Printf("UNWRAP: %s\n", unwrap)
231 x, ok := unwrap.err.(*WrappedError)
232 if !ok {
233 return ShortMessage(unwrap.err)
234 }
235 unwrap = x
236 }
237 return fmt.Sprintf("%s", e2.err)
238 }
239
240 return fmt.Sprintf("%s", err)
241 }
242
View as plain text