-
Notifications
You must be signed in to change notification settings - Fork 288
/
tracer.go
150 lines (125 loc) · 3.48 KB
/
tracer.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
144
145
146
147
148
149
150
package tracer
import (
"context"
"fmt"
"log"
"os"
"strings"
"github.com/pkg/errors"
"github.com/lightstep/lightstep-tracer-go"
"github.com/opentracing/opentracing-go"
zipkin "github.com/openzipkin/zipkin-go-opentracing"
jaeger "github.com/uber/jaeger-client-go"
jaegercfg "github.com/uber/jaeger-client-go/config"
"github.com/windmilleng/tilt/pkg/logger"
)
const windmillTracerHostPort = "opentracing.windmill.build:9411"
type TracerBackend int
const (
Windmill TracerBackend = iota
Lightstep
Jaeger
)
type zipkinLogger struct {
ctx context.Context
}
func (zl zipkinLogger) Log(keyvals ...interface{}) error {
logger.Get(zl.ctx).Debugf("%v", keyvals)
return nil
}
var _ zipkin.Logger = zipkinLogger{}
func Init(ctx context.Context, tracer TracerBackend) (func() error, error) {
switch tracer {
case Windmill:
return initWindmillZipkin(ctx)
case Lightstep:
return initLightStep(ctx)
case Jaeger:
return initJaeger(ctx)
default:
return nil, fmt.Errorf("Init: Invalid Tracer backend: %d", tracer)
}
}
func TraceID(ctx context.Context) (string, error) {
spanContext := opentracing.SpanFromContext(ctx)
if spanContext == nil {
return "", errors.New("cannot get traceid - there is no span context")
}
switch t := spanContext.Context().(type) {
case zipkin.SpanContext:
return t.TraceID.ToHex(), nil
case lightstep.SpanContext:
return string(t.TraceID), nil
case jaeger.SpanContext:
return t.TraceID().String(), nil
default:
return "", errors.New("cannot get traceid - unknown span type")
}
}
// TagStrToMap converts a user-passed string of tags of the form `key1=val1,key2=val2` to a map.
func TagStrToMap(tagStr string) map[string]string {
if tagStr == "" {
return nil
}
res := make(map[string]string)
pairs := strings.Split(tagStr, ",")
for _, p := range pairs {
elems := strings.Split(strings.TrimSpace(p), "=")
if len(elems) != 2 {
log.Printf("got malformed trace tag: %s", p)
continue
}
res[elems[0]] = elems[1]
}
return res
}
func StringToTracerBackend(s string) (TracerBackend, error) {
switch s {
case "windmill":
return Windmill, nil
case "lightstep":
return Lightstep, nil
case "jaeger":
return Jaeger, nil
default:
return Windmill, fmt.Errorf("Invalid Tracer backend: %s", s)
}
}
func initWindmillZipkin(ctx context.Context) (func() error, error) {
collector, err := zipkin.NewHTTPCollector(fmt.Sprintf("http://%s/api/v1/spans", windmillTracerHostPort), zipkin.HTTPLogger(zipkinLogger{ctx}))
if err != nil {
return nil, errors.Wrap(err, "unable to create zipkin collector")
}
recorder := zipkin.NewRecorder(collector, true, "0.0.0.0:0", "tilt")
tracer, err := zipkin.NewTracer(recorder)
if err != nil {
return nil, errors.Wrap(err, "unable to create tracer")
}
opentracing.SetGlobalTracer(tracer)
return collector.Close, nil
}
func initLightStep(ctx context.Context) (func() error, error) {
token, ok := os.LookupEnv("LIGHTSTEP_ACCESS_TOKEN")
if !ok {
return nil, fmt.Errorf("No token found in the LIGHTSTEP_ACCESS_TOKEN environment variable")
}
lightstepTracer := lightstep.NewTracer(lightstep.Options{
AccessToken: token,
})
opentracing.SetGlobalTracer(lightstepTracer)
close := func() error {
lightstepTracer.Close(context.Background())
return nil
}
return close, nil
}
func initJaeger(ctx context.Context) (func() error, error) {
cfg := jaegercfg.Configuration{
Sampler: &jaegercfg.SamplerConfig{
Type: "const",
Param: 1,
},
}
closer, err := cfg.InitGlobalTracer("tilt")
return closer.Close, err
}