[chore] simplify generating log entry caller information (#863)
* vastly simplify logging caller information Signed-off-by: kim <grufwub@gmail.com> * fix failing test due to multiple calls to processor.Start() Signed-off-by: kim <grufwub@gmail.com> Signed-off-by: kim <grufwub@gmail.com>
This commit is contained in:
parent
a156188b3e
commit
2f22780800
|
@ -292,15 +292,6 @@ func (suite *InboxPostTestSuite) TestPostUpdate() {
|
|||
federator := testrig.NewTestFederator(suite.db, tc, suite.storage, suite.mediaManager, fedWorker)
|
||||
emailSender := testrig.NewEmailSender("../../../../web/template/", nil)
|
||||
processor := testrig.NewTestProcessor(suite.db, suite.storage, federator, emailSender, suite.mediaManager, clientWorker, fedWorker)
|
||||
if err := processor.Start(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer func() {
|
||||
if err := processor.Stop(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}()
|
||||
|
||||
userModule := user.New(processor).(*user.Module)
|
||||
suite.NoError(processor.Start())
|
||||
|
||||
|
|
|
@ -21,69 +21,39 @@ package log
|
|||
import (
|
||||
"runtime"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var (
|
||||
// fnCache is a cache of PCs to their calculated function names.
|
||||
fnCache = map[uintptr]string{}
|
||||
|
||||
// strCache is a cache of strings to the originally allocated version
|
||||
// of that string contents. so we don't have hundreds of the same instances
|
||||
// of string floating around in memory.
|
||||
strCache = map[string]string{}
|
||||
|
||||
// cacheMu protects fnCache and strCache.
|
||||
cacheMu sync.Mutex
|
||||
)
|
||||
|
||||
// Caller fetches the calling function name, skipping 'depth'. Results are cached per PC.
|
||||
func Caller(depth int) string {
|
||||
var rpc [1]uintptr
|
||||
var pcs [1]uintptr
|
||||
|
||||
// Fetch pcs of callers
|
||||
n := runtime.Callers(depth, rpc[:])
|
||||
// Fetch calling function using calldepth
|
||||
_ = runtime.Callers(depth, pcs[:])
|
||||
fn := runtime.FuncForPC(pcs[0])
|
||||
|
||||
if n > 0 {
|
||||
// Look for value in cache
|
||||
cacheMu.Lock()
|
||||
fn, ok := fnCache[rpc[0]]
|
||||
cacheMu.Unlock()
|
||||
|
||||
if ok {
|
||||
return fn
|
||||
}
|
||||
|
||||
// Fetch frame info for caller pc
|
||||
frame, _ := runtime.CallersFrames(rpc[:]).Next()
|
||||
|
||||
if frame.PC != 0 {
|
||||
name := frame.Function
|
||||
|
||||
// Drop all but the package name and function name, no mod path
|
||||
if idx := strings.LastIndex(name, "/"); idx >= 0 {
|
||||
name = name[idx+1:]
|
||||
}
|
||||
|
||||
// Drop any generic type parameter markers
|
||||
if idx := strings.Index(name, "[...]"); idx >= 0 {
|
||||
name = name[:idx] + name[idx+5:]
|
||||
}
|
||||
|
||||
// Cache this func name
|
||||
cacheMu.Lock()
|
||||
fn, ok := strCache[name]
|
||||
if !ok {
|
||||
// Cache ptr to this allocated str
|
||||
strCache[name] = name
|
||||
fn = name
|
||||
}
|
||||
fnCache[rpc[0]] = fn
|
||||
cacheMu.Unlock()
|
||||
|
||||
return fn
|
||||
}
|
||||
if fn == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
return "???"
|
||||
// return formatted name
|
||||
return callername(fn)
|
||||
}
|
||||
|
||||
// callername generates a human-readable calling function name.
|
||||
func callername(fn *runtime.Func) string {
|
||||
name := fn.Name()
|
||||
|
||||
// Drop all but the package name and function name, no mod path
|
||||
if idx := strings.LastIndex(name, "/"); idx >= 0 {
|
||||
name = name[idx+1:]
|
||||
}
|
||||
|
||||
const params = `[...]`
|
||||
|
||||
// Drop any generic type parameter markers
|
||||
if idx := strings.Index(name, params); idx >= 0 {
|
||||
name = name[:idx] + name[idx+len(params):]
|
||||
}
|
||||
|
||||
return name
|
||||
}
|
||||
|
|
|
@ -1,54 +0,0 @@
|
|||
package log_test
|
||||
|
||||
import (
|
||||
"runtime"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"codeberg.org/gruf/go-atomics"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/log"
|
||||
)
|
||||
|
||||
// noopt exists to prevent certain optimisations during benching.
|
||||
var noopt = atomics.NewString()
|
||||
|
||||
func BenchmarkCaller(b *testing.B) {
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
for pb.Next() {
|
||||
name := log.Caller(2)
|
||||
noopt.Store(name)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func BenchmarkCallerNoCache(b *testing.B) {
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
for pb.Next() {
|
||||
var rpc [1]uintptr
|
||||
|
||||
// Fetch pcs of callers
|
||||
n := runtime.Callers(2, rpc[:])
|
||||
|
||||
if n > 0 {
|
||||
// Fetch frame info for caller pc
|
||||
frame, _ := runtime.CallersFrames(rpc[:]).Next()
|
||||
|
||||
if frame.PC != 0 {
|
||||
name := frame.Function
|
||||
|
||||
// Drop all but the package name and function name, no mod path
|
||||
if idx := strings.LastIndex(name, "/"); idx >= 0 {
|
||||
name = name[idx+1:]
|
||||
}
|
||||
|
||||
// Drop any generic type parameter markers
|
||||
if idx := strings.Index(name, "[...]"); idx >= 0 {
|
||||
name = name[:idx] + name[idx+5:]
|
||||
}
|
||||
|
||||
noopt.Store(name)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
Loading…
Reference in New Issue