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