zipkin

package module
v0.1.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 7, 2018 License: Apache-2.0 Imports: 15 Imported by: 0

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

gRPC middleware / interceptors are planned for the near future.

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

Documentation

Overview

Package zipkin implements a native Zipkin instrumentation library for Go.

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

Example
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)
	}
}
Output:

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 added in v0.1.1

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 added in v0.1.1

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
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)

}
Output:

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()

	// 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.

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
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()

}
Output:

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
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()

}
Output:

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
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()

}
Output:

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
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
v2
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.
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.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL