This is a client side library that implements an OpenTracing Tracer, with Zipkin-compatible data model.
import (
"github.com/opentracing/opentracing-go"
"github.com/uber/jaeger-client-go/config"
)
type AppConfig struct {
...
Tracing config.Configuration
...
}
func main() {
cfg := loadAppConfig() // e.g. from a yaml file
tracer, closer, err := cfg.Tracing.New("your-service-name", nil)
// check err
defer closer.Close()
opentracing.InitGlobalTracer(tracer)
...
}
The tracer emits a number of different metrics, defined in
metrics.go. The monitoring backend is expected to support
tag-based metric names, e.g. instead of statsd
-style string names
like counters.my-service.jaeger.spans.started.sampled
, the metrics
are defined by a short name and a collection of key/value tags, for
example: name:traces, state:started, sampled:true
.
The monitoring backend is represented by the
StatsReporter interface. An implementation
of that interface should be passed to the New
method during
tracer initialization:
stats := // create StatsReporter implementation
tracer := config.Tracing.New("your-service-name", stats)
By default, a no-op NullStatsReporter
is used.
The tracer can be configured with an optional logger, which will be
used to log communication errors, or log spans if a logging reporter
option is specified in the configuration. The logging API is abstracted
by the Logger interface. A logger instance implementing
this interface can be set on the Config
object before calling the
New
method.
Since this tracer is fully compliant with OpenTracing API 1.0, all code instrumentation should only use the API itself, as described in the [opentracing-go] (https://github.com/opentracing/opentracing-go) documentation.
A "reporter" is a component receives the finished spans and reports
them to somewhere. Under normal circumstances, the Tracer
should use the default RemoteReporter
, which sends the spans out of
process via configurable "transport". For testing purposes, one can
use an InMemoryReporter
that accumulates spans in a buffer and
allows to retrieve them for later verification. Also available are
NullReporter
, a no-op reporter that does nothing, a LoggingReporter
which logs all finished spans using their String()
method, and a
CompositeReporter
that can be used to combine more than one reporter
into one, e.g. to attach a logging reporter to the main remote reporter.
The remote reporter uses "transports" to actually send the spans out of process. Currently two supported transports are Thrift over UDP and Thrift over TChannel. More transports will be added in the future.
The only data format currently used is Zipkin Thrift 1.x span format, which allows easy integration of the tracer with Zipkin backend.
The tracer does not record all spans, but only those that have the
sampling bit set in the flags
. When a new trace is started and a new
unique ID is generated, a sampling decision is made whether this trace
should be sampled. The sampling decision is propagated to all downstream
calls via the flags
field of the trace context. The following samplers
are available:
RemotelyControlledSampler
uses one of the other simpler samplers and periodically updates it by polling an external server. This allows dynamic control of the sampling strategies.ConstSampler
always makes the same sampling decision for all trace IDs. it can be configured to either sample all traces, or to sample none.ProbabilisticSampler
uses a fixed sampling rate as a probability for a given trace to be sampled. The actual decision is made by comparing the trace ID with a random number multiplied by the sampling rate.RateLimitingSampler
can be used to allow only a certain fixed number of traces to be sampled per second.
The OpenTracing spec allows for baggage,
which are key value pairs that are added to the span context and propagated
throughout the trace.
An external process can inject baggage by setting the special
HTTP Header jaeger-baggage
on a request
curl -H "jaeger-baggage: key1=value1, key2=value2" http://myhost.com
Baggage can also be programatically set inside your service by doing the following
span.SetBaggageItem("key", "value")
The OpenTracing API defines a sampling.priority
standard tag that
can be used to affect the sampling of a span and its children:
import (
"github.com/opentracing/opentracing-go"
"github.com/opentracing/opentracing-go/ext"
)
span := opentracing.SpanFromContext(ctx)
ext.SamplingPriority.Set(span, 1)
Jaeger Tracer also understands a special HTTP Header jaeger-debug-id
,
which can be set in the incoming request, e.g.
curl -H "jaeger-debug-id: some-correlation-id" http://myhost.com
When Jaeger sees this header in the request that otherwise has no tracing context, it ensures that the new trace started for this request will be sampled in the "debug" mode (meaning it should survive all downsampling that might happen in the collection pipeline), and the root span will have a tag as if this statement was executed:
span.SetTag("jaeger-debug-id", "some-correlation-id")
This allows using Jaeger UI to find the trace by this tag.