1[![GoDoc][doc-img]][doc] [![Build Status][ci-img]][ci] [![Coverage Status][cov-img]][cov] [![OpenTracing 1.0 Enabled][ot-img]][ot-url]
2
3# Jaeger Bindings for Go OpenTracing API
4
5Instrumentation library that implements an
6[OpenTracing](http://opentracing.io) Tracer for Jaeger (https://jaegertracing.io).
7
8**IMPORTANT**: The library's import path is based on its original location under `github.com/uber`. Do not try to import it as `github.com/jaegertracing`, it will not compile. We might revisit this in the next major release.
9  * :white_check_mark: `import "github.com/uber/jaeger-client-go"`
10  * :x: `import "github.com/jaegertracing/jaeger-client-go"`
11
12## How to Contribute
13
14Please see [CONTRIBUTING.md](CONTRIBUTING.md).
15
16## Installation
17
18We recommended using a dependency manager like [glide](https://github.com/Masterminds/glide)
19and [semantic versioning](http://semver.org/) when including this library into an application.
20For example, Jaeger backend imports this library like this:
21
22```yaml
23- package: github.com/uber/jaeger-client-go
24  version: ^2.7.0
25```
26
27If you instead want to use the latest version in `master`, you can pull it via `go get`.
28Note that during `go get` you may see build errors due to incompatible dependencies, which is why
29we recommend using semantic versions for dependencies.  The error  may be fixed by running
30`make install` (it will install `glide` if you don't have it):
31
32```shell
33go get -u github.com/uber/jaeger-client-go/
34cd $GOPATH/src/github.com/uber/jaeger-client-go/
35git submodule update --init --recursive
36make install
37```
38
39## Initialization
40
41See tracer initialization examples in [godoc](https://godoc.org/github.com/uber/jaeger-client-go/config#pkg-examples)
42and [config/example_test.go](./config/example_test.go).
43
44### Environment variables
45
46The tracer can be initialized with values coming from environment variables. None of the env vars are required
47and all of them can be overriden via direct setting of the property on the configuration object.
48
49Property| Description
50--- | ---
51JAEGER_SERVICE_NAME | The service name
52JAEGER_AGENT_HOST | The hostname for communicating with agent via UDP
53JAEGER_AGENT_PORT | The port for communicating with agent via UDP
54JAEGER_ENDPOINT | The HTTP endpoint for sending spans directly to a collector, i.e. http://jaeger-collector:14268/api/traces
55JAEGER_USER | Username to send as part of "Basic" authentication to the collector endpoint
56JAEGER_PASSWORD | Password to send as part of "Basic" authentication to the collector endpoint
57JAEGER_REPORTER_LOG_SPANS | Whether the reporter should also log the spans
58JAEGER_REPORTER_MAX_QUEUE_SIZE | The reporter's maximum queue size
59JAEGER_REPORTER_FLUSH_INTERVAL | The reporter's flush interval, with units, e.g. "500ms" or "2s" ([valid units][timeunits])
60JAEGER_SAMPLER_TYPE | The sampler type
61JAEGER_SAMPLER_PARAM | The sampler parameter (number)
62JAEGER_SAMPLER_MANAGER_HOST_PORT | The HTTP endpoint when using the remote sampler, i.e. http://jaeger-agent:5778/sampling
63JAEGER_SAMPLER_MAX_OPERATIONS | The maximum number of operations that the sampler will keep track of
64JAEGER_SAMPLER_REFRESH_INTERVAL | How often the remotely controlled sampler will poll jaeger-agent for the appropriate sampling strategy, with units, e.g. "1m" or "30s" ([valid units][timeunits])
65JAEGER_TAGS | A comma separated list of `name = value` tracer level tags, which get added to all reported spans. The value can also refer to an environment variable using the format `${envVarName:default}`, where the `:default` is optional, and identifies a value to be used if the environment variable cannot be found
66JAEGER_DISABLED | Whether the tracer is disabled or not. If true, the default `opentracing.NoopTracer` is used.
67JAEGER_RPC_METRICS | Whether to store RPC metrics
68
69By default, the client sends traces via UDP to the agent at `localhost:6831`. Use `JAEGER_AGENT_HOST` and
70`JAEGER_AGENT_PORT` to send UDP traces to a different `host:port`. If `JAEGER_ENDPOINT` is set, the client sends traces
71to the endpoint via `HTTP`, making the `JAEGER_AGENT_HOST` and `JAEGER_AGENT_PORT` unused. If `JAEGER_ENDPOINT` is
72secured, HTTP basic authentication can be performed by setting the `JAEGER_USER` and `JAEGER_PASSWORD` environment
73variables.
74
75### Closing the tracer via `io.Closer`
76
77The constructor function for Jaeger Tracer returns the tracer itself and an `io.Closer` instance.
78It is recommended to structure your `main()` so that it calls the `Close()` function on the closer
79before exiting, e.g.
80
81```go
82tracer, closer, err := cfg.NewTracer(...)
83defer closer.Close()
84```
85
86This is especially useful for command-line tools that enable tracing, as well as
87for the long-running apps that support graceful shutdown. For example, if your deployment
88system sends SIGTERM instead of killing the process and you trap that signal to do a graceful
89exit, then having `defer closer.Closer()` ensures that all buffered spans are flushed.
90
91### Metrics & Monitoring
92
93The tracer emits a number of different metrics, defined in
94[metrics.go](metrics.go). The monitoring backend is expected to support
95tag-based metric names, e.g. instead of `statsd`-style string names
96like `counters.my-service.jaeger.spans.started.sampled`, the metrics
97are defined by a short name and a collection of key/value tags, for
98example: `name:jaeger.traces, state:started, sampled:y`. See [metrics.go](./metrics.go)
99file for the full list and descriptions of emitted metrics.
100
101The monitoring backend is represented by the `metrics.Factory` interface from package
102[`"github.com/uber/jaeger-lib/metrics"`](https://github.com/jaegertracing/jaeger-lib/tree/master/metrics).  An implementation
103of that interface can be passed as an option to either the Configuration object or the Tracer
104constructor, for example:
105
106```go
107import (
108    "github.com/uber/jaeger-client-go/config"
109    "github.com/uber/jaeger-lib/metrics/prometheus"
110)
111
112    metricsFactory := prometheus.New()
113    tracer, closer, err := config.Configuration{
114        ServiceName: "your-service-name",
115    }.NewTracer(
116        config.Metrics(metricsFactory),
117    )
118```
119
120By default, a no-op `metrics.NullFactory` is used.
121
122### Logging
123
124The tracer can be configured with an optional logger, which will be
125used to log communication errors, or log spans if a logging reporter
126option is specified in the configuration. The logging API is abstracted
127by the [Logger](logger.go) interface. A logger instance implementing
128this interface can be set on the `Config` object before calling the
129`New` method.
130
131Besides the [zap](https://github.com/uber-go/zap) implementation
132bundled with this package there is also a [go-kit](https://github.com/go-kit/kit)
133one in the [jaeger-lib](https://github.com/jaegertracing/jaeger-lib) repository.
134
135## Instrumentation for Tracing
136
137Since this tracer is fully compliant with OpenTracing API 1.0,
138all code instrumentation should only use the API itself, as described
139in the [opentracing-go](https://github.com/opentracing/opentracing-go) documentation.
140
141## Features
142
143### Reporters
144
145A "reporter" is a component that receives the finished spans and reports
146them to somewhere. Under normal circumstances, the Tracer
147should use the default `RemoteReporter`, which sends the spans out of
148process via configurable "transport". For testing purposes, one can
149use an `InMemoryReporter` that accumulates spans in a buffer and
150allows to retrieve them for later verification. Also available are
151`NullReporter`, a no-op reporter that does nothing, a `LoggingReporter`
152which logs all finished spans using their `String()` method, and a
153`CompositeReporter` that can be used to combine more than one reporter
154into one, e.g. to attach a logging reporter to the main remote reporter.
155
156### Span Reporting Transports
157
158The remote reporter uses "transports" to actually send the spans out
159of process. Currently the supported transports include:
160  * [Jaeger Thrift](https://github.com/jaegertracing/jaeger-idl/blob/master/thrift/agent.thrift) over UDP or HTTP,
161  * [Zipkin Thrift](https://github.com/jaegertracing/jaeger-idl/blob/master/thrift/zipkincore.thrift) over HTTP.
162
163### Sampling
164
165The tracer does not record all spans, but only those that have the
166sampling bit set in the `flags`. When a new trace is started and a new
167unique ID is generated, a sampling decision is made whether this trace
168should be sampled. The sampling decision is propagated to all downstream
169calls via the `flags` field of the trace context. The following samplers
170are available:
171  1. `RemotelyControlledSampler` uses one of the other simpler samplers
172     and periodically updates it by polling an external server. This
173     allows dynamic control of the sampling strategies.
174  1. `ConstSampler` always makes the same sampling decision for all
175     trace IDs. it can be configured to either sample all traces, or
176     to sample none.
177  1. `ProbabilisticSampler` uses a fixed sampling rate as a probability
178     for a given trace to be sampled. The actual decision is made by
179     comparing the trace ID with a random number multiplied by the
180     sampling rate.
181  1. `RateLimitingSampler` can be used to allow only a certain fixed
182     number of traces to be sampled per second.
183
184### Baggage Injection
185
186The OpenTracing spec allows for [baggage][baggage], which are key value pairs that are added
187to the span context and propagated throughout the trace. An external process can inject baggage
188by setting the special HTTP Header `jaeger-baggage` on a request:
189
190```sh
191curl -H "jaeger-baggage: key1=value1, key2=value2" http://myhost.com
192```
193
194Baggage can also be programatically set inside your service:
195
196```go
197if span := opentracing.SpanFromContext(ctx); span != nil {
198    span.SetBaggageItem("key", "value")
199}
200```
201
202Another service downstream of that can retrieve the baggage in a similar way:
203
204```go
205if span := opentracing.SpanFromContext(ctx); span != nil {
206    val := span.BaggageItem("key")
207    println(val)
208}
209```
210
211### Debug Traces (Forced Sampling)
212
213#### Programmatically
214
215The OpenTracing API defines a `sampling.priority` standard tag that
216can be used to affect the sampling of a span and its children:
217
218```go
219import (
220    "github.com/opentracing/opentracing-go"
221    "github.com/opentracing/opentracing-go/ext"
222)
223
224span := opentracing.SpanFromContext(ctx)
225ext.SamplingPriority.Set(span, 1)
226```
227
228#### Via HTTP Headers
229
230Jaeger Tracer also understands a special HTTP Header `jaeger-debug-id`,
231which can be set in the incoming request, e.g.
232
233```sh
234curl -H "jaeger-debug-id: some-correlation-id" http://myhost.com
235```
236
237When Jaeger sees this header in the request that otherwise has no
238tracing context, it ensures that the new trace started for this
239request will be sampled in the "debug" mode (meaning it should survive
240all downsampling that might happen in the collection pipeline), and the
241root span will have a tag as if this statement was executed:
242
243```go
244span.SetTag("jaeger-debug-id", "some-correlation-id")
245```
246
247This allows using Jaeger UI to find the trace by this tag.
248
249### Zipkin HTTP B3 compatible header propagation
250
251Jaeger Tracer supports Zipkin B3 Propagation HTTP headers, which are used
252by a lot of Zipkin tracers. This means that you can use Jaeger in conjunction with e.g. [these OpenZipkin tracers](https://github.com/openzipkin).
253
254However it is not the default propagation format, see [here](zipkin/README.md#NewZipkinB3HTTPHeaderPropagator) how to set it up.
255
256## License
257
258[Apache 2.0 License](LICENSE).
259
260
261[doc-img]: https://godoc.org/github.com/uber/jaeger-client-go?status.svg
262[doc]: https://godoc.org/github.com/uber/jaeger-client-go
263[ci-img]: https://travis-ci.org/jaegertracing/jaeger-client-go.svg?branch=master
264[ci]: https://travis-ci.org/jaegertracing/jaeger-client-go
265[cov-img]: https://codecov.io/gh/jaegertracing/jaeger-client-go/branch/master/graph/badge.svg
266[cov]: https://codecov.io/gh/jaegertracing/jaeger-client-go
267[ot-img]: https://img.shields.io/badge/OpenTracing--1.0-enabled-blue.svg
268[ot-url]: http://opentracing.io
269[baggage]: https://github.com/opentracing/specification/blob/master/specification.md#set-a-baggage-item
270[timeunits]: https://golang.org/pkg/time/#ParseDuration
271