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