mirror of
				https://github.com/superseriousbusiness/gotosocial.git
				synced 2025-11-03 19:02:26 -06:00 
			
		
		
		
	[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
					
				
			
		
					 3 changed files with 27 additions and 120 deletions
				
			
		| 
						 | 
				
			
			@ -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
 | 
			
		||||
	if fn == nil {
 | 
			
		||||
		return ""
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
		// Fetch frame info for caller pc
 | 
			
		||||
		frame, _ := runtime.CallersFrames(rpc[:]).Next()
 | 
			
		||||
	// return formatted name
 | 
			
		||||
	return callername(fn)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		if frame.PC != 0 {
 | 
			
		||||
			name := frame.Function
 | 
			
		||||
// 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, "[...]"); idx >= 0 {
 | 
			
		||||
				name = name[:idx] + name[idx+5:]
 | 
			
		||||
	if idx := strings.Index(name, params); idx >= 0 {
 | 
			
		||||
		name = name[:idx] + name[idx+len(params):]
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
			// 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
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return "???"
 | 
			
		||||
	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…
	
	Add table
		Add a link
		
	
		Reference in a new issue