Skip to content

Commit

Permalink
Refactor caller reporting (#4)
Browse files Browse the repository at this point in the history
* refactor caller reporting

* simplify handling of the inability to request caller info
  • Loading branch information
zonescape authored and umputun committed Mar 14, 2019
1 parent e8926af commit a7f793b
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 28 deletions.
97 changes: 69 additions & 28 deletions logger.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,34 +74,10 @@ func (l *Logger) logf(format string, args ...interface{}) {
bld.WriteString(l.formatLevel(lv))
bld.WriteString(" ")

if l.callerFile || l.callerFunc || l.callerPkg {
if pc, file, line, ok := runtime.Caller(2); ok {

funcName, fileInfo := "", ""

if l.callerFunc {
funcNameElems := strings.Split(runtime.FuncForPC(pc).Name(), "/")
funcName = funcNameElems[len(funcNameElems)-1]
}

if l.callerFile {
fnameElems := strings.Split(file, "/")
fileInfo = fmt.Sprintf("%s:%d", strings.Join(fnameElems[len(fnameElems)-2:], "/"), line)
if l.callerFunc {
fileInfo += " "
}
}
// callerPkg only if no other callers
if l.callerPkg && !l.callerFile && !l.callerFunc {
file = l.ignoreCaller(file)
_, fileInfo = path.Split(path.Dir(file))
if l.callerFunc {
fileInfo += " "
}
}
srcFileInfo := fmt.Sprintf("{%s%s} ", fileInfo, funcName)
bld.WriteString(srcFileInfo)
}
if caller := l.reportCaller(2); caller != "" {
bld.WriteString("{")
bld.WriteString(caller)
bld.WriteString("} ")
}

bld.WriteString(msg) //nolint
Expand All @@ -124,6 +100,71 @@ func (l *Logger) logf(format string, args ...interface{}) {
l.lock.Unlock()
}

// calldepth 0 identifying the caller of reportCaller()
func (l *Logger) reportCaller(calldepth int) string {
if !(l.callerFile || l.callerFunc || l.callerPkg) {
return ""
}

filePath, line, funcName := l.caller(calldepth + 1)
if (filePath == "") || (line <= 0) || (funcName == "") {
return "???"
}

// callerPkg only if no other callers
if l.callerPkg && !l.callerFile && !l.callerFunc {
pkgInfo := l.ignoreCaller(filePath)
_, pkgInfo = path.Split(path.Dir(pkgInfo))
return pkgInfo
}

res := ""

if l.callerFile {
fileInfo := filePath
if pathElems := strings.Split(filePath, "/"); len(pathElems) > 2 {
fileInfo = strings.Join(pathElems[len(pathElems)-2:], "/")
}
res += fmt.Sprintf("%s:%d", fileInfo, line)
if l.callerFunc {
res += " "
}
}

if l.callerFunc {
funcNameElems := strings.Split(funcName, "/")
funcInfo := funcNameElems[len(funcNameElems)-1]
res += funcInfo
}

return res
}

// caller is a modified version of runtime.Caller()
// calldepth 0 identifying the caller of caller()
// file looks like:
// /go/src/github.com/go-pkgz/lgr/logger.go
// file is an empty string if not known.
// funcName looks like:
// main.Test
// foo/bar.Test
// foo/bar.Test.func1
// foo/bar.(*Bar).Test
// foo/bar.glob..func1
// funcName is an empty string if not known.
// line is a zero if not known.
func (l *Logger) caller(calldepth int) (file string, line int, funcName string) {
pcs := make([]uintptr, 1)
n := runtime.Callers(calldepth+2, pcs)
if n != 1 {
return "", 0, ""
}

frame, _ := runtime.CallersFrames(pcs).Next()

return frame.File, frame.Line, frame.Function
}

func (l *Logger) ignoreCaller(p string) string {
for _, s := range l.ignoredPkgCallers {
if strings.Contains(p, "/"+s+"/") {
Expand Down
17 changes: 17 additions & 0 deletions logger_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,23 @@ func TestLoggerConcurrent(t *testing.T) {
assert.Equal(t, "", rerr.String())
}

func TestCaller(t *testing.T) {
var l *Logger

filePath, line, funcName := l.caller(0)
assert.True(t, strings.HasSuffix(filePath, "go-pkgz/lgr/logger_test.go"), filePath)
assert.Equal(t, 222, line)
assert.Equal(t, funcName, "github.com/go-pkgz/lgr.TestCaller")

f := func() {
filePath, line, funcName = l.caller(1)
}
f()
assert.True(t, strings.HasSuffix(filePath, "go-pkgz/lgr/logger_test.go"), filePath)
assert.Equal(t, 230, line)
assert.Equal(t, funcName, "github.com/go-pkgz/lgr.TestCaller")
}

func BenchmarkNoDbg(b *testing.B) {
rout, rerr := bytes.NewBuffer([]byte{}), bytes.NewBuffer([]byte{})
l := New(Out(rout), Err(rerr))
Expand Down

0 comments on commit a7f793b

Please sign in to comment.