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 ¶
- Variables
- func AddIgnoredCallerPrefix(prefix string)
- func CallerName() string
- func ContextWithSpan(ctx context.Context, s *Span) context.Context
- func ContextWrapper(h ContextHTTPHandler) http.Handler
- func PackageName() string
- func RedirectPackets(listen_addr string, collector *ScribeCollector) error
- func Trace(ctx *context.Context) func(*error)
- type Client
- type ContextHTTPHandler
- type ContextHTTPHandlerFunc
- type HeaderGetter
- type HeaderSetter
- type Request
- type ScribeCollector
- type Span
- func (s *Span) Annotate(key string, val interface{}, host *zipkin.Endpoint)
- func (s *Span) AnnotateTimestamp(key string, now time.Time, duration *time.Duration, host *zipkin.Endpoint)
- func (s *Span) Debug() bool
- func (s *Span) Export() *zipkin.Span
- func (s *Span) Name() string
- func (parent *Span) NewSpan(name string) *Span
- func (s *Span) Observe() func(errptr *error)
- func (s *Span) ObserveService(service *zipkin.Endpoint) func(errptr *error)
- func (s *Span) ParentId() *int64
- func (s *Span) Request() Request
- func (s *Span) SpanId() int64
- func (s *Span) TraceDisabled() bool
- func (s *Span) TraceId() int64
- type SpanManager
- func (m *SpanManager) Configure(trace_fraction float64, trace_debug bool, default_local_host *zipkin.Endpoint)
- func (m *SpanManager) NewSampledTrace(span_name string, debug bool) *Span
- func (m *SpanManager) NewSpanFromRequest(name string, req Request) *Span
- func (m *SpanManager) NewTrace(span_name string) *Span
- func (m *SpanManager) RegisterTraceCollector(collector TraceCollector)
- func (m *SpanManager) Trace(ctx *context.Context) func(*error)
- func (m *SpanManager) TraceHandler(c ContextHTTPHandler) ContextHTTPHandler
- func (m *SpanManager) TraceRequest(ctx context.Context, cl Client, req *http.Request) (resp *http.Response, err error)
- func (m *SpanManager) TraceWithSpanNamed(ctx *context.Context, name string) func(*error)
- type TraceCollector
- type TraceCollectorFunc
- type UDPCollector
Examples ¶
Constants ¶
This section is empty.
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 :)
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 ¶
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.
Types ¶
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 ¶
ContextHTTPHandlerFunc is like http.HandlerFunc but for ContextHTTPHandlers
func (ContextHTTPHandlerFunc) ServeHTTP ¶
func (f ContextHTTPHandlerFunc) ServeHTTP(ctx context.Context, w http.ResponseWriter, r *http.Request)
type HeaderGetter ¶
HeaderGetter is an interface that http.Header matches for RequestFromHeader
type HeaderSetter ¶
HeaderSetter is an interface that http.Header matches for Request.SetHeader
type Request ¶
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 ¶
SpanFromContext loads the current span from the current Context if one exists
func (*Span) Annotate ¶
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 ¶
Debug is whether or not the trace collector is allowed to sample this trace on its own.
func (*Span) Observe ¶
Observe is meant to watch a Span over a given Span duration.
Example ¶
package main import ( "gopkg.in/spacemonkeygo/monitor.v1/trace" ) func main() { myfunc := func() (err error) { span := trace.NewTrace("my span") defer span.Observe()(&err) // do things return nil } myfunc() }
Output:
func (*Span) ObserveService ¶
ObserveService is like Observe, but uses a provided host instead of the SpanManager's default local host for annotations.
func (*Span) Request ¶
Request will return a Request for RPC purposes based off of the existing Span
func (*Span) TraceDisabled ¶
Trace disabled returns whether the trace is even active. A disabled trace causes many operations to be a no-op.
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 ¶
package main import ( "golang.org/x/net/context" "gopkg.in/spacemonkeygo/monitor.v1/trace" ) func main() { myfunc := func(ctx context.Context) (err error) { defer trace.Trace(&ctx)(&err) // do things return nil } myfunc(context.Background()) }
Output:
func (*SpanManager) TraceHandler ¶
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 ¶
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 ¶
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.