...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package githubapp
16
17 import (
18 "fmt"
19 "io"
20 "runtime"
21
22 "github.com/rcrowley/go-metrics"
23 )
24
25 const (
26 MetricsKeyHandlerError = "github.handler.error"
27 )
28
29 var (
30
31
32 HandlerRecoverStackDepth = 32
33 )
34
35 func errorCounter(r metrics.Registry, event string) metrics.Counter {
36 if r == nil {
37 return metrics.NilCounter{}
38 }
39
40 key := MetricsKeyHandlerError
41 if event != "" {
42 key = fmt.Sprintf("%s[event:%s]", key, event)
43 }
44 return metrics.GetOrRegisterCounter(key, r)
45 }
46
47
48 type HandlerPanicError struct {
49 value interface{}
50 stack []runtime.Frame
51 }
52
53
54 func (e HandlerPanicError) Value() interface{} {
55 return e.value
56 }
57
58
59 func (e HandlerPanicError) StackTrace() []runtime.Frame {
60 return e.stack
61 }
62
63
64
65
66
67
68
69
70
71 func (e HandlerPanicError) Format(s fmt.State, verb rune) {
72 switch verb {
73 case 's':
74 _, _ = io.WriteString(s, e.Error())
75 case 'v':
76 _, _ = io.WriteString(s, e.Error())
77 for _, f := range e.stack {
78 _, _ = io.WriteString(s, "\n")
79 if s.Flag('+') {
80 _, _ = fmt.Fprintf(s, "%s\n\t", f.Function)
81 }
82 _, _ = fmt.Fprintf(s, "%s:%d", f.File, f.Line)
83 }
84 }
85 }
86
87 func (e HandlerPanicError) Error() string {
88 v := e.value
89 if err, ok := v.(error); ok {
90 v = err.Error()
91 }
92 return fmt.Sprintf("panic: %v", v)
93 }
94
95 func getStack(skip int) []runtime.Frame {
96 rpc := make([]uintptr, HandlerRecoverStackDepth)
97
98 n := runtime.Callers(skip+2, rpc)
99 frames := runtime.CallersFrames(rpc[0:n])
100
101 var stack []runtime.Frame
102 for {
103 f, more := frames.Next()
104 if !more {
105 break
106 }
107 stack = append(stack, f)
108 }
109 return stack
110 }
111
View as plain text