/
runtime.go
78 lines (63 loc) · 1.98 KB
/
runtime.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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
package tracer
import (
"context"
"runtime"
"strings"
"go.opentelemetry.io/otel/api/kv"
"go.opentelemetry.io/otel/api/trace"
)
type RuntimeProvider struct {
root trace.Provider
}
func NewRuntimeProvider(root trace.Provider) *RuntimeProvider {
return &RuntimeProvider{root}
}
func (rp *RuntimeProvider) Tracer(name string, opts ...trace.TracerOption) trace.Tracer {
return &RuntimeTracer{
skipCall: 2,
root: rp.root.Tracer(name),
}
}
type RuntimeTracer struct {
skipCall int
root trace.Tracer
}
// Start identical to original start span, but automatically add runtime information to the span
func (rt *RuntimeTracer) Start(ctx context.Context, spanName string, opts ...trace.StartOption) (context.Context, trace.Span) {
callerName, pkgName := retrieveCaller(rt.skipCall)
opts = append(opts, trace.WithAttributes(
kv.String("runtime.package", pkgName),
kv.String("runtime.caller", callerName)))
if spanName == "" {
spanName = callerName
}
return rt.root.Start(ctx, spanName, opts...)
}
// WithSpan is identical to original start span, but automatically add runtime information to the span
func (rt *RuntimeTracer) WithSpan(ctx context.Context, spanName string, fn func(ctx context.Context) error, opts ...trace.StartOption) error {
callerName, pkgName := retrieveCaller(rt.skipCall)
opts = append(opts, trace.WithAttributes(
kv.String("runtime.package", pkgName),
kv.String("runtime.caller", callerName)))
if spanName == "" {
spanName = callerName
}
return rt.root.WithSpan(ctx, spanName, fn, opts...)
}
func retrieveCaller(skip int) (string, string) {
pc, _, _, ok := runtime.Caller(skip)
if !ok {
return "undefined", "undefined"
}
parts := strings.Split(runtime.FuncForPC(pc).Name(), ".")
pl := len(parts)
packageName := ""
funcName := parts[pl-1]
if parts[pl-2][0] == '(' {
funcName = parts[pl-2] + "." + funcName
packageName = strings.Join(parts[0:pl-2], ".")
} else {
packageName = strings.Join(parts[0:pl-1], ".")
}
return packageName, funcName
}