/
trace.go
38 lines (33 loc) · 859 Bytes
/
trace.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
package fn
import (
"go/build"
"path/filepath"
"reflect"
"runtime"
"strconv"
)
func WithTrace[F any](f F, logger interface{ Println(v ...any) }) F {
vf := reflect.ValueOf(f)
typ := vf.Type()
if typ.Kind() != reflect.Func {
panic("fn: WithTrace(non-function " + typ.String() + ")")
}
var call func([]reflect.Value) []reflect.Value
if typ.IsVariadic() {
call = vf.CallSlice
} else {
call = vf.Call
}
funcName := runtime.FuncForPC(vf.Pointer()).Name()
return reflect.MakeFunc(typ, func(args []reflect.Value) []reflect.Value {
_, file, line, _ := runtime.Caller(1)
for _, gopath := range filepath.SplitList(build.Default.GOPATH) {
if rel, err := filepath.Rel(gopath, file); err == nil {
file = rel
break
}
}
logger.Println("[TRACE]", file+":"+strconv.Itoa(line), funcName)
return call(args)
}).Interface().(F)
}