README

Zipkin Library for Go

Travis CI CircleCI Appveyor CI Coverage Status Go Report Card GoDoc Gitter chat Sourcegraph

Zipkin Go is the official Go Tracer implementation for Zipkin, supported by the OpenZipkin community.

package organization

zipkin-go is built with interoperability in mind within the OpenZipkin community and even 3rd parties, the library consists of several packages.

The main tracing implementation can be found in the root folder of this repository. Reusable parts not considered core implementation or deemed beneficiary for usage by others are placed in their own packages within this repository.

model

This library implements the Zipkin V2 Span Model which is available in the model package. It contains a Go data model compatible with the Zipkin V2 API and can automatically sanitize, parse and (de)serialize to and from the required JSON representation as used by the official Zipkin V2 Collectors.

propagation

The propagation package and B3 subpackage hold the logic for propagating SpanContext (span identifiers and sampling flags) between services participating in traces. Currently Zipkin B3 Propagation is supported for HTTP and GRPC.

middleware

The middleware subpackages contain officially supported middleware handlers and tracing wrappers.

http

An easy to use http.Handler middleware for tracing server side requests is provided. This allows one to use this middleware in applications using standard library servers as well as most available higher level frameworks. Some frameworks will have their own instrumentation and middleware that maps better for their ecosystem.

For HTTP client operations NewTransport can return a http.RoundTripper implementation that can either wrap the standard http.Client's Transport or a custom provided one and add per request tracing. Since HTTP Requests can have one or multiple redirects it is advisable to always enclose HTTP Client calls with a Span either around the *http.Client call level or parent function level.

For convenience NewClient is provided which returns a HTTP Client which embeds *http.Client and provides an application span around the HTTP calls when calling the DoWithAppSpan() method.

grpc

Easy to use grpc.StatsHandler middleware are provided for tracing gRPC server and client requests.

For a server, pass NewServerHandler when calling NewServer, e.g.,

import (
	"google.golang.org/grpc"
	zipkingrpc "github.com/openzipkin/zipkin-go/middleware/grpc"
)

server = grpc.NewServer(grpc.StatsHandler(zipkingrpc.NewServerHandler(tracer)))

For a client, pass NewClientHandler when calling Dial, e.g.,

import (
	"google.golang.org/grpc"
	zipkingrpc "github.com/openzipkin/zipkin-go/middleware/grpc"
)

conn, err = grpc.Dial(addr, grpc.WithStatsHandler(zipkingrpc.NewClientHandler(tracer)))
reporter

The reporter package holds the interface which the various Reporter implementations use. It is exported into its own package as it can be used by 3rd parties to use these Reporter packages in their own libraries for exporting to the Zipkin ecosystem. The zipkin-go tracer also uses the interface to accept 3rd party Reporter implementations.

HTTP Reporter

Most common Reporter type used by Zipkin users transporting Spans to the Zipkin server using JSON over HTTP. The reporter holds a buffer and reports to the backend asynchronously.

Kafka Reporter

High performance Reporter transporting Spans to the Zipkin server using a Kafka Producer digesting JSON V2 Spans. The reporter uses the Sarama async producer underneath.

usage and examples

HTTP Server Example

Expand ▾ Collapse ▴

Documentation

Overview

    Package zipkin implements a native Zipkin instrumentation library for Go.

    See https://zipkin.io for more information about Zipkin.

    Example

    Code:

    package main
    
    import (
    	"log"
    	"net/http"
    	"net/http/httptest"
    	"os"
    	"time"
    
    	"github.com/gorilla/mux"
    
    	zipkin "github.com/openzipkin/zipkin-go"
    	zipkinhttp "github.com/openzipkin/zipkin-go/middleware/http"
    	logreporter "github.com/openzipkin/zipkin-go/reporter/log"
    )
    
    func main() {
    	// set up a span reporter
    	reporter := logreporter.NewReporter(log.New(os.Stderr, "", log.LstdFlags))
    	defer reporter.Close()
    
    	// create our local service endpoint
    	endpoint, err := zipkin.NewEndpoint("myService", "localhost:0")
    	if err != nil {
    		log.Fatalf("unable to create local endpoint: %+v\n", err)
    	}
    
    	// initialize our tracer
    	tracer, err := zipkin.NewTracer(reporter, zipkin.WithLocalEndpoint(endpoint))
    	if err != nil {
    		log.Fatalf("unable to create tracer: %+v\n", err)
    	}
    
    	// create global zipkin http server middleware
    	serverMiddleware := zipkinhttp.NewServerMiddleware(
    		tracer, zipkinhttp.TagResponseSize(true),
    	)
    
    	// create global zipkin traced http client
    	client, err := zipkinhttp.NewClient(tracer, zipkinhttp.ClientTrace(true))
    	if err != nil {
    		log.Fatalf("unable to create client: %+v\n", err)
    	}
    
    	// initialize router
    	router := mux.NewRouter()
    
    	// start web service with zipkin http server middleware
    	ts := httptest.NewServer(serverMiddleware(router))
    	defer ts.Close()
    
    	// set-up handlers
    	router.Methods("GET").Path("/some_function").HandlerFunc(someFunc(client, ts.URL))
    	router.Methods("POST").Path("/other_function").HandlerFunc(otherFunc(client))
    
    	// initiate a call to some_func
    	req, err := http.NewRequest("GET", ts.URL+"/some_function", nil)
    	if err != nil {
    		log.Fatalf("unable to create http request: %+v\n", err)
    	}
    
    	res, err := client.DoWithAppSpan(req, "some_function")
    	if err != nil {
    		log.Fatalf("unable to do http request: %+v\n", err)
    	}
    	res.Body.Close()
    
    }
    
    func someFunc(client *zipkinhttp.Client, url string) http.HandlerFunc {
    	return func(w http.ResponseWriter, r *http.Request) {
    		log.Printf("some_function called with method: %s\n", r.Method)
    
    		// retrieve span from context (created by server middleware)
    		span := zipkin.SpanFromContext(r.Context())
    		span.Tag("custom_key", "some value")
    
    		// doing some expensive calculations....
    		time.Sleep(25 * time.Millisecond)
    		span.Annotate(time.Now(), "expensive_calc_done")
    
    		newRequest, err := http.NewRequest("POST", url+"/other_function", nil)
    		if err != nil {
    			log.Printf("unable to create client: %+v\n", err)
    			http.Error(w, err.Error(), 500)
    			return
    		}
    
    		ctx := zipkin.NewContext(newRequest.Context(), span)
    
    		newRequest = newRequest.WithContext(ctx)
    
    		res, err := client.DoWithAppSpan(newRequest, "other_function")
    		if err != nil {
    			log.Printf("call to other_function returned error: %+v\n", err)
    			http.Error(w, err.Error(), 500)
    			return
    		}
    		res.Body.Close()
    	}
    }
    
    func otherFunc(client *zipkinhttp.Client) http.HandlerFunc {
    	return func(w http.ResponseWriter, r *http.Request) {
    		log.Printf("other_function called with method: %s\n", r.Method)
    		time.Sleep(50 * time.Millisecond)
    	}
    }
    
    
    

    Index

    Examples

    Constants

    This section is empty.

    Variables

    View Source
    var (
    	ErrInvalidEndpoint             = errors.New("requires valid local endpoint")
    	ErrInvalidExtractFailurePolicy = errors.New("invalid extract failure policy provided")
    )

      Tracer Option Errors

      Functions

      func AlwaysSample

      func AlwaysSample(_ uint64) bool

        AlwaysSample will always return true. If used by a service it will always start traces if no upstream trace has been propagated. If an incoming upstream trace is not sampled the service will adhere to this and only propagate the context.

        func NeverSample

        func NeverSample(_ uint64) bool

          NeverSample will always return false. If used by a service it will not allow the service to start traces but will still allow the service to participate in traces started upstream.

          func NewContext

          func NewContext(ctx context.Context, s Span) context.Context

            NewContext stores a Zipkin Span into Go's context propagation mechanism.

            Example

            Code:

            package main
            
            import (
            	"context"
            
            	zipkin "github.com/openzipkin/zipkin-go"
            	"github.com/openzipkin/zipkin-go/reporter"
            )
            
            func doSomeWork(context.Context) {}
            
            func main() {
            	var (
            		tracer, _ = zipkin.NewTracer(reporter.NewNoopReporter())
            		ctx       = context.Background()
            	)
            
            	// span for this function
            	span := tracer.StartSpan("ExampleNewContext")
            	defer span.Finish()
            
            	// add span to Context
            	ctx = zipkin.NewContext(ctx, span)
            
            	// pass along Context which holds the span to another function
            	doSomeWork(ctx)
            
            }
            
            
            

            func NewEndpoint

            func NewEndpoint(serviceName string, hostPort string) (*model.Endpoint, error)

              NewEndpoint creates a new endpoint given the provided serviceName and hostPort.

              Types

              type ExtractFailurePolicy

              type ExtractFailurePolicy int

                ExtractFailurePolicy deals with Extraction errors

                const (
                	ExtractFailurePolicyRestart ExtractFailurePolicy = iota
                	ExtractFailurePolicyError
                	ExtractFailurePolicyTagAndRestart
                )

                  ExtractFailurePolicyOptions

                  type Sampler

                  type Sampler func(id uint64) bool

                    Sampler functions return if a Zipkin span should be sampled, based on its traceID.

                    func NewBoundarySampler

                    func NewBoundarySampler(rate float64, salt int64) (Sampler, error)

                      NewBoundarySampler is appropriate for high-traffic instrumentation who provision random trace ids, and make the sampling decision only once. It defends against nodes in the cluster selecting exactly the same ids.

                      func NewCountingSampler

                      func NewCountingSampler(rate float64) (Sampler, error)

                        NewCountingSampler is appropriate for low-traffic instrumentation or those who do not provision random trace ids. It is not appropriate for collectors as the sampling decision isn't idempotent (consistent based on trace id).

                        func NewModuloSampler

                        func NewModuloSampler(mod uint64) Sampler

                          NewModuloSampler provides a generic type Sampler.

                          type Span

                          type Span interface {
                          	// Context returns the Span's SpanContext.
                          	Context() model.SpanContext
                          
                          	// SetName updates the Span's name.
                          	SetName(string)
                          
                          	// SetRemoteEndpoint updates the Span's Remote Endpoint.
                          	SetRemoteEndpoint(*model.Endpoint)
                          
                          	// Annotate adds a timed event to the Span.
                          	Annotate(time.Time, string)
                          
                          	// Tag sets Tag with given key and value to the Span. If key already exists in
                          	// the Span the value will be overridden except for error tags where the first
                          	// value is persisted.
                          	Tag(string, string)
                          
                          	// Finish the Span and send to Reporter. If DelaySend option was used at
                          	// Span creation time, Finish will not send the Span to the Reporter. It then
                          	// becomes the user's responsibility to get the Span reported (by using
                          	// span.Flush).
                          	Finish()
                          
                          	// Finish the Span with duration and send to Reporter. If DelaySend option was used at
                          	// Span creation time, FinishedWithDuration will not send the Span to the Reporter. It then
                          	// becomes the user's responsibility to get the Span reported (by using
                          	// span.Flush).
                          	FinishedWithDuration(duration time.Duration)
                          
                          	// Flush the Span to the Reporter (regardless of being finished or not).
                          	// This can be used if the DelaySend SpanOption was set or when dealing with
                          	// one-way RPC tracing where duration might not be measured.
                          	Flush()
                          }

                            Span interface as returned by Tracer.StartSpan()

                            func SpanFromContext

                            func SpanFromContext(ctx context.Context) Span

                              SpanFromContext retrieves a Zipkin Span from Go's context propagation mechanism if found. If not found, returns nil.

                              func SpanOrNoopFromContext

                              func SpanOrNoopFromContext(ctx context.Context) Span

                                SpanOrNoopFromContext retrieves a Zipkin Span from Go's context propagation mechanism if found. If not found, returns a noopSpan. This function typically is used for modules that want to provide existing Zipkin spans with additional data, but can't guarantee that spans are properly propagated. It is preferred to use SpanFromContext() and test for Nil instead of using this function.

                                type SpanOption

                                type SpanOption func(t *Tracer, s *spanImpl)

                                  SpanOption allows for functional options to adjust behavior and payload of the Span to be created with tracer.StartSpan().

                                  Example

                                  Code:

                                  package main
                                  
                                  import (
                                  	"log"
                                  
                                  	zipkin "github.com/openzipkin/zipkin-go"
                                  	"github.com/openzipkin/zipkin-go/model"
                                  	"github.com/openzipkin/zipkin-go/reporter"
                                  )
                                  
                                  func main() {
                                  	tracer, _ := zipkin.NewTracer(reporter.NewNoopReporter())
                                  
                                  	// set-up the remote endpoint for the service we're about to call
                                  	endpoint, err := zipkin.NewEndpoint("otherService", "172.20.23.101:80")
                                  	if err != nil {
                                  		log.Fatalf("unable to create remote endpoint: %+v\n", err)
                                  	}
                                  
                                  	// start a client side RPC span and use RemoteEndpoint SpanOption
                                  	span := tracer.StartSpan(
                                  		"some-operation",
                                  		zipkin.RemoteEndpoint(endpoint),
                                  		zipkin.Kind(model.Client),
                                  	)
                                  	// ... call other service ...
                                  	span.Finish()
                                  
                                  }
                                  
                                  
                                  

                                  func FlushOnFinish

                                  func FlushOnFinish(b bool) SpanOption

                                    FlushOnFinish when set to false will disable span.Finish() to send the Span to the Reporter automatically (which is the default behavior). If set to false, having the Span be reported becomes the responsibility of the user. This is available if late tag data is expected to be only available after the required finish time of the Span.

                                    func Kind

                                    func Kind(kind model.Kind) SpanOption

                                      Kind sets the kind of the span being created..

                                      func Parent

                                      func Parent(sc model.SpanContext) SpanOption

                                        Parent will use provided SpanContext as parent to the span being created.

                                        func RemoteEndpoint

                                        func RemoteEndpoint(e *model.Endpoint) SpanOption

                                          RemoteEndpoint sets the remote endpoint of the span being created.

                                          func StartTime

                                          func StartTime(start time.Time) SpanOption

                                            StartTime uses a given start time for the span being created.

                                            func Tags

                                            func Tags(tags map[string]string) SpanOption

                                              Tags sets initial tags for the span being created. If default tracer tags are present they will be overwritten on key collisions.

                                              type Tag

                                              type Tag string

                                                Tag holds available types

                                                const (
                                                	TagHTTPMethod       Tag = "http.method"
                                                	TagHTTPPath         Tag = "http.path"
                                                	TagHTTPUrl          Tag = "http.url"
                                                	TagHTTPRoute        Tag = "http.route"
                                                	TagHTTPStatusCode   Tag = "http.status_code"
                                                	TagHTTPRequestSize  Tag = "http.request.size"
                                                	TagHTTPResponseSize Tag = "http.response.size"
                                                	TagGRPCStatusCode   Tag = "grpc.status_code"
                                                	TagSQLQuery         Tag = "sql.query"
                                                	TagError            Tag = "error"
                                                )

                                                  Common Tag values

                                                  func (Tag) Set

                                                  func (t Tag) Set(s Span, value string)

                                                    Set a standard Tag with a payload on provided Span.

                                                    type Tracer

                                                    type Tracer struct {
                                                    	// contains filtered or unexported fields
                                                    }

                                                      Tracer is our Zipkin tracer implementation. It should be initialized using the NewTracer method.

                                                      func NewTracer

                                                      func NewTracer(rep reporter.Reporter, opts ...TracerOption) (*Tracer, error)

                                                        NewTracer returns a new Zipkin Tracer.

                                                        Example

                                                        Code:

                                                        package main
                                                        
                                                        import (
                                                        	"log"
                                                        	"time"
                                                        
                                                        	zipkin "github.com/openzipkin/zipkin-go"
                                                        	httpreporter "github.com/openzipkin/zipkin-go/reporter/http"
                                                        )
                                                        
                                                        func main() {
                                                        	// create a reporter to be used by the tracer
                                                        	reporter := httpreporter.NewReporter("http://localhost:9411/api/v2/spans")
                                                        	defer reporter.Close()
                                                        
                                                        	// set-up the local endpoint for our service
                                                        	endpoint, err := zipkin.NewEndpoint("demoService", "172.20.23.100:80")
                                                        	if err != nil {
                                                        		log.Fatalf("unable to create local endpoint: %+v\n", err)
                                                        	}
                                                        
                                                        	// set-up our sampling strategy
                                                        	sampler, err := zipkin.NewBoundarySampler(0.01, time.Now().UnixNano())
                                                        	if err != nil {
                                                        		log.Fatalf("unable to create sampler: %+v\n", err)
                                                        	}
                                                        
                                                        	// initialize the tracer
                                                        	tracer, err := zipkin.NewTracer(
                                                        		reporter,
                                                        		zipkin.WithLocalEndpoint(endpoint),
                                                        		zipkin.WithSampler(sampler),
                                                        	)
                                                        	if err != nil {
                                                        		log.Fatalf("unable to create tracer: %+v\n", err)
                                                        	}
                                                        
                                                        	// tracer can now be used to create spans.
                                                        	span := tracer.StartSpan("some_operation")
                                                        	// ... do some work ...
                                                        	span.Finish()
                                                        
                                                        }
                                                        
                                                        
                                                        

                                                        func (*Tracer) Extract

                                                        func (t *Tracer) Extract(extractor propagation.Extractor) (sc model.SpanContext)

                                                          Extract extracts a SpanContext using the provided Extractor function.

                                                          func (*Tracer) LocalEndpoint

                                                          func (t *Tracer) LocalEndpoint() *model.Endpoint

                                                            LocalEndpoint returns a copy of the currently set local endpoint of the tracer instance.

                                                            func (*Tracer) SetNoop

                                                            func (t *Tracer) SetNoop(noop bool)

                                                              SetNoop allows for killswitch behavior. If set to true the tracer will return noopSpans and all data is dropped. This allows operators to stop tracing in risk scenarios. Set back to false to resume tracing.

                                                              func (*Tracer) StartSpan

                                                              func (t *Tracer) StartSpan(name string, options ...SpanOption) Span

                                                                StartSpan creates and starts a span.

                                                                func (*Tracer) StartSpanFromContext

                                                                func (t *Tracer) StartSpanFromContext(ctx context.Context, name string, options ...SpanOption) (Span, context.Context)

                                                                  StartSpanFromContext creates and starts a span using the span found in context as parent. If no parent span is found a root span is created.

                                                                  type TracerOption

                                                                  type TracerOption func(o *Tracer) error

                                                                    TracerOption allows for functional options to adjust behavior of the Tracer to be created with NewTracer().

                                                                    Example

                                                                    Code:

                                                                    package main
                                                                    
                                                                    import (
                                                                    	zipkin "github.com/openzipkin/zipkin-go"
                                                                    	"github.com/openzipkin/zipkin-go/reporter"
                                                                    )
                                                                    
                                                                    func main() {
                                                                    	// initialize the tracer and use the WithNoopSpan TracerOption
                                                                    	tracer, _ := zipkin.NewTracer(
                                                                    		reporter.NewNoopReporter(),
                                                                    		zipkin.WithNoopSpan(true),
                                                                    	)
                                                                    
                                                                    	// tracer can now be used to create spans
                                                                    	span := tracer.StartSpan("some_operation")
                                                                    	// ... do some work ...
                                                                    	span.Finish()
                                                                    
                                                                    }
                                                                    
                                                                    
                                                                    

                                                                    func WithExtractFailurePolicy

                                                                    func WithExtractFailurePolicy(p ExtractFailurePolicy) TracerOption

                                                                      WithExtractFailurePolicy allows one to set the ExtractFailurePolicy.

                                                                      func WithIDGenerator

                                                                      func WithIDGenerator(generator idgenerator.IDGenerator) TracerOption

                                                                        WithIDGenerator allows one to set a custom ID Generator

                                                                        func WithLocalEndpoint

                                                                        func WithLocalEndpoint(e *model.Endpoint) TracerOption

                                                                          WithLocalEndpoint sets the local endpoint of the tracer.

                                                                          func WithNoopSpan

                                                                          func WithNoopSpan(unsampledNoop bool) TracerOption

                                                                            WithNoopSpan if set to true will switch to a NoopSpan implementation if the trace is not sampled.

                                                                            func WithNoopTracer

                                                                            func WithNoopTracer(tracerNoop bool) TracerOption

                                                                              WithNoopTracer allows one to start the Tracer as Noop implementation.

                                                                              func WithSampler

                                                                              func WithSampler(sampler Sampler) TracerOption

                                                                                WithSampler allows one to set a Sampler function

                                                                                func WithSharedSpans

                                                                                func WithSharedSpans(val bool) TracerOption

                                                                                  WithSharedSpans allows to place client-side and server-side annotations for a RPC call in the same span (Zipkin V1 behavior) or different spans (more in line with other tracing solutions). By default this Tracer uses shared host spans (so client-side and server-side in the same span).

                                                                                  func WithTags

                                                                                  func WithTags(tags map[string]string) TracerOption

                                                                                    WithTags allows one to set default tags to be added to each created span

                                                                                    func WithTraceID128Bit

                                                                                    func WithTraceID128Bit(val bool) TracerOption

                                                                                      WithTraceID128Bit if set to true will instruct the Tracer to start traces with 128 bit TraceID's. If set to false the Tracer will start traces with 64 bits.

                                                                                      Directories

                                                                                      Path Synopsis
                                                                                      Package idgenerator contains several Span and Trace ID generators which can be used by the Zipkin tracer.
                                                                                      Package idgenerator contains several Span and Trace ID generators which can be used by the Zipkin tracer.
                                                                                      middleware
                                                                                      grpc
                                                                                      Package grpc contains several gRPC handlers which can be used for instrumenting calls with Zipkin.
                                                                                      Package grpc contains several gRPC handlers which can be used for instrumenting calls with Zipkin.
                                                                                      http
                                                                                      Package http contains several http middlewares which can be used for instrumenting calls with Zipkin.
                                                                                      Package http contains several http middlewares which can be used for instrumenting calls with Zipkin.
                                                                                      Package model contains the Zipkin V2 model which is used by the Zipkin Go tracer implementation.
                                                                                      Package model contains the Zipkin V2 model which is used by the Zipkin Go tracer implementation.
                                                                                      Package propagation holds the required function signatures for Injection and Extraction as used by the Zipkin Tracer.
                                                                                      Package propagation holds the required function signatures for Injection and Extraction as used by the Zipkin Tracer.
                                                                                      b3
                                                                                      Package b3 implements serialization and deserialization logic for Zipkin B3 Headers.
                                                                                      Package b3 implements serialization and deserialization logic for Zipkin B3 Headers.
                                                                                      proto
                                                                                      zipkin_proto3
                                                                                      Package zipkin_proto3 adds support for the Zipkin protobuf definition to allow Go applications to consume model.SpanModel from protobuf serialized data.
                                                                                      Package zipkin_proto3 adds support for the Zipkin protobuf definition to allow Go applications to consume model.SpanModel from protobuf serialized data.
                                                                                      Package reporter holds the Reporter interface which is used by the Zipkin Tracer to send finished spans.
                                                                                      Package reporter holds the Reporter interface which is used by the Zipkin Tracer to send finished spans.
                                                                                      amqp
                                                                                      Package amqp implements a RabbitMq reporter to send spans to a Rabbit server/cluster.
                                                                                      Package amqp implements a RabbitMq reporter to send spans to a Rabbit server/cluster.
                                                                                      http
                                                                                      Package http implements a HTTP reporter to send spans to Zipkin V2 collectors.
                                                                                      Package http implements a HTTP reporter to send spans to Zipkin V2 collectors.
                                                                                      kafka
                                                                                      Package kafka implements a Kafka reporter to send spans to a Kafka server/cluster.
                                                                                      Package kafka implements a Kafka reporter to send spans to a Kafka server/cluster.
                                                                                      log
                                                                                      Package log implements a reporter to send spans in V2 JSON format to the Go standard Logger.
                                                                                      Package log implements a reporter to send spans in V2 JSON format to the Go standard Logger.
                                                                                      recorder
                                                                                      Package recorder implements a reporter to record spans in v2 format.
                                                                                      Package recorder implements a reporter to record spans in v2 format.