mirror of
https://github.com/akvorado/akvorado.git
synced 2025-12-12 06:24:10 +01:00
global: split Akvorado into 3 services
This commit is contained in:
102
common/reporter/stack/root.go
Normal file
102
common/reporter/stack/root.go
Normal file
@@ -0,0 +1,102 @@
|
||||
// Package stack implements a very minimal version of the the stack
|
||||
// package from "gopkg.in/inconshreveable/log15.v2/stack"
|
||||
package stack
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// Call records a single function invocation from a goroutine stack. It is a
|
||||
// wrapper for the program counter values returned by runtime.Caller and
|
||||
// runtime.Callers and consumed by runtime.FuncForPC.
|
||||
type Call uintptr
|
||||
|
||||
// Trace records a sequence of function invocations from a goroutine stack.
|
||||
type Trace []Call
|
||||
|
||||
var pcStackPool = sync.Pool{
|
||||
New: func() interface{} { return make([]uintptr, 1000) },
|
||||
}
|
||||
|
||||
func poolBuf() []uintptr {
|
||||
return pcStackPool.Get().([]uintptr)
|
||||
}
|
||||
func putPoolBuf(p []uintptr) {
|
||||
pcStackPool.Put(p)
|
||||
}
|
||||
|
||||
// Callers return the list of callers from the current stack.
|
||||
func Callers() Trace {
|
||||
pcs := poolBuf()
|
||||
pcs = pcs[:cap(pcs)]
|
||||
n := runtime.Callers(2, pcs)
|
||||
cs := make([]Call, n)
|
||||
for i, pc := range pcs[:n] {
|
||||
cs[i] = Call(pc)
|
||||
}
|
||||
putPoolBuf(pcs)
|
||||
return cs
|
||||
}
|
||||
|
||||
// FunctionName provides the function name associated with the call
|
||||
// point. It includes the module name as well.
|
||||
func (pc Call) FunctionName() string {
|
||||
pcFix := uintptr(pc) - 1
|
||||
fn := runtime.FuncForPC(pcFix)
|
||||
if fn == nil {
|
||||
return "(nofunc)"
|
||||
}
|
||||
|
||||
name := fn.Name()
|
||||
return name
|
||||
}
|
||||
|
||||
// SourceFile returns the source file and optionally line number of
|
||||
// the call point. The source file is relative to the import point
|
||||
// (and includes it).
|
||||
func (pc Call) SourceFile(withLine bool) string {
|
||||
pcFix := uintptr(pc) - 1
|
||||
fn := runtime.FuncForPC(pcFix)
|
||||
if fn == nil {
|
||||
return "(nosource)"
|
||||
}
|
||||
|
||||
const sep = "/"
|
||||
file, line := fn.FileLine(pcFix)
|
||||
functionName := fn.Name()
|
||||
impCnt := strings.Count(functionName, sep)
|
||||
pathCnt := strings.Count(file, sep)
|
||||
for pathCnt > impCnt {
|
||||
i := strings.Index(file, sep)
|
||||
if i == -1 {
|
||||
break
|
||||
}
|
||||
file = file[i+len(sep):]
|
||||
pathCnt--
|
||||
}
|
||||
i := strings.Index(functionName, ".")
|
||||
if i == -1 {
|
||||
return "(nosource)"
|
||||
}
|
||||
moduleName := functionName[:i]
|
||||
i = strings.Index(moduleName, "/")
|
||||
if i != -1 {
|
||||
moduleName = moduleName[:i]
|
||||
}
|
||||
if withLine {
|
||||
return fmt.Sprintf("%s/%s:%d", moduleName, file, line)
|
||||
}
|
||||
return fmt.Sprintf("%s/%s", moduleName, file)
|
||||
}
|
||||
|
||||
var (
|
||||
ownPackageCall = Callers()[0]
|
||||
ownPackageName = strings.SplitN(ownPackageCall.FunctionName(), ".", 2)[0] // akvorado/common/reporter/stack
|
||||
parentPackageName = ownPackageName[0:strings.LastIndex(ownPackageName, "/")] // akvorado/common/reporter
|
||||
|
||||
// ModuleName is the name of the current module. This can be used to prefix stuff.
|
||||
ModuleName = strings.TrimSuffix(parentPackageName[0:strings.LastIndex(parentPackageName, "/")], "/common") // akvorado
|
||||
)
|
||||
Reference in New Issue
Block a user