Documentation

Overview

Package trace is a distributed tracing and Zipkin client library for Go.

Background

For background, Zipkin (http://twitter.github.io/zipkin/) is Twitter's implementation of the Google Dapper paper (http://research.google.com/pubs/pub36356.html) for collecting tracing information from a distributed system. Both Zipkin and Dapper instrument RPC layers for collecting tracing information from the system as messages pass between services. Please read more at the aforementioned websites.

This library is a Go client library to assist in integrating with Zipkin.

This library, for most common uses, relies heavily on Google's Context objects. See http://blog.golang.org/context for more information there, but essentially this library works best if you are already passing Context objects through most of your callstacks.

Full example

See https://github.com/jtolds/go-zipkin-sample for a set of toy example programs that use this library, or https://raw.githubusercontent.com/jtolds/go-zipkin-sample/master/screenshot.png for a screenshot of the Zipkin user interface after collecting a trace from the sample application.

Basic usage

At a basic level, all you need to do to use this library to interface with Zipkin are the two functions TraceHandler and TraceRequest.

Here's an example client:

func MyOperation(ctx context.Context) error {
  req, err := http.NewRequest("GET", "http://my.url.tld/resource", nil)
  if err != nil {
    return err
  }
  resp, err := trace.TraceRequest(ctx, http.DefaultClient, req)
  if err != nil {
    return err
  }
  defer resp.Body.Close()

  // do stuff
}

And an example server:

func MyServer(addr string) error {
  return http.ListenAndServe(addr, trace.ContextWrapper(
      trace.TraceHandler(trace.ContextHTTPHandlerFunc(
      func(ctx context.Context, w http.ResponseWriter, r *http.Request) {
        MyOperation(ctx)
        fmt.Fprintf(w, "hello\n")
      }))))
}

It is important that the context objects are passed all the way through your application logic from server to client to get the full effect.

In-process tracing

You may want to get tracing information out of operations and services within a process, instead of only at RPC boundaries. In this scenario, there is one more function used for creating new Spans within the same process.

For each function you want dedicated tracing information for, you can call the Trace function like so:

func MyTask(ctx context.Context) (result int, err error) {
  defer trace.Trace(&ctx)(&err)

  result, err = OtherTask1(ctx)
  if err != nil {
    return 0, err
  }

  var wg sync.WaitGroup
  wg.Add(2)

  go func() {
    defer wg.Done()
    OtherTask2(ctx)
  }()

  go func() {
    defer wg.Done()
    OtherTask3(ctx)
  }()

  wg.Wait()

  return result, nil
}

Here, Trace modifies the current context to include a new Span named after the calling function (MyTask). Your tracing collector will then receive this Span and include annotations about when each sampled Span started, when it finished, if it had a non-nil error or had a panic, what the error type was (if github.com/spacemonkeygo/errors can identify it), and pass the Span along to subcalls, for if they have their own spans.

If you don't like the automatic Span naming, you can use TraceWithSpanNamed instead.

Process setup

Every process that sends Spans will need to be configured with Configure and RegisterTraceCollector, so make sure to call those functions appropriately early in your process lifetime.

Other

See https://github.com/itszero/docker-zipkin for easy Zipkin setup.

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	DefaultManager = NewSpanManager()

	Configure              = DefaultManager.Configure
	NewSampledTrace        = DefaultManager.NewSampledTrace
	NewSpanFromRequest     = DefaultManager.NewSpanFromRequest
	NewTrace               = DefaultManager.NewTrace
	RegisterTraceCollector = DefaultManager.RegisterTraceCollector
	TraceHandler           = DefaultManager.TraceHandler
	TraceRequest           = DefaultManager.TraceRequest
	TraceWithSpanNamed     = DefaultManager.TraceWithSpanNamed
)
View Source
var Rng = rand.New(&locker{s: rand.NewSource(seed())})

    Rng is not a source of safe cryptographic randomness. This is only for instances where cryptographic randomness isn't needed. If in doubt, assume you need cryptographic randomness :)

    Functions

    func AddIgnoredCallerPrefix

    func AddIgnoredCallerPrefix(prefix string)

      AddIgnoredCallerPrefix adds a prefix that will get trimmed off from automatic name generation through CallerName (and therefore Trace)

      func CallerName

      func CallerName() string

        CallerName returns the name of the caller two frames up the stack.

        func ContextWithSpan

        func ContextWithSpan(ctx context.Context, s *Span) context.Context

          ContextWithSpan creates a new Context with the provided Span set as the current Span.

          func ContextWrapper

          func ContextWrapper(h ContextHTTPHandler) http.Handler

            ContextWrapper will turn a ContextHTTPHandler into an http.Handler by passing a new Context into every request.

            func PackageName

            func PackageName() string

              PackageName returns the name of the package of the caller two frames up the stack.

              func RedirectPackets

              func RedirectPackets(listen_addr string, collector *ScribeCollector) error

                RedirectPackets is a method that handles incoming packets from the UDPCollector class. RedirectPackets, when running, will listen for UDP packets containing serialized zipkin.Span objects on listen_addr, then will resend those packets to the given ScribeCollector. On any error, RedirectPackets currently aborts.

                func Trace

                func Trace(ctx *context.Context) func(*error)

                  Trace calls Trace on the DefaultManager

                  Types

                  type Client

                  type Client interface {
                  	Do(req *http.Request) (*http.Response, error)
                  }

                    Client is an interface that matches an http.Client

                    type ContextHTTPHandler

                    type ContextHTTPHandler interface {
                    	ServeHTTP(ctx context.Context, w http.ResponseWriter, r *http.Request)
                    }

                      ContextHTTPHandler is like http.Handler, but expects a Context object as the first parameter.

                      type ContextHTTPHandlerFunc

                      type ContextHTTPHandlerFunc func(
                      	ctx context.Context, w http.ResponseWriter, r *http.Request)

                        ContextHTTPHandlerFunc is like http.HandlerFunc but for ContextHTTPHandlers

                        func (ContextHTTPHandlerFunc) ServeHTTP

                        type HeaderGetter

                        type HeaderGetter interface {
                        	Get(string) string
                        }

                          HeaderGetter is an interface that http.Header matches for RequestFromHeader

                          type HeaderSetter

                          type HeaderSetter interface {
                          	Set(string, string)
                          }

                            HeaderSetter is an interface that http.Header matches for Request.SetHeader

                            type Request

                            type Request struct {
                            	TraceId  *int64
                            	SpanId   *int64
                            	ParentId *int64
                            	Sampled  *bool
                            	Flags    *int64
                            }

                              Request is a structure representing an incoming RPC request. Every field is optional.

                              func RequestFromHeader

                              func RequestFromHeader(header HeaderGetter) (rv Request)

                                RequestFromHeader will create a Request object given an http.Header or anything that matches the HeaderGetter interface.

                                func (Request) SetHeader

                                func (r Request) SetHeader(header HeaderSetter)

                                  SetHeader will take a Request and fill out an http.Header, or anything that matches the HeaderSetter interface.

                                  type ScribeCollector

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

                                    ScribeCollector matches the TraceCollector interface, but writes directly to a connected Scribe socket.

                                    func NewScribeCollector

                                    func NewScribeCollector(scribe_addr string) (*ScribeCollector, error)

                                      NewScribeCollector creates a ScribeCollector. scribe_addr is the address of the Scribe endpoint, typically "127.0.0.1:9410"

                                      func (*ScribeCollector) Close

                                      func (s *ScribeCollector) Close() error

                                        Close closes an existing ScribeCollector

                                        func (*ScribeCollector) Collect

                                        func (c *ScribeCollector) Collect(s *zipkin.Span)

                                          Collect will serialize and send a zipkin.Span to the configured Scribe endpoint

                                          func (*ScribeCollector) CollectSerialized

                                          func (c *ScribeCollector) CollectSerialized(serialized []byte) error

                                            CollectSerialized buffers a serialized zipkin.Span to be sent to the Scribe endpoint. It returns an error and loses the log entry if the buffer is full.

                                            type Span

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

                                              Span represents a given task or request within a full trace.

                                              func NewDisabledTrace

                                              func NewDisabledTrace() *Span

                                                NewDisabledTrace creates a new Span that is disabled.

                                                func SpanFromContext

                                                func SpanFromContext(ctx context.Context) (s *Span, ok bool)

                                                  SpanFromContext loads the current span from the current Context if one exists

                                                  func (*Span) Annotate

                                                  func (s *Span) Annotate(key string, val interface{}, host *zipkin.Endpoint)

                                                    Annotate annotates a given span with an arbitrary value. host is optional. Annotate is a no-op unless val is of type time.Time, []byte, or string.

                                                    func (*Span) AnnotateTimestamp

                                                    func (s *Span) AnnotateTimestamp(key string, now time.Time,
                                                    	duration *time.Duration, host *zipkin.Endpoint)

                                                      AnnotateTimestamp annotates a given span with a timestamp. duration and host are optional.

                                                      func (*Span) Debug

                                                      func (s *Span) Debug() bool

                                                        Debug is whether or not the trace collector is allowed to sample this trace on its own.

                                                        func (*Span) Export

                                                        func (s *Span) Export() *zipkin.Span

                                                          Export will take a Span and return a serializable thrift object.

                                                          func (*Span) Name

                                                          func (s *Span) Name() string

                                                            Name is the name of the given span, if not disabled.

                                                            func (*Span) NewSpan

                                                            func (parent *Span) NewSpan(name string) *Span

                                                              NewSpan creates a new Span off of the given parent Span.

                                                              func (*Span) Observe

                                                              func (s *Span) Observe() func(errptr *error)

                                                                Observe is meant to watch a Span over a given Span duration.

                                                                Example
                                                                Output:
                                                                
                                                                

                                                                func (*Span) ObserveService

                                                                func (s *Span) ObserveService(service *zipkin.Endpoint) func(errptr *error)

                                                                  ObserveService is like Observe, but uses a provided host instead of the SpanManager's default local host for annotations.

                                                                  func (*Span) ParentId

                                                                  func (s *Span) ParentId() *int64

                                                                    ParentId is the id of the parent span in the given trace, if not disabled.

                                                                    func (*Span) Request

                                                                    func (s *Span) Request() Request

                                                                      Request will return a Request for RPC purposes based off of the existing Span

                                                                      func (*Span) SpanId

                                                                      func (s *Span) SpanId() int64

                                                                        SpanId is the id of the given span, if not disabled.

                                                                        func (*Span) TraceDisabled

                                                                        func (s *Span) TraceDisabled() bool

                                                                          Trace disabled returns whether the trace is even active. A disabled trace causes many operations to be a no-op.

                                                                          func (*Span) TraceId

                                                                          func (s *Span) TraceId() int64

                                                                            TraceId is the id of the given trace, if not disabled.

                                                                            type SpanManager

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

                                                                              SpanManager creates and configures settings about Spans. Create one with NewSpanManager

                                                                              func NewSpanManager

                                                                              func NewSpanManager() *SpanManager

                                                                                NewSpanManager creates a new SpanManager. No traces will be collected by default until Configure is called.

                                                                                func (*SpanManager) Configure

                                                                                func (m *SpanManager) Configure(trace_fraction float64, trace_debug bool,
                                                                                	default_local_host *zipkin.Endpoint)

                                                                                  Configure configures a SpanManager. trace_fraction is the fraction of new traces that will be collected (between 0 and 1, inclusive). trace_debug is whether or not traces will have the debug flag set, which controls whether or not the trace collector will be allowed to sample them on its own. default_local_host is the annotation host endpoint to set when one isn't otherwise provided.

                                                                                  func (*SpanManager) NewSampledTrace

                                                                                  func (m *SpanManager) NewSampledTrace(span_name string, debug bool) *Span

                                                                                    NewSampledTrace creates a new span that begins a trace that is being sampled without consulting the configured trace_fraction. span_name names the first span of the trace, and debug controls whether or not the span collector is allowed to sample the trace on its own.

                                                                                    func (*SpanManager) NewSpanFromRequest

                                                                                    func (m *SpanManager) NewSpanFromRequest(name string, req Request) *Span

                                                                                      NewSpanFromRequest creates a new span, and possibly a new trace, given whatever was supplied in the incoming request.

                                                                                      func (*SpanManager) NewTrace

                                                                                      func (m *SpanManager) NewTrace(span_name string) *Span

                                                                                        NewTrace creates a new span that begins a trace, after consulting the SpanManager's configured trace_fraction and trace_debug settings. The trace may or may not actually be sampled. span_name is the name of the beginning Span.

                                                                                        func (*SpanManager) RegisterTraceCollector

                                                                                        func (m *SpanManager) RegisterTraceCollector(collector TraceCollector)

                                                                                          RegisterTraceCollector takes a TraceCollector and calls Collect on it whenever a Span from this SpanManager is complete.

                                                                                          func (*SpanManager) Trace

                                                                                          func (m *SpanManager) Trace(ctx *context.Context) func(*error)

                                                                                            Trace is a utility that allows you to automatically create a Span (or a brand new trace, if needed) that observes the current function scope, given a function call context. The name of the Span is pulled from the current function name. See the example for usage.

                                                                                            Example
                                                                                            Output:
                                                                                            
                                                                                            

                                                                                            func (*SpanManager) TraceHandler

                                                                                              TraceHandler wraps a ContextHTTPHandler with a Span pulled from incoming requests, possibly starting new Traces if necessary.

                                                                                              func (*SpanManager) TraceRequest

                                                                                              func (m *SpanManager) TraceRequest(ctx context.Context, cl Client,
                                                                                              	req *http.Request) (
                                                                                              	resp *http.Response, err error)

                                                                                                TraceRequest will perform an HTTP request, creating a new Span for the HTTP request and sending the Span in the HTTP request headers. Compare to http.Client.Do.

                                                                                                func (*SpanManager) TraceWithSpanNamed

                                                                                                func (m *SpanManager) TraceWithSpanNamed(
                                                                                                	ctx *context.Context, name string) func(*error)

                                                                                                  TraceWithSpanNamed is like Trace, except you get to pick the Span name.

                                                                                                  type TraceCollector

                                                                                                  type TraceCollector interface {
                                                                                                  	// Collect gets called with a Span whenever a Span is completed on a
                                                                                                  	// SpanManager.
                                                                                                  	Collect(span *zipkin.Span)
                                                                                                  }

                                                                                                    TraceCollector is an interface dealing with completed Spans on a SpanManager. See RegisterTraceCollector.

                                                                                                    type TraceCollectorFunc

                                                                                                    type TraceCollectorFunc func(span *zipkin.Span)

                                                                                                      TraceCollectorFunc is for closures that match the TraceCollector interface.

                                                                                                      func (TraceCollectorFunc) Collect

                                                                                                      func (f TraceCollectorFunc) Collect(span *zipkin.Span)

                                                                                                      type UDPCollector

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

                                                                                                        UDPCollector matches the TraceCollector interface, but sends serialized zipkin.Span objects over UDP, instead of the Scribe protocol. See RedirectPackets for the UDP server-side code.

                                                                                                        func NewUDPCollector

                                                                                                        func NewUDPCollector(collector_addr string, buffer_size int) (
                                                                                                        	*UDPCollector, error)

                                                                                                          NewUDPCollector creates a UDPCollector that sends packets to collector_addr. buffer_size is how many outstanding unsent zipkin.Span objects can exist before Spans start getting dropped.

                                                                                                          func (*UDPCollector) Collect

                                                                                                          func (c *UDPCollector) Collect(span *zipkin.Span)

                                                                                                            Collect takes a zipkin.Span object, serializes it, and sends it to the configured collector_addr.

                                                                                                            Directories

                                                                                                            Path Synopsis
                                                                                                            gen-go