Skip to content

Commit a628f19

Browse files
author
auxten
committed
Add call stack print for Error, Fatal and Panic
1 parent 3a72395 commit a628f19

File tree

2 files changed

+79
-21
lines changed

2 files changed

+79
-21
lines changed

utils/log/logwrapper.go

Lines changed: 61 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -60,11 +60,28 @@ type Logger logrus.Logger
6060
type Fields logrus.Fields
6161

6262
// CallerHook defines caller awareness hook for logrus.
63-
type CallerHook struct{}
63+
type CallerHook struct {
64+
StackLevels []logrus.Level
65+
}
66+
67+
// NewCallerHook creates new CallerHook
68+
func NewCallerHook(stackLevels []logrus.Level) *CallerHook {
69+
return &CallerHook{
70+
StackLevels: stackLevels,
71+
}
72+
}
73+
74+
// StandardCallerHook is a convenience initializer for LogrusStackHook{} with
75+
// default args.
76+
func StandardCallerHook() *CallerHook {
77+
return NewCallerHook(
78+
[]logrus.Level{logrus.PanicLevel, logrus.FatalLevel, logrus.ErrorLevel},
79+
)
80+
}
6481

6582
// Fire defines hook event handler.
6683
func (hook *CallerHook) Fire(entry *logrus.Entry) error {
67-
funcDesc, caller := hook.caller()
84+
funcDesc, caller := hook.caller(entry)
6885
fields := strings.SplitN(funcDesc, ".", 2)
6986
if len(fields) > 0 {
7087
level, ok := PkgDebugLogFilter[fields[0]]
@@ -91,38 +108,61 @@ func (hook *CallerHook) Levels() []logrus.Level {
91108
}
92109
}
93110

94-
func (hook *CallerHook) caller() (relFuncName, caller string) {
95-
var (
96-
file = "unknown"
97-
line = 0
98-
funcName = "unknown"
99-
)
111+
func (hook *CallerHook) caller(entry *logrus.Entry) (relFuncName, caller string) {
112+
var skipFrames int
113+
if len(entry.Data) == 0 {
114+
// When WithField(s) is not used, we have 8 logrus frames to skip.
115+
skipFrames = 8
116+
} else {
117+
// When WithField(s) is used, we have 6 logrus frames to skip.
118+
skipFrames = 6
119+
}
120+
100121
pcs := make([]uintptr, 12)
101-
if runtime.Callers(6, pcs) > 0 {
102-
frames := runtime.CallersFrames(pcs)
122+
stacks := make([]runtime.Frame, 0, 12)
123+
if runtime.Callers(skipFrames, pcs) > 0 {
124+
var foundCaller bool
125+
_frames := runtime.CallersFrames(pcs)
103126
for {
104-
f, more := frames.Next()
127+
f, more := _frames.Next()
105128
//fmt.Printf("%s:%d %s\n", f.File, f.Line, f.Function)
106-
if strings.HasSuffix(f.File, "logwrapper.go") && more {
107-
f, _ = frames.Next()
108-
file = f.File
109-
line = f.Line
110-
funcName = f.Function
111-
break
129+
if !foundCaller && strings.HasSuffix(f.File, "logwrapper.go") && more {
130+
f, _ = _frames.Next()
131+
relFuncName = strings.TrimPrefix(f.Function, "github.com/CovenantSQL/CovenantSQL/")
132+
caller = fmt.Sprintf("%s:%d %s", filepath.Base(f.File), f.Line, relFuncName)
133+
foundCaller = true
134+
}
135+
if foundCaller {
136+
stacks = append(stacks, f)
112137
}
113138
if !more {
114139
break
115140
}
116141
}
117142
}
118143

119-
relFuncName = strings.TrimPrefix(funcName, "github.com/CovenantSQL/CovenantSQL/")
120-
funcLocation := fmt.Sprintf("%s:%d %s", filepath.Base(file), line, relFuncName)
121-
return relFuncName, funcLocation
144+
if len(stacks) > 0 {
145+
for _, level := range hook.StackLevels {
146+
if entry.Level == level {
147+
stacksStr := make([]string, 0, len(stacks))
148+
for i, s := range stacks {
149+
if s.Line > 0 {
150+
fName := strings.TrimPrefix(s.Function, "github.com/CovenantSQL/CovenantSQL/")
151+
stackStr := fmt.Sprintf("#%d %s@%s:%d ", i, fName, filepath.Base(s.File), s.Line)
152+
stacksStr = append(stacksStr, stackStr)
153+
}
154+
}
155+
entry.Data["stack"] = stacksStr
156+
break
157+
}
158+
}
159+
}
160+
161+
return relFuncName, caller
122162
}
123163

124164
func init() {
125-
AddHook(&CallerHook{})
165+
AddHook(StandardCallerHook())
126166
}
127167

128168
//var (

utils/log/logwrapper_test.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ import (
2121
"testing"
2222
"time"
2323

24+
"github.com/ethereum/go-ethereum/log"
25+
2426
"github.com/pkg/errors"
2527

2628
"github.com/sirupsen/logrus"
@@ -82,11 +84,27 @@ func TestStandardLogger(t *testing.T) {
8284

8385
}
8486

87+
func call0() {
88+
call1()
89+
}
90+
91+
func call1() {
92+
call2()
93+
}
94+
95+
func call2() {
96+
WithField("k", "v").Error("Error")
97+
log.Error("call2 error")
98+
}
99+
85100
func TestWithField(t *testing.T) {
86101
SetLevel(DebugLevel)
87102
if GetLevel() != DebugLevel {
88103
t.Fail()
89104
}
105+
106+
call0()
107+
90108
f := new(Fields)
91109
WithError(errors.New("new")).WithFields(*f).WithTime(time.Now()).Debug("Debug")
92110

0 commit comments

Comments
 (0)