forked from afocus/trace
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcore.go
143 lines (124 loc) · 3.15 KB
/
core.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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
package trace
import (
"context"
"fmt"
"sync"
"time"
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/codes"
"go.opentelemetry.io/otel/trace"
)
var defaultTracker = otel.Tracer("github.com/afocus/trace")
func GetDefaultTracer() trace.Tracer {
return defaultTracker
}
type Trace struct {
r *zerolog.Logger
begin time.Time
spanName string
spanAttrs []attribute.KeyValue
span trace.Span
}
var traceSpanPool = &sync.Pool{New: func() interface{} {
return &Trace{}
}}
func GetLog(c context.Context) *zerolog.Logger {
if span := trace.SpanFromContext(c); span.SpanContext().IsValid() {
logger := log.With().
Str("spanID", span.SpanContext().SpanID().String()).
Str("traceID", span.SpanContext().TraceID().String()).
Logger()
return &logger
}
return &log.Logger
}
func GetTraceID(c context.Context) string {
if span := trace.SpanFromContext(c); span.SpanContext().IsValid() {
return span.SpanContext().TraceID().String()
}
return ""
}
func Attribute(key string, v interface{}) attribute.KeyValue {
switch value := v.(type) {
case int:
return attribute.Int(key, value)
case int64:
return attribute.Int64(key, value)
case bool:
return attribute.Bool(key, value)
case float32:
return attribute.Float64(key, float64(value))
case float64:
return attribute.Float64(key, value)
case fmt.Stringer:
return attribute.Stringer(key, value)
default:
return attribute.String(key, fmt.Sprintf("%+v", value))
}
}
// Start 从上下文开始一次链路追踪
// param name 轨迹的名字
// param attrs 附加属性 可以记录一些额外的信息 将会记录到链路追踪里
func Start(c context.Context, name string, attrs ...attribute.KeyValue) (*Trace, context.Context) {
ctx, span := defaultTracker.Start(c, name)
tr := traceSpanPool.Get().(*Trace)
tr.begin = time.Now()
tr.r = GetLog(ctx)
tr.spanName = name
tr.spanAttrs = attrs
tr.span = span
return tr, context.WithValue(ctx, traceLogContextKey{}, tr)
}
func (l *Trace) SetAttributes(attrs ...attribute.KeyValue) {
l.spanAttrs = append(l.spanAttrs, attrs...)
}
func FromContext(c context.Context) *Trace {
if v := c.Value(traceLogContextKey{}); v != nil {
lc, ok := v.(*Trace)
if ok {
return lc
}
}
return nil
}
type traceLogContextKey struct{}
func (l *Trace) Log() *zerolog.Logger {
if l.r == nil {
return &log.Logger
}
return l.r
}
func (l *Trace) Begin() time.Time {
return l.begin
}
func (l *Trace) Name() string {
return l.spanName
}
func (l *Trace) TraceID() string {
return l.span.SpanContext().TraceID().String()
}
func (l *Trace) SpanID() string {
return l.span.SpanContext().SpanID().String()
}
func (l *Trace) End(err ...error) {
p := l.Log().Info()
if len(err) > 0 {
if err[0] == nil {
l.span.SetStatus(codes.Ok, "")
} else {
l.span.SetStatus(codes.Error, err[0].Error())
p = l.Log().Error().Err(err[0])
}
}
for _, v := range l.spanAttrs {
p.Interface(string(v.Key), v.Value.AsInterface())
}
p.Dur("duration", time.Since(l.Begin()))
p.Msg(l.spanName)
l.span.SetAttributes(l.spanAttrs...)
l.span.End()
traceSpanPool.Put(l)
}