/
recover.go
70 lines (63 loc) · 1.41 KB
/
recover.go
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
package middleware
import (
"bytes"
"fmt"
"runtime"
"github.com/kataras/iris/v12/context"
"github.com/8treenet/freedom"
)
// NewRecover Request recover.
func NewRecover() context.Handler {
return func(ctx context.Context) {
defer func() {
if err := recover(); err != nil {
if ctx.IsStopped() {
return
}
rt := freedom.ToWorker(ctx)
// when stack finishes
logMessage := fmt.Sprintf("Recovered from path('%s')\n", ctx.Path())
logMessage += fmt.Sprintf("Panic: %s\n", err)
logMessage += fmt.Sprintf("At stack: %s\n", string(panicTrace()))
rt.Logger().Error(logMessage)
ctx.StatusCode(500)
ctx.StopExecution()
}
}()
ctx.Next()
}
}
func panicTrace() []byte {
def := []byte("An unknown error")
s := []byte("/src/runtime/panic.go")
e := []byte("\ngoroutine ")
line := []byte("\n")
stack := make([]byte, 2<<10) //2KB
length := runtime.Stack(stack, false)
start := bytes.Index(stack, s)
if start == -1 || start > len(stack) || length > len(stack) {
return def
}
stack = stack[start:length]
start = bytes.Index(stack, line) + 1
if start >= len(stack) {
return def
}
stack = stack[start:]
end := bytes.LastIndex(stack, line)
if end > len(stack) {
return def
}
if end != -1 {
stack = stack[:end]
}
end = bytes.Index(stack, e)
if end > len(stack) {
return def
}
if end != -1 {
stack = stack[:end]
}
stack = bytes.TrimRight(stack, "\n")
return stack
}