...
1 package tracing
2
3 import (
4 "io"
5 "os"
6 "strings"
7
8 "github.com/opentracing/opentracing-go"
9 "github.com/pkg/errors"
10
11 "github.com/ory/x/logrusx"
12
13 zipkinOT "github.com/openzipkin-contrib/zipkin-go-opentracing"
14 "github.com/openzipkin/zipkin-go"
15 zipkinHttp "github.com/openzipkin/zipkin-go/reporter/http"
16
17 jaegerConf "github.com/uber/jaeger-client-go/config"
18 jaegerZipkin "github.com/uber/jaeger-client-go/zipkin"
19
20 datadogOpentracer "gopkg.in/DataDog/dd-trace-go.v1/ddtrace/opentracer"
21 datadogTracer "gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer"
22
23 "go.elastic.co/apm"
24 "go.elastic.co/apm/module/apmot"
25 )
26
27
28 type Tracer struct {
29 Config *Config
30
31 l *logrusx.Logger
32 tracer opentracing.Tracer
33 closer io.Closer
34 }
35
36 func New(l *logrusx.Logger, c *Config) (*Tracer, error) {
37 t := &Tracer{Config: c, l: l}
38
39 if err := t.setup(); err != nil {
40 return nil, err
41 }
42
43 return t, nil
44 }
45
46
47 func (t *Tracer) setup() error {
48 switch strings.ToLower(t.Config.Provider) {
49 case "jaeger":
50 jc, err := jaegerConf.FromEnv()
51
52 if err != nil {
53 return err
54 }
55
56 if t.Config.Jaeger.SamplerServerURL != "" {
57 jc.Sampler.SamplingServerURL = t.Config.Jaeger.SamplerServerURL
58 }
59
60 if t.Config.Jaeger.SamplerType != "" {
61 jc.Sampler.Type = t.Config.Jaeger.SamplerType
62 }
63
64 if t.Config.Jaeger.SamplerValue != 0 {
65 jc.Sampler.Param = t.Config.Jaeger.SamplerValue
66 }
67
68 if t.Config.Jaeger.LocalAgentHostPort != "" {
69 jc.Reporter.LocalAgentHostPort = t.Config.Jaeger.LocalAgentHostPort
70 }
71
72 var configs []jaegerConf.Option
73
74
75 if t.Config.Jaeger.Propagation == "b3" {
76 zipkinPropagator := jaegerZipkin.NewZipkinB3HTTPHeaderPropagator()
77 configs = append(
78 configs,
79 jaegerConf.Injector(opentracing.HTTPHeaders, zipkinPropagator),
80 jaegerConf.Extractor(opentracing.HTTPHeaders, zipkinPropagator),
81 )
82 }
83
84 closer, err := jc.InitGlobalTracer(
85 t.Config.ServiceName,
86 configs...,
87 )
88
89 if err != nil {
90 return err
91 }
92
93 t.closer = closer
94 t.tracer = opentracing.GlobalTracer()
95 t.l.Infof("Jaeger tracer configured!")
96 case "zipkin":
97 if t.Config.Zipkin.ServerURL == "" {
98 return errors.Errorf("Zipkin's server url is required")
99 }
100
101 reporter := zipkinHttp.NewReporter(t.Config.Zipkin.ServerURL)
102
103 endpoint, err := zipkin.NewEndpoint(t.Config.ServiceName, "")
104
105 if err != nil {
106 return err
107 }
108
109 nativeTracer, err := zipkin.NewTracer(reporter, zipkin.WithLocalEndpoint(endpoint))
110
111 if err != nil {
112 return err
113 }
114
115 opentracing.SetGlobalTracer(zipkinOT.Wrap(nativeTracer))
116
117 t.closer = reporter
118 t.tracer = opentracing.GlobalTracer()
119 t.l.Infof("Zipkin tracer configured!")
120 case "datadog":
121 var serviceName = os.Getenv("DD_SERVICE")
122 if serviceName == "" {
123 serviceName = t.Config.ServiceName
124 }
125
126 opentracing.SetGlobalTracer(datadogOpentracer.New(datadogTracer.WithService(serviceName)))
127
128 t.closer = datadogCloser{}
129 t.tracer = opentracing.GlobalTracer()
130 t.l.Infof("DataDog tracer configured!")
131 case "elastic-apm":
132 var serviceName = os.Getenv("ELASTIC_APM_SERVICE_NAME")
133 if serviceName == "" {
134 serviceName = t.Config.ServiceName
135 }
136
137 tr, err := apm.NewTracer(serviceName, "")
138 if err != nil {
139 return err
140 }
141 opentracing.SetGlobalTracer(apmot.New(apmot.WithTracer(tr)))
142
143
144 t.tracer = opentracing.GlobalTracer()
145 t.l.Infof("Elastic APM tracer configured!")
146
147 case "":
148 t.l.Infof("No tracer configured - skipping tracing setup")
149 default:
150 return errors.Errorf("unknown tracer: %s", t.Config.Provider)
151 }
152 return nil
153 }
154
155
156 func (t *Tracer) IsLoaded() bool {
157 if t == nil || t.tracer == nil {
158 return false
159 }
160 return true
161 }
162
163
164 func (t *Tracer) Tracer() opentracing.Tracer {
165 return t.tracer
166 }
167
168
169 func (t *Tracer) Close() {
170 if t.closer != nil {
171 err := t.closer.Close()
172 if err != nil {
173 t.l.WithError(err).Error("Unable to close tracer.")
174 }
175 }
176 }
177
View as plain text