tracing

package
v0.0.0-...-bde19ca Latest Latest
Warning

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

Go to latest
Published: Mar 28, 2020 License: BSD-3-Clause Imports: 21 Imported by: 0

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

Examples

Constants

View Source
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.

View Source
const (
	ZipkinTimeAnnotationKeyClientReceive = "cr"
	ZipkinTimeAnnotationKeyClientSend    = "cs"
	ZipkinTimeAnnotationKeyServerReceive = "sr"
	ZipkinTimeAnnotationKeyServerSend    = "ss"
)

Zipkin span well-known time annotation keys.

View Source
const (
	// String values
	ZipkinBinaryAnnotationKeyComponent      = "component"
	ZipkinBinaryAnnotationKeyLocalComponent = "lc"

	// Boolean values
	ZipkinBinaryAnnotationKeyDebug   = "debug"
	ZipkinBinaryAnnotationKeyError   = "error"
	ZipkinBinaryAnnotationKeyTimeOut = "timed_out"
)

Zipkin span well-known binary annotation keys.

View Source
const (
	// When set, this trace passes all samplers.
	FlagMaskDebug int64 = 1
)

FlagMask values.

Reference: https://github.com/'.py/blob/1ca8488bcd42c8786e6a3db35b2a99517fd07a99/baseplate/observers/tracing.py#L60-L64

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

func CreateThriftContextFromSpan(ctx context.Context, span *Span) context.Context

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

func TestWrapper(tb testing.TB) (logger log.Wrapper, startFailing func())

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

type FinishOptions struct {
	Ctx context.Context
	Err error
}

FinishOptions are the options to be converted into opentracing.FinishOptions.

All fields are optional.

func (FinishOptions) Convert

Convert converts FinishOptions into opentracing.FinishOptions which can be used in Span.FinishWithOptions().

type InvalidSpanTypeError

type InvalidSpanTypeError struct {
	ExpectedSpanType SpanType
	ActualSpanType   SpanType
}

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

func StartSpanFromHTTPContext(ctx context.Context, name string) (context.Context, *Span)

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

func StartSpanFromThriftContext(ctx context.Context, name string) (context.Context, *Span)

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

func (s *Span) AddCounter(key string, delta float64)

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

func (s *Span) BaggageItem(restrictedKey string) string

BaggageItem implements opentracing.Span.

As we don't support any extra baggage items, it always returns empty string.

func (*Span) Component

func (s *Span) Component() string

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

func (s *Span) ForeachBaggageItem(handler func(k, v string) bool)

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

func (s Span) LogError(msg string, err error)

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

func (s *Span) LogEvent(event string)

LogEvent implements opentracing.Span.

it's deprecated in the interface and is a no-op here.

func (*Span) LogEventWithPayload

func (s *Span) LogEventWithPayload(event string, payload interface{})

LogEventWithPayload implements opentracing.Span.

it's deprecated in the interface and is a noop here.

func (*Span) LogFields

func (s *Span) LogFields(fields ...log.Field)

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

func (s Span) Name() string

Name returns the name of the Span.

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

func (s *Span) SetDebug(v bool)

SetDebug sets or unsets the debug flag of this Span.

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

func (s Span) SpanType() SpanType

SpanType returns the SpanType for the Span.

func (*Span) Stop

func (s *Span) Stop(ctx context.Context, err error) error

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 SpanType

type SpanType int

SpanType enum.

const (
	SpanTypeLocal SpanType = iota
	SpanTypeClient
	SpanTypeServer
)

SpanType values.

func (SpanType) String

func (st SpanType) String() string

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

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

func (t *Tracer) Close() error

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.

Reference: https://github.com/'.py/blob/1ca8488bcd42c8786e6a3db35b2a99517fd07a99/baseplate/observers/tracing.py#L266-L280

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.

Jump to

Keyboard shortcuts

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