monitor.v1: gopkg.in/spacemonkeygo/monitor.v1/trace Index | Examples | Files | Directories

package trace

import "gopkg.in/spacemonkeygo/monitor.v1/trace"

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

Package Files

backoff.go caller.go ctx.go doc.go http.go manager.go rand.go request.go scribe.go span.go udp.go

Variables

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

func AddIgnoredCallerPrefix Uses

func AddIgnoredCallerPrefix(prefix string)

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

func CallerName Uses

func CallerName() string

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

func ContextWithSpan Uses

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 Uses

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 Uses

func PackageName() string

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

func RedirectPackets Uses

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 Uses

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

Trace calls Trace on the DefaultManager

type Client Uses

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

Client is an interface that matches an http.Client

type ContextHTTPHandler Uses

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 Uses

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

ContextHTTPHandlerFunc is like http.HandlerFunc but for ContextHTTPHandlers

func (ContextHTTPHandlerFunc) ServeHTTP Uses

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

type HeaderGetter Uses

type HeaderGetter interface {
    Get(string) string
}

HeaderGetter is an interface that http.Header matches for RequestFromHeader

type HeaderSetter Uses

type HeaderSetter interface {
    Set(string, string)
}

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

type Request Uses

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 Uses

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 Uses

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 Uses

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

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

func NewScribeCollector Uses

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 Uses

func (s *ScribeCollector) Close() error

Close closes an existing ScribeCollector

func (*ScribeCollector) Collect Uses

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

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

func (*ScribeCollector) CollectSerialized Uses

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 Uses

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

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

func NewDisabledTrace Uses

func NewDisabledTrace() *Span

NewDisabledTrace creates a new Span that is disabled.

func SpanFromContext Uses

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

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

func (*Span) Annotate Uses

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 Uses

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 Uses

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 Uses

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

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

func (*Span) Name Uses

func (s *Span) Name() string

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

func (*Span) NewSpan Uses

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

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

func (*Span) Observe Uses

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

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

Code:

myfunc := func() (err error) {
    span := trace.NewTrace("my span")
    defer span.Observe()(&err)

    // do things

    return nil
}

myfunc()

func (*Span) ObserveService Uses

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 Uses

func (s *Span) ParentId() *int64

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

func (*Span) Request Uses

func (s *Span) Request() Request

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

func (*Span) SpanId Uses

func (s *Span) SpanId() int64

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

func (*Span) TraceDisabled Uses

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 Uses

func (s *Span) TraceId() int64

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

type SpanManager Uses

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

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

func NewSpanManager Uses

func NewSpanManager() *SpanManager

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

func (*SpanManager) Configure Uses

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 Uses

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 Uses

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 Uses

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 Uses

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 Uses

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.

Code:

myfunc := func(ctx context.Context) (err error) {
    defer trace.Trace(&ctx)(&err)

    // do things

    return nil
}

myfunc(context.Background())

func (*SpanManager) TraceHandler Uses

func (m *SpanManager) TraceHandler(c ContextHTTPHandler) ContextHTTPHandler

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

func (*SpanManager) TraceRequest Uses

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 Uses

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 Uses

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 Uses

type TraceCollectorFunc func(span *zipkin.Span)

TraceCollectorFunc is for closures that match the TraceCollector interface.

func (TraceCollectorFunc) Collect Uses

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

type UDPCollector Uses

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 Uses

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 Uses

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

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

Directories

PathSynopsis
gen-go/scribe
gen-go/zipkin

Package trace imports 21 packages (graph) and is imported by 9 packages. Updated 2016-07-17. Refresh now. Tools for package owners.