Skip to content

Commit 3401fd9

Browse files
committed
Add stack trace after panic
Signed-off-by: Jason Joo <[email protected]>
1 parent df0dd39 commit 3401fd9

File tree

8 files changed

+112
-20
lines changed

8 files changed

+112
-20
lines changed

core/leader.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,9 @@ func (manager *ScheduleManager) stopWorkers(strategy *definition.Strategy) error
262262
defer func() {
263263
if err := recover(); err != nil {
264264
log.Errorf("Stop worker %s failed: %v", strategy.ID, err)
265+
traceData := utils.StackTraceData()
266+
defer traceData.Recycle()
267+
log.Error("Trace: ", traceData.String())
265268
}
266269
}()
267270
w.Stop(strategy.ID, strategy.Parameter)

core/worker/task_worker/executor_batch.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@ import (
88
"sync"
99
"time"
1010

11+
"github.com/jasonjoo2010/goschedule/log"
1112
"github.com/jasonjoo2010/goschedule/types"
13+
"github.com/jasonjoo2010/goschedule/utils"
1214
"github.com/sirupsen/logrus"
1315
)
1416

@@ -26,6 +28,9 @@ func (m *BatchExecutor) execute(items []interface{}) {
2628
defer func() {
2729
if r := recover(); r != nil {
2830
logrus.Error("Execute error: ", r)
31+
traceData := utils.StackTraceData()
32+
defer traceData.Recycle()
33+
log.Error("Trace: ", traceData.String())
2934
succ = false
3035
}
3136
m.worker.Statistics.Execute(succ, cost)

core/worker/task_worker/executor_single.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@ package task_worker
77
import (
88
"time"
99

10+
"github.com/jasonjoo2010/goschedule/log"
1011
"github.com/jasonjoo2010/goschedule/types"
12+
"github.com/jasonjoo2010/goschedule/utils"
1113
"github.com/sirupsen/logrus"
1214
)
1315

@@ -24,6 +26,9 @@ func (m *SingleExecutor) execute(item interface{}) {
2426
defer func() {
2527
if r := recover(); r != nil {
2628
logrus.Error("Execute error: ", r)
29+
traceData := utils.StackTraceData()
30+
defer traceData.Recycle()
31+
log.Error("Trace: ", traceData.String())
2732
succ = false
2833
}
2934
m.worker.Statistics.Execute(succ, cost)

core/worker/task_worker/task_worker.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,9 @@ func (w *TaskWorker) selectOnce() {
240240
defer func() {
241241
if r := recover(); r != nil {
242242
logrus.Error("Selecting error: ", r)
243+
traceData := utils.StackTraceData()
244+
defer traceData.Recycle()
245+
log.Error("Trace: ", traceData.String())
243246
}
244247
if utils.ContextDone(w.ctx) {
245248
// notify blocking routines

log/log.go

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@ var inst = NewLogrusWrapper()
55
// Wrapper defines the interface used in project to make it able to integrate with different loggers
66
type Wrapper interface {
77
Name() string
8-
Debug(fmt string)
9-
Info(fmt string)
10-
Warn(fmt string)
11-
Error(fmt string)
8+
Debug(args ...interface{})
9+
Info(args ...interface{})
10+
Warn(args ...interface{})
11+
Error(args ...interface{})
1212
Debugf(fmt string, args ...interface{})
1313
Infof(fmt string, args ...interface{})
1414
Warnf(fmt string, args ...interface{})
@@ -49,21 +49,21 @@ func Errorf(fmt string, args ...interface{}) {
4949
}
5050

5151
// Debug is a convenient scaffold for debug logs
52-
func Debug(fmt string) {
53-
inst.Debug(fmt)
52+
func Debug(args ...interface{}) {
53+
inst.Debug(args...)
5454
}
5555

5656
// Info is a convenient scaffold for information logs
57-
func Info(fmt string) {
58-
inst.Info(fmt)
57+
func Info(args ...interface{}) {
58+
inst.Info(args...)
5959
}
6060

6161
// Warn is a convenient scaffold for warning logs
62-
func Warn(fmt string) {
63-
inst.Warn(fmt)
62+
func Warn(args ...interface{}) {
63+
inst.Warn(args...)
6464
}
6565

6666
// Error is a convenient scaffold for error logs
67-
func Error(fmt string) {
68-
inst.Error(fmt)
67+
func Error(args ...interface{}) {
68+
inst.Error(args...)
6969
}

log/logrus.go

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -31,18 +31,18 @@ func (w *logrusWrapper) Errorf(fmt string, args ...interface{}) {
3131
logrus.Errorf(fmt, args...)
3232
}
3333

34-
func (w *logrusWrapper) Debug(fmt string) {
35-
logrus.Debugf(fmt)
34+
func (w *logrusWrapper) Debug(args ...interface{}) {
35+
logrus.Debug(args...)
3636
}
3737

38-
func (w *logrusWrapper) Info(fmt string) {
39-
logrus.Infof(fmt)
38+
func (w *logrusWrapper) Info(args ...interface{}) {
39+
logrus.Info(args...)
4040
}
4141

42-
func (w *logrusWrapper) Warn(fmt string) {
43-
logrus.Warnf(fmt)
42+
func (w *logrusWrapper) Warn(args ...interface{}) {
43+
logrus.Warn(args...)
4444
}
4545

46-
func (w *logrusWrapper) Error(fmt string) {
47-
logrus.Errorf(fmt)
46+
func (w *logrusWrapper) Error(args ...interface{}) {
47+
logrus.Error(args...)
4848
}

utils/trace.go

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package utils
2+
3+
import (
4+
"runtime"
5+
"sync"
6+
)
7+
8+
type TraceData struct {
9+
data []byte
10+
size int
11+
}
12+
13+
func (data *TraceData) Len() int {
14+
return data.size
15+
}
16+
17+
func (data *TraceData) Data() []byte {
18+
return data.data[:data.size]
19+
}
20+
21+
func (data *TraceData) String() string {
22+
return string(data.Data())
23+
}
24+
25+
// call this to reuse the memory
26+
func (data *TraceData) Recycle() {
27+
tracePool.Put(data)
28+
}
29+
30+
var tracePool = &sync.Pool{
31+
New: func() interface{} {
32+
return &TraceData{
33+
data: make([]byte, 1024*64),
34+
size: 0,
35+
}
36+
},
37+
}
38+
39+
func StackTraceData() *TraceData {
40+
data := tracePool.Get().(*TraceData)
41+
data.size = runtime.Stack(data.data, false)
42+
return data
43+
}

utils/trace_test.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package utils
2+
3+
import (
4+
"fmt"
5+
"testing"
6+
7+
"github.com/stretchr/testify/assert"
8+
)
9+
10+
func TestTrace(t *testing.T) {
11+
data := StackTraceData()
12+
ptr := fmt.Sprintf("%p", data)
13+
assert.True(t, data.Len() > 0)
14+
data.Recycle()
15+
16+
data1 := StackTraceData()
17+
ptr1 := fmt.Sprintf("%p", data1)
18+
assert.True(t, data1.Len() > 0)
19+
data1.Recycle()
20+
21+
data2 := StackTraceData()
22+
ptr2 := fmt.Sprintf("%p", data2)
23+
assert.True(t, data2.Len() > 0)
24+
25+
data3 := StackTraceData()
26+
ptr3 := fmt.Sprintf("%p", data3)
27+
assert.True(t, data3.Len() > 0)
28+
data2.Recycle()
29+
data3.Recycle()
30+
31+
assert.Equal(t, ptr, ptr1)
32+
assert.NotEqual(t, ptr2, ptr3)
33+
}

0 commit comments

Comments
 (0)