Documentation ¶
Overview ¶
Package tracing provides tracing integration with zipkin.
For thrift services, they should call StartSpanFromThriftContext with the context object injected by thrift library to get a root span for the thrift handler function, then call CreateChildSpan to create child-spans.
This package also implements opentracing defined interfaces. As a side effect, importing this package will call opentracing.SetGlobalTracer automatically with a Tracer implementation that does not send spans anywhere. Call InitGlobalTracer early in your main function to setup spans sampling.
Index ¶
- Constants
- func CloseTracer() error
- func CreateThriftContextFromSpan(ctx context.Context, span *Span) context.Context
- func InitGlobalTracer(cfg TracerConfig) error
- func InjectHTTPServerSpan(name string) endpoint.Middleware
- func InjectThriftServerSpan(name string) endpoint.Middleware
- func IsSpanHook(hook interface{}) bool
- func RegisterCreateServerSpanHooks(hooks ...CreateServerSpanHook)
- func ResetHooks()
- func TestWrapper(tb testing.TB) (logger log.Wrapper, startFailing func())
- type AddSpanCounterHook
- type CreateChildSpanHook
- type CreateServerSpanHook
- type ErrorReporterCreateServerSpanHook
- type FinishOptions
- type InvalidSpanTypeError
- type LocalComponentOption
- type SetSpanTagHook
- type Span
- func (s *Span) AddCounter(key string, delta float64)
- func (s *Span) AddHooks(hooks ...interface{})
- func (s *Span) BaggageItem(restrictedKey string) string
- func (s *Span) Component() string
- func (s *Span) Context() opentracing.SpanContext
- func (s *Span) Finish()
- func (s *Span) FinishWithOptions(opts opentracing.FinishOptions)
- func (s *Span) ForeachBaggageItem(handler func(k, v string) bool)
- func (s *Span) Log(data opentracing.LogData)
- func (s Span) LogError(msg string, err error)
- func (s *Span) LogEvent(event string)
- func (s *Span) LogEventWithPayload(event string, payload interface{})
- func (s *Span) LogFields(fields ...log.Field)
- func (s *Span) LogKV(alternatingKeyValues ...interface{})
- func (s Span) Name() string
- func (s *Span) SetBaggageItem(restrictedKey, value string) opentracing.Span
- func (s *Span) SetDebug(v bool)
- func (s *Span) SetOperationName(operationName string) opentracing.Span
- func (s *Span) SetTag(key string, value interface{}) opentracing.Span
- func (s Span) SpanType() SpanType
- func (s *Span) Stop(ctx context.Context, err error) error
- func (s *Span) Tracer() opentracing.Tracer
- type SpanType
- type SpanTypeOption
- type StartSpanOption
- type StartSpanOptions
- type StartStopSpanHook
- type Tracer
- func (t *Tracer) Close() error
- func (t *Tracer) Extract(format interface{}, carrier interface{}) (opentracing.SpanContext, error)
- func (t *Tracer) Inject(sm opentracing.SpanContext, format interface{}, carrier interface{}) error
- func (t *Tracer) Record(ctx context.Context, zs ZipkinSpan) error
- func (t *Tracer) StartSpan(operationName string, opts ...opentracing.StartSpanOption) opentracing.Span
- type TracerConfig
- type ZipkinBinaryAnnotation
- type ZipkinEndpointInfo
- type ZipkinSpan
- type ZipkinTimeAnnotation
Examples ¶
Constants ¶
const ( // Max size of serialized span in bytes. MaxSpanSize = 102400 // Max number of spans allowed in the message queue at one time. MaxQueueSize = 10000 // Prefix added to the queue name. QueueNamePrefix = "traces-" // The default MaxRecordTimeout used in Tracers. DefaultMaxRecordTimeout = time.Millisecond * 50 )
Configuration values for the message queue.
const ( ZipkinTimeAnnotationKeyClientReceive = "cr" ZipkinTimeAnnotationKeyClientSend = "cs" ZipkinTimeAnnotationKeyServerReceive = "sr" ZipkinTimeAnnotationKeyServerSend = "ss" )
Zipkin span well-known time annotation keys.
const ( // String values ZipkinBinaryAnnotationKeyComponent = "component" ZipkinBinaryAnnotationKeyLocalComponent = "lc" // Boolean values ZipkinBinaryAnnotationKeyDebug = "debug" ZipkinBinaryAnnotationKeyError = "error" ZipkinBinaryAnnotationKeyTimeOut = "timed_out" )
Zipkin span well-known binary annotation keys.
const ( // When set, this trace passes all samplers. FlagMaskDebug int64 = 1 )
FlagMask values.
Variables ¶
This section is empty.
Functions ¶
func CloseTracer ¶
func CloseTracer() error
CloseTracer tries to cast opentracing.GlobalTracer() into *Tracer, and calls its Close function.
See Tracer.Close for more details.
func CreateThriftContextFromSpan ¶
CreateThriftContextFromSpan injects span info into a context object that can be used in thrift client code.
Caller should first create a client child-span for the thrift call as usual, then use that span and the parent context object with this call, then use the returned context object in the thrift call. Something like:
span, clientCtx := opentracing.StartSpanFromContext( ctx, "myCall", tracing.SpanTypeOption{Type: SpanTypeClient}, ) result, err := client.MyCall(clientCtx, arg1, arg2) // Or: span.Stop(ctx, err) span.FinishWithOptions(tracing.FinishOptions{ Ctx: ctx, Err: err, }.Convert())
func InitGlobalTracer ¶
func InitGlobalTracer(cfg TracerConfig) error
InitGlobalTracer initializes opentracing's global tracer.
This function will try to get the first local IPv4 address of this machine as part of the span information send to the backend service. If it fails to do so, UndefinedIP will be used instead, and the error will be logged if logger is non-nil.
func InjectHTTPServerSpan ¶
func InjectHTTPServerSpan(name string) endpoint.Middleware
InjectHTTPServerSpan returns a go-kit endpoint.Middleware that injects a server span into the `next` context.
Starts the server span before calling the `next` endpoint and stops the span after the endpoint finishes. If the endpoint returns an error, that will be passed to span.Stop. If the response implements ErrorResponse, the error returned by Err() will not be passed to span.Stop.
Note, this function depends on the edge context headers already being set on the context object. This can be done by adding httpbp.PopulateRequestContext as a ServerBefore option when setting up the request handler for an endpoint.
Example ¶
This example shows how to use the InjectHTTPServerSpan middleware in a go-kit HTTP service.
package main import ( "net/http" "github.com/fizx/baseplate.go/httpbp" "github.com/fizx/baseplate.go/log" "github.com/fizx/baseplate.go/tracing" "github.com/go-kit/kit/endpoint" httpgk "github.com/go-kit/kit/transport/http" ) func main() { // variables should be properly initialized in production code var ( IsHealthy endpoint.Endpoint DecodeIsHealthyRequest httpgk.DecodeRequestFunc trustHandler httpbp.AlwaysTrustHeaders ) name := "my-service" handler := http.NewServeMux() handler.Handle("/health", httpgk.NewServer( // You don't have to use endpoint.Chain when using a single // endpoint.Middleware, as we are in this example, but it will make it // easier to add more later on down the line (since you'll have to add // it then anyways). endpoint.Chain( tracing.InjectHTTPServerSpan(name), )(IsHealthy), DecodeIsHealthyRequest, httpbp.EncodeJSONResponse, httpgk.ServerBefore( // InjectHTTPServerSpan relies on PopulateRequestContext from the // httpbp package to set up the context object with the appropriate // headers from the request. httpbp.PopulateRequestContext(trustHandler), ), )) log.Fatal(http.ListenAndServe(":8080", handler)) }
Output:
func InjectThriftServerSpan ¶
func InjectThriftServerSpan(name string) endpoint.Middleware
InjectThriftServerSpan returns a go-kit endpoint.Middleware that injects a server span into the `next` context.
Starts the server span before calling the `next` endpoint and stops the span after the endpoint finishes. If the endpoint returns an error, that will be passed to span.Stop.
Note, this depends on the edge context headers already being set on the context object. These should be automatically injected by your thrift.TSimpleServer.
func IsSpanHook ¶
func IsSpanHook(hook interface{}) bool
IsSpanHook returns true if hook implements at least one of the span Hook interfaces and false if it implements none.
func RegisterCreateServerSpanHooks ¶
func RegisterCreateServerSpanHooks(hooks ...CreateServerSpanHook)
RegisterCreateServerSpanHooks registers Hooks into the Baseplate request lifecycle.
This function and ResetHooks are not safe to call concurrently.
func ResetHooks ¶
func ResetHooks()
ResetHooks removes all global hooks and resets back to initial state.
This function and RegisterCreateServerSpanHooks are not safe to call concurrently.
func TestWrapper ¶
TestWrapper is a log.Wrapper implementation can be used in tests.
It's similar to but different from log.TestWrapper. In InitGlobalTracer call logger could be called once for unable to find ip, and we don't want to fail the tests because of that. So in this implementation, initially this logger just print the message but don't fail the test, and only start failing the test after startFailing is called.
Types ¶
type AddSpanCounterHook ¶
type AddSpanCounterHook interface { // OnAddCounter is called by Span.AddCounter, after the counter is updated // on the Span. OnAddCounter(span *Span, key string, delta float64) error }
AddSpanCounterHook allows you to inject functionality after adding a counter on a span.
type CreateChildSpanHook ¶
type CreateChildSpanHook interface { // OnCreateChild is called after a child Span is first created, before any // OnPostStart Hooks are called. // // OnCreateChild is the recommended place to register Hooks onto the // child Span. OnCreateChild(parent, child *Span) error }
CreateChildSpanHook allows you to inject functionality into the creation of a Baseplate span.
type CreateServerSpanHook ¶
type CreateServerSpanHook interface { // OnCreateServerSpan is called after a server Span is first created by // tracing.CreateServerSpan, before any OnPostStart Hooks are called. // // OnCreateServerSpan is the recommended place to register Hooks onto the // server Span. OnCreateServerSpan(span *Span) error }
CreateServerSpanHook allows you to inject functionality into the lifecycle of a Baseplate request.
type ErrorReporterCreateServerSpanHook ¶
type ErrorReporterCreateServerSpanHook struct{}
ErrorReporterCreateServerSpanHook registers each Server Span with an ErrorReporterSpanHook that will publish errors sent to OnPreStop to Sentry.
Example ¶
This example demonstrates how to use ErrorReporterCreateServerSpanHook.
package main import ( "errors" "github.com/fizx/baseplate.go/tracing" opentracing "github.com/opentracing/opentracing-go" ) func main() { // variables should be properly initialized in production code var ( parent *tracing.Span ) // initialize the ErrorReporterCreateServerSpanHook hook := tracing.ErrorReporterCreateServerSpanHook{} // register the hook with Baseplate tracing.RegisterCreateServerSpanHooks(hook) // Create a child server Span span := opentracing.StartSpan( "test", opentracing.ChildOf(parent), tracing.SpanTypeOption{Type: tracing.SpanTypeServer}, ) // Errors given to span.FinishWithOptions will be sent to Sentry span.FinishWithOptions(tracing.FinishOptions{ Err: errors.New("test error"), }.Convert()) }
Output:
func (ErrorReporterCreateServerSpanHook) OnCreateServerSpan ¶
func (h ErrorReporterCreateServerSpanHook) OnCreateServerSpan(span *Span) error
OnCreateServerSpan registers SentrySpanHook on a Server Span.
type FinishOptions ¶
FinishOptions are the options to be converted into opentracing.FinishOptions.
All fields are optional.
func (FinishOptions) Convert ¶
func (fo FinishOptions) Convert() opentracing.FinishOptions
Convert converts FinishOptions into opentracing.FinishOptions which can be used in Span.FinishWithOptions().
type InvalidSpanTypeError ¶
InvalidSpanTypeError is the error type returned when trying to use a Span in a way that is incompatible with its type.
For example, trying to set a child span as a ServerSpan.
func (*InvalidSpanTypeError) Error ¶
func (e *InvalidSpanTypeError) Error() string
type LocalComponentOption ¶
type LocalComponentOption struct { Name string // contains filtered or unexported fields }
LocalComponentOption implements StartSpanOption to set the type to local and also sets the local component name.
func (LocalComponentOption) Apply ¶
func (LocalComponentOption) Apply(*opentracing.StartSpanOptions)
func (LocalComponentOption) ApplyBP ¶
func (l LocalComponentOption) ApplyBP(sso *StartSpanOptions)
ApplyBP implements StartSpanOption.
type SetSpanTagHook ¶
type SetSpanTagHook interface { // OnSetTag is called by Span.SetTag, after the tag is set on the Span. OnSetTag(span *Span, key string, value interface{}) error }
SetSpanTagHook allows you to inject functionality after setting a tag on a span.
type Span ¶
type Span struct {
// contains filtered or unexported fields
}
Span defines a tracing span.
func AsSpan ¶
func AsSpan(s opentracing.Span) *Span
AsSpan converts an opentracing.Span back to *Span.
This function never returns nil. If the passed in opentracing.Span is actually not implemented by *Span, a new *Span with empty name and local type will be created and returned. When that happens it will also be logged if the last InitGlobalTracer call was with a non-nil logger.
This function is provided for convenience calling functions not in opentracing Span API, for example:
span := opentracing.StartSpan(name, opts...) tracing.AsSpan(span).AddHooks(hooks...)
func StartSpanFromHTTPContext ¶
StartSpanFromHTTPContext creates a server span from http context object.
This span would usually be used as the span of the whole http endpoint handler, and the parent of the child-spans.
Please note that "Sampled" header is default to false according to baseplate spec, so if the context object doesn't have headers injected correctly, this span (and all its child-spans) will never be sampled, unless debug flag was set explicitly later.
Caller should pass in the context object they got from go-kit http library with httpbp.PopulateRequestContext as a ServerBefore hook, this way the context object would have all the required headers already injected.
If any headers are missing or malformed, they will be ignored. Malformed headers will be logged if InitGlobalTracer was last called with a non-nil logger.
func StartSpanFromThriftContext ¶
StartSpanFromThriftContext creates a server span from thrift context object.
This span would usually be used as the span of the whole thrift endpoint handler, and the parent of the child-spans.
Caller should pass in the context object they got from thrift library, which would have all the required headers already injected.
Please note that "Sampled" header is default to false according to baseplate spec, so if the context object doesn't have headers injected correctly, this span (and all its child-spans) will never be sampled, unless debug flag was set explicitly later.
If any of the tracing related thrift header is present but malformed, it will be ignored. The error will also be logged if InitGlobalTracer was last called with a non-nil logger. Absent tracing related headers are always silently ignored.
func (*Span) AddCounter ¶
AddCounter adds delta to a counter annotation and calls all OnAddCounter Hooks registered to the Span.
func (*Span) AddHooks ¶
func (s *Span) AddHooks(hooks ...interface{})
AddHooks adds hooks into the Span.
Any hooks that do not conform to at least one of the span hook interfaces will be discarded and an error will be logged.
It is recommended that you only call AddHooks on a Span within an OnCreateChild/OnCreateServerSpan hook so the Span is set up with all of its hooks as a part of its creation.
func (*Span) BaggageItem ¶
BaggageItem implements opentracing.Span.
As we don't support any extra baggage items, it always returns empty string.
func (*Span) Component ¶
Component returns the local component name of this span, with special cases.
For local spans, this returns the component name set while starting the span, or "local" if it's empty. For client spans, this returns "clients". For all other span types, this returns the string version of the span type.
func (*Span) Context ¶
func (s *Span) Context() opentracing.SpanContext
Context implements opentracing.Span.
It returns self as opentracing.SpanContext.
func (*Span) Finish ¶
func (s *Span) Finish()
Finish implements opentracing.Span.
It calls Stop with background context and nil error. If Stop returns an error, it will also be logged with the tracer's logger.
func (*Span) FinishWithOptions ¶
func (s *Span) FinishWithOptions(opts opentracing.FinishOptions)
FinishWithOptions implements opentracing.Span.
In this implementation we ignore all timestamps in opts, only extract context and error out of all the log fields, and ignore all other log fields.
Please use FinishOptions.Convert() to prepare the opts arg.
It calls Stop with context and error extracted from opts. If Stop returns an error, it will also be logged with the tracer's logger.
func (*Span) ForeachBaggageItem ¶
ForeachBaggageItem implements opentracing.SpanContext.
We don't support any extra baggage items, so it's a noop.
func (*Span) Log ¶
func (s *Span) Log(data opentracing.LogData)
Log implements opentracing.Span.
it's deprecated in the interface and is a no-op here.
func (Span) LogError ¶
LogError is a helper method to log an error plus a message.
This uses the the logger provided by the underlying tracing.Tracer used to publish the Span.
func (*Span) LogEvent ¶
LogEvent implements opentracing.Span.
it's deprecated in the interface and is a no-op here.
func (*Span) LogEventWithPayload ¶
LogEventWithPayload implements opentracing.Span.
it's deprecated in the interface and is a noop here.
func (*Span) LogFields ¶
LogFields implements opentracing.Span.
In this implementation it's a no-op.
func (*Span) LogKV ¶
func (s *Span) LogKV(alternatingKeyValues ...interface{})
LogKV implements opentracing.Span.
In this implementation it's a no-op.
func (*Span) SetBaggageItem ¶
func (s *Span) SetBaggageItem(restrictedKey, value string) opentracing.Span
SetBaggageItem implements opentracing.Span.
As we don't support any extra baggage items, it's a noop and just returns self.
func (*Span) SetOperationName ¶
func (s *Span) SetOperationName(operationName string) opentracing.Span
SetOperationName implements opentracing.Span.
func (*Span) SetTag ¶
func (s *Span) SetTag(key string, value interface{}) opentracing.Span
SetTag sets a binary tag annotation and calls all OnSetTag Hooks registered to the Span.
func (*Span) Stop ¶
Stop stops the Span, calls all registered OnPreStop Hooks, serializes the Span, and sends the serialized Span to a back-end that records the Span.
In most cases FinishWithOptions should be used instead, which calls Stop and auto logs the error returned by Stop. Stop is still provided in case there's need to handle the error differently.
func (*Span) Tracer ¶
func (s *Span) Tracer() opentracing.Tracer
Tracer implements opentracing.Span.
type SpanTypeOption ¶
type SpanTypeOption struct { Type SpanType // contains filtered or unexported fields }
SpanTypeOption implements StartSpanOption to set the type of the span.
func (SpanTypeOption) Apply ¶
func (SpanTypeOption) Apply(*opentracing.StartSpanOptions)
func (SpanTypeOption) ApplyBP ¶
func (s SpanTypeOption) ApplyBP(sso *StartSpanOptions)
ApplyBP implements StartSpanOption.
type StartSpanOption ¶
type StartSpanOption interface { opentracing.StartSpanOption ApplyBP(*StartSpanOptions) }
StartSpanOption defines additional options for baseplate spans.
type StartSpanOptions ¶
type StartSpanOptions struct { OpenTracingOptions opentracing.StartSpanOptions Type SpanType ComponentName string }
StartSpanOptions is the additional options for baseplate spans.
func (*StartSpanOptions) Apply ¶
func (sso *StartSpanOptions) Apply(opt opentracing.StartSpanOption)
Apply calls opt.Apply against sso.OpenTracingOptions.
If opt also implements StartSpanOptions, it also calls opt.ApplyBP against sso.
type StartStopSpanHook ¶
type StartStopSpanHook interface { // OnPostStart is called after a child Span is created and the OnCreateChild // Hooks on the parent Span are called. OnPostStart(span *Span) error // OnPreStop is called by Span.Stop, after setting any custom tags, but // before the span is stopped, serialized, or published. OnPreStop(span *Span, err error) error }
StartStopSpanHook allows you to inject functionality immediately after starting a span and immediately before stopping a span.
type Tracer ¶
type Tracer struct {
// contains filtered or unexported fields
}
A Tracer creates and manages spans.
func (*Tracer) Close ¶
Close closes the tracer's reporting.
After Close is called, no more spans will be sampled.
func (*Tracer) Extract ¶
func (t *Tracer) Extract(format interface{}, carrier interface{}) (opentracing.SpanContext, error)
Extract implements opentracing.Tracer.
Currently it always return opentracing.ErrInvalidCarrier as the error.
func (*Tracer) Inject ¶
func (t *Tracer) Inject(sm opentracing.SpanContext, format interface{}, carrier interface{}) error
Inject implements opentracing.Tracer.
Currently it always return opentracing.ErrInvalidCarrier as the error.
func (*Tracer) Record ¶
func (t *Tracer) Record(ctx context.Context, zs ZipkinSpan) error
Record records a span with the Recorder.
Span.Stop(), Span.Finish(), and Span.FinishWithOptions() call this function automatically. In most cases that should be enough and you should not call this function directly.
func (*Tracer) StartSpan ¶
func (t *Tracer) StartSpan(operationName string, opts ...opentracing.StartSpanOption) opentracing.Span
StartSpan implements opentracing.Tracer.
For opentracing.StartSpanOptions, it only support the following options and will ignore all others:
- ChildOfRef (in which case the parent span must be of type *Span)
- StartTime
- Tags
It supports additional StartSpanOptions defined in this package.
If the new span's type is server, all registered CreateServerSpanHooks will be called as well.
Please note that trying to set span type via opentracing-go/ext package won't work, please use SpanTypeOption defined in this package instead.
type TracerConfig ¶
type TracerConfig struct { // The name of the service that will be attached to every span. ServiceName string // SampleRate should be in the range of [0, 1]. // When SampleRate >= 1, all traces will be recoreded; // When SampleRate <= 0, none of the traces will be recorded, // except the ones with debug flag set. // // Please note that SampleRate only affect top level spans created inside this // service. For most services the sample status will be inherited from the // headers from the client. SampleRate float64 // Logger, if non-nil, will be used to log additional informations Record // returned certain errors. Logger log.Wrapper // The max timeout applied to Record function. // // If the passed in context object has an earlier deadline set, // that deadline will be respected instead. // // If MaxRecordTimeout <= 0, DefaultMaxRecordTimeout will be used. MaxRecordTimeout time.Duration // The name of the message queue to be used to actually send sampled spans to // backend service (requires baseplate.py tracing publishing sidecar with the // same name configured). // // QueueName should not contain "traces-" prefix, it will be auto added. // // If QueueName is empty, no spans will be sampled, // including the ones with debug flag set. QueueName string // In test code, // this field can be used to set the message queue the tracer publishes to, // usually an *mqsend.MockMessageQueue. // // This field will be ignored when QueueName is non-empty, // to help avoiding footgun prod code. // // DO NOT USE IN PROD CODE. TestOnlyMockMessageQueue mqsend.MessageQueue }
TracerConfig are the configuration values to be used in InitGlobalTracer.
type ZipkinBinaryAnnotation ¶
type ZipkinBinaryAnnotation struct { Endpoint ZipkinEndpointInfo `json:"endpoint"` Key string `json:"key"` Value interface{} `json:"value"` }
ZipkinBinaryAnnotation defines Zipkin's binary annotation json format.
type ZipkinEndpointInfo ¶
type ZipkinEndpointInfo struct { ServiceName string `json:"serviceName"` IPv4 string `json:"ipv4"` }
ZipkinEndpointInfo defines Zipkin's endpoint json format.
type ZipkinSpan ¶
type ZipkinSpan struct { // Required fields. TraceID uint64 `json:"traceId"` Name string `json:"name"` SpanID uint64 `json:"id"` Start timebp.TimestampMicrosecond `json:"timestamp"` Duration timebp.DurationMicrosecond `json:"duration"` // parentId is actually optional, // but when it's absent 0 needs to be set explicitly. ParentID uint64 `json:"parentId"` // Annotations are all optional. TimeAnnotations []ZipkinTimeAnnotation `json:"annotations,omitempty"` BinaryAnnotations []ZipkinBinaryAnnotation `json:"binaryAnnotations,omitempty"` }
ZipkinSpan defines a span in zipkin's json format.
It's used as an intermediate format before encoding to json string. It shouldn't be used directly.
type ZipkinTimeAnnotation ¶
type ZipkinTimeAnnotation struct { Endpoint ZipkinEndpointInfo `json:"endpoint"` Timestamp timebp.TimestampMicrosecond `json:"timestamp"` // In time annotations the value is actually the timestamp and the key is // actually the value. Key string `json:"value"` }
ZipkinTimeAnnotation defines Zipkin's time annotation json format.