tracing

package
v0.0.0-...-1dc08c0 Latest Latest
Warning

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

Go to latest
Published: Jun 17, 2021 License: Apache-2.0 Imports: 32 Imported by: 0

Documentation

Index

Constants

View Source
const (
	// TagPrefix is prefixed to all tags that should be output in SHOW TRACE.
	TagPrefix = "cockroach."
	// StatTagPrefix is prefixed to all stats output in span tags.
	StatTagPrefix = TagPrefix + "stat."
)
View Source
const LogMessageField = "event"

LogMessageField is the field name used for the opentracing.Span.LogFields() for a log message.

View Source
const Snowball = "sb"

Snowball is set as Baggage on traces which are used for snowball tracing.

Variables

View Source
var (
	ErrInvalidLengthRecordedSpan = fmt.Errorf("proto: negative length found during unmarshaling")
	ErrIntOverflowRecordedSpan   = fmt.Errorf("proto: integer overflow")
)
View Source
var Recordable opentracing.StartSpanOption = recordableOption{}

Recordable is a StartSpanOption that forces creation of a real span.

When tracing is disabled all spans are noopSpans; these spans aren't capable of recording, so this option should be passed to StartSpan if the caller wants to be able to call StartRecording on the resulting span.

Functions

func AnnotateTrace

func AnnotateTrace()

AnnotateTrace adds an annotation to the golang executation tracer by calling a no-op cgo function.

func ChildSpan

func ChildSpan(ctx context.Context, opName string) (context.Context, opentracing.Span)

ChildSpan opens a span as a child of the current span in the context (if there is one). The span's tags are inherited from the ctx's log tags automatically.

Returns the new context and the new span (if any). The span should be closed via FinishSpan.

func ChildSpanSeparateRecording

func ChildSpanSeparateRecording(
	ctx context.Context, opName string,
) (context.Context, opentracing.Span)

ChildSpanSeparateRecording is like ChildSpan but the new span has separate recording (see StartChildSpan).

func ContextWithRecordingSpan

func ContextWithRecordingSpan(
	ctx context.Context, opName string,
) (retCtx context.Context, getRecording func() Recording, cancel func())

ContextWithRecordingSpan returns a context with an embedded trace span which returns its contents when getRecording is called and must be stopped by calling the cancel method when done with the context (getRecording() needs to be called before cancel()).

Note that to convert the recorded spans into text, you can use Recording.String(). Tests can also use FindMsgInRecording().

func EnsureChildSpan

func EnsureChildSpan(
	ctx context.Context, tracer opentracing.Tracer, name string,
) (context.Context, opentracing.Span)

EnsureChildSpan is the same as EnsureContext, except it creates a child span for the input context if the input context already has an active trace.

The caller is responsible for closing the span (via Span.Finish).

func EnsureContext

func EnsureContext(
	ctx context.Context, tracer opentracing.Tracer, opName string,
) (context.Context, func())

EnsureContext checks whether the given context.Context contains a Span. If not, it creates one using the provided Tracer and wraps it in the returned Span. The returned closure must be called after the request has been fully processed.

Note that, if there's already a span in the context, this method does nothing even if the current context's log tags are different from that span's tags.

func FindMsgInRecording

func FindMsgInRecording(recording Recording, msg string) int

FindMsgInRecording returns the index of the first span containing msg in its logs, or -1 if no span is found.

func FinishSpan

func FinishSpan(span opentracing.Span)

FinishSpan closes the given span (if not nil). It is a convenience wrapper for span.Finish() which tolerates nil spans.

func ForkCtxSpan

func ForkCtxSpan(ctx context.Context, opName string) (context.Context, opentracing.Span)

ForkCtxSpan checks if ctx has a Span open; if it does, it creates a new Span that "follows from" the original Span. This allows the resulting context to be used in an async task that might outlive the original operation.

Returns the new context and the new span (if any). The span should be closed via FinishSpan.

See also ChildSpan() for a "parent-child relationship".

func ImportRemoteSpans

func ImportRemoteSpans(os opentracing.Span, remoteSpans []RecordedSpan) error

ImportRemoteSpans adds RecordedSpan data to the recording of the given span; these spans will be part of the result of GetRecording. Used to import recorded traces from other nodes.

func IsBlackHoleSpan

func IsBlackHoleSpan(s opentracing.Span) bool

IsBlackHoleSpan returns true if events for this span are just dropped. This is the case when tracing is disabled and we're not recording. Tracing clients can use this method to figure out if they can short-circuit some tracing-related work that would be discarded anyway.

func IsNoopContext

func IsNoopContext(spanCtx opentracing.SpanContext) bool

IsNoopContext returns true if the span context is from a "no-op" span. If this is true, any span derived from this context will be a "black hole span".

func IsRecordable

func IsRecordable(os opentracing.Span) bool

IsRecordable returns true if {Start,Stop}Recording() can be called on this span.

In other words, this tests if the span is our custom type, and not a noopSpan or anything else.

func IsRecording

func IsRecording(s opentracing.Span) bool

IsRecording returns true if the span is recording its events.

func LogTags

LogTags returns a StartSpanOption that sets the span tags to the given log tags. When applied, the returned option will apply any logtag name->span tag name remapping that has been registered via RegisterTagRemapping.

func LogTagsFromCtx

func LogTagsFromCtx(ctx context.Context) opentracing.StartSpanOption

LogTagsFromCtx returns a StartSpanOption that sets the span tags to the log tags in the context.

func RegisterTagRemapping

func RegisterTagRemapping(logTag, spanTag string)

RegisterTagRemapping sets the span tag name that corresponds to the given log tag name. Should be called as part of an init() function.

func SetSpanStats

func SetSpanStats(os opentracing.Span, stats SpanStats)

SetSpanStats sets the stats on a span. stats.Stats() will also be added to the span tags.

func StartChildSpan

func StartChildSpan(
	opName string, parentSpan opentracing.Span, logTags *logtags.Buffer, separateRecording bool,
) opentracing.Span

StartChildSpan creates a child span of the given parent span. This is functionally equivalent to: parentSpan.Tracer().(*Tracer).StartSpan(opName, opentracing.ChildOf(parentSpan.Context())) Compared to that, it's more efficient, particularly in terms of memory allocations; among others, it saves the call to parentSpan.Context.

This only works for creating children of local parents (i.e. the caller needs to have a reference to the parent span).

If separateRecording is true and the parent span is recording, the child's recording will not be part of the parent's recording. This is useful when the child's recording will be reported to a collector separate from the parent's recording; for example DistSQL processors each report their own recording, and we don't want the parent's recording to include a child's because then we might double-report that child.

func StartRecording

func StartRecording(os opentracing.Span, recType RecordingType)

StartRecording enables recording on the span. Events from this point forward are recorded; also, all direct and indirect child spans started from now on will be part of the same recording.

Recording is not supported by noop spans; to ensure a real span is always created, use the Recordable option to StartSpan.

If recording was already started on this span (either directly or because a parent span is recording), the old recording is lost.

func StartSnowballTrace

func StartSnowballTrace(
	ctx context.Context, tracer opentracing.Tracer, opName string,
) (context.Context, opentracing.Span)

StartSnowballTrace takes in a context and returns a derived one with a "snowball span" in it. The caller takes ownership of this span from the returned context and is in charge of Finish()ing it. The span has recording enabled.

TODO(andrei): remove this method once EXPLAIN(TRACE) is gone.

func StopRecording

func StopRecording(os opentracing.Span)

StopRecording disables recording on this span. Child spans that were created since recording was started will continue to record until they finish.

Calling this after StartRecording is not required; the recording will go away when all the spans finish.

StopRecording() can be called on a Finish()ed span.

func TestingCheckRecordedSpans

func TestingCheckRecordedSpans(recSpans []RecordedSpan, expected string) error

TestingCheckRecordedSpans checks whether a recording looks like an expected one represented by a string with one line per expected span and one line per expected event (i.e. log message).

Use with something like:

	 if err := TestingCheckRecordedSpans(tracing.GetRecording(span), `
    span root:
      event: a
      event: c
    span child:
      event: [ambient] b
  `); err != nil {
  	t.Fatal(err)
  }

The event lines can (and generally should) omit the file:line part that they might contain (depending on the level at which they were logged).

Note: this test function is in this file because it needs to be used by both tests in the tracing package and tests outside of it, and the function itself depends on tracing.

Types

type LogRecord

type LogRecord struct {
	// Time of the log record.
	Time time.Time `protobuf:"bytes,1,opt,name=time,proto3,stdtime" json:"time"`
	// Fields with values converted to strings.
	Fields []LogRecord_Field `protobuf:"bytes,2,rep,name=fields,proto3" json:"fields"`
}

LogRecord is a log message recorded in a traced span.

func (*LogRecord) Descriptor

func (*LogRecord) Descriptor() ([]byte, []int)

func (*LogRecord) Marshal

func (m *LogRecord) Marshal() (dAtA []byte, err error)

func (*LogRecord) MarshalTo

func (m *LogRecord) MarshalTo(dAtA []byte) (int, error)

func (LogRecord) Msg

func (l LogRecord) Msg() string

Msg extracts the message of the LogRecord, which is either in an "event" or "error" field.

func (*LogRecord) ProtoMessage

func (*LogRecord) ProtoMessage()

func (*LogRecord) Reset

func (m *LogRecord) Reset()

func (*LogRecord) Size

func (m *LogRecord) Size() (n int)

func (*LogRecord) String

func (m *LogRecord) String() string

func (*LogRecord) Unmarshal

func (m *LogRecord) Unmarshal(dAtA []byte) error

func (*LogRecord) XXX_DiscardUnknown

func (m *LogRecord) XXX_DiscardUnknown()

func (*LogRecord) XXX_Marshal

func (m *LogRecord) XXX_Marshal(b []byte, deterministic bool) ([]byte, error)

func (*LogRecord) XXX_Merge

func (m *LogRecord) XXX_Merge(src proto.Message)

func (*LogRecord) XXX_Size

func (m *LogRecord) XXX_Size() int

func (*LogRecord) XXX_Unmarshal

func (m *LogRecord) XXX_Unmarshal(b []byte) error

type LogRecord_Field

type LogRecord_Field struct {
	Key   string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"`
	Value string `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"`
}

func (*LogRecord_Field) Descriptor

func (*LogRecord_Field) Descriptor() ([]byte, []int)

func (*LogRecord_Field) Marshal

func (m *LogRecord_Field) Marshal() (dAtA []byte, err error)

func (*LogRecord_Field) MarshalTo

func (m *LogRecord_Field) MarshalTo(dAtA []byte) (int, error)

func (*LogRecord_Field) ProtoMessage

func (*LogRecord_Field) ProtoMessage()

func (*LogRecord_Field) Reset

func (m *LogRecord_Field) Reset()

func (*LogRecord_Field) Size

func (m *LogRecord_Field) Size() (n int)

func (*LogRecord_Field) String

func (m *LogRecord_Field) String() string

func (*LogRecord_Field) Unmarshal

func (m *LogRecord_Field) Unmarshal(dAtA []byte) error

func (*LogRecord_Field) XXX_DiscardUnknown

func (m *LogRecord_Field) XXX_DiscardUnknown()

func (*LogRecord_Field) XXX_Marshal

func (m *LogRecord_Field) XXX_Marshal(b []byte, deterministic bool) ([]byte, error)

func (*LogRecord_Field) XXX_Merge

func (m *LogRecord_Field) XXX_Merge(src proto.Message)

func (*LogRecord_Field) XXX_Size

func (m *LogRecord_Field) XXX_Size() int

func (*LogRecord_Field) XXX_Unmarshal

func (m *LogRecord_Field) XXX_Unmarshal(b []byte) error

type NormalizedSpan

type NormalizedSpan struct {
	Operation string            `protobuf:"bytes,1,opt,name=operation,proto3" json:"operation,omitempty"`
	Tags      map[string]string `` /* 149-byte string literal not displayed */
	StartTime time.Time         `protobuf:"bytes,3,opt,name=start_time,json=startTime,proto3,stdtime" json:"start_time"`
	Duration  time.Duration     `protobuf:"bytes,4,opt,name=duration,proto3,stdduration" json:"duration"`
	Logs      []LogRecord       `protobuf:"bytes,5,rep,name=logs,proto3" json:"logs"`
	Children  []NormalizedSpan  `protobuf:"bytes,6,rep,name=children,proto3" json:"children"`
}

NormalizedSpan is a representation of a RecordedSpan from a trace with all its children embedded, recursively. This JSON serialization of this proto is used in the system.statement_diagnostics.trace column.

See RecordedSpan for the description of the fields.

func (*NormalizedSpan) Descriptor

func (*NormalizedSpan) Descriptor() ([]byte, []int)

func (*NormalizedSpan) Marshal

func (m *NormalizedSpan) Marshal() (dAtA []byte, err error)

func (*NormalizedSpan) MarshalTo

func (m *NormalizedSpan) MarshalTo(dAtA []byte) (int, error)

func (*NormalizedSpan) ProtoMessage

func (*NormalizedSpan) ProtoMessage()

func (*NormalizedSpan) Reset

func (m *NormalizedSpan) Reset()

func (*NormalizedSpan) Size

func (m *NormalizedSpan) Size() (n int)

func (*NormalizedSpan) String

func (m *NormalizedSpan) String() string

func (*NormalizedSpan) Unmarshal

func (m *NormalizedSpan) Unmarshal(dAtA []byte) error

func (*NormalizedSpan) XXX_DiscardUnknown

func (m *NormalizedSpan) XXX_DiscardUnknown()

func (*NormalizedSpan) XXX_Marshal

func (m *NormalizedSpan) XXX_Marshal(b []byte, deterministic bool) ([]byte, error)

func (*NormalizedSpan) XXX_Merge

func (m *NormalizedSpan) XXX_Merge(src proto.Message)

func (*NormalizedSpan) XXX_Size

func (m *NormalizedSpan) XXX_Size() int

func (*NormalizedSpan) XXX_Unmarshal

func (m *NormalizedSpan) XXX_Unmarshal(b []byte) error

type RecordableOpt

type RecordableOpt bool

RecordableOpt specifies whether a root span should be recordable.

const (
	// RecordableSpan means that the root span will be recordable. This means that
	// a real span will be created (and so it carries a cost).
	RecordableSpan RecordableOpt = true
	// NonRecordableSpan means that the root span will not be recordable. This
	// means that the static noop span might be returned.
	NonRecordableSpan RecordableOpt = false
)

type RecordedSpan

type RecordedSpan struct {
	// ID of the trace; spans that are part of the same hierarchy share
	// the same trace ID.
	TraceID uint64 `protobuf:"varint,1,opt,name=trace_id,json=traceId,proto3" json:"trace_id,omitempty"`
	// ID of the span.
	SpanID uint64 `protobuf:"varint,2,opt,name=span_id,json=spanId,proto3" json:"span_id,omitempty"`
	// Span ID of the parent span.
	ParentSpanID uint64 `protobuf:"varint,3,opt,name=parent_span_id,json=parentSpanId,proto3" json:"parent_span_id,omitempty"`
	// Operation name.
	Operation string `protobuf:"bytes,4,opt,name=operation,proto3" json:"operation,omitempty"`
	// Baggage items get passed from parent to child spans (even through gRPC).
	// Notably, snowball tracing uses a special `sb` baggage item.
	Baggage map[string]string `` /* 155-byte string literal not displayed */
	// Tags associated with the span.
	Tags map[string]string `` /* 149-byte string literal not displayed */
	// Time when the span was started.
	StartTime time.Time `protobuf:"bytes,7,opt,name=start_time,json=startTime,proto3,stdtime" json:"start_time"`
	// Duration is the span's duration, measured from start to Finish().
	//
	// A spans whose recording is collected before it's finished will have the
	// duration set as the time of collection - start_time. Such a span will have
	// an "unfinished" tag.
	Duration time.Duration `protobuf:"bytes,8,opt,name=duration,proto3,stdduration" json:"duration"`
	// Events logged in the span.
	Logs []LogRecord `protobuf:"bytes,9,rep,name=logs,proto3" json:"logs"`
	// Stats collected in this span.
	Stats *types.Any `protobuf:"bytes,10,opt,name=stats,proto3" json:"stats,omitempty"`
}

RecordedSpan is a span that is part of a recording. It can be transferred over the wire for snowball tracing.

func (*RecordedSpan) Descriptor

func (*RecordedSpan) Descriptor() ([]byte, []int)

func (*RecordedSpan) Marshal

func (m *RecordedSpan) Marshal() (dAtA []byte, err error)

func (*RecordedSpan) MarshalTo

func (m *RecordedSpan) MarshalTo(dAtA []byte) (int, error)

func (*RecordedSpan) ProtoMessage

func (*RecordedSpan) ProtoMessage()

func (*RecordedSpan) Reset

func (m *RecordedSpan) Reset()

func (*RecordedSpan) Size

func (m *RecordedSpan) Size() (n int)

func (*RecordedSpan) String

func (s *RecordedSpan) String() string

func (*RecordedSpan) Unmarshal

func (m *RecordedSpan) Unmarshal(dAtA []byte) error

func (*RecordedSpan) XXX_DiscardUnknown

func (m *RecordedSpan) XXX_DiscardUnknown()

func (*RecordedSpan) XXX_Marshal

func (m *RecordedSpan) XXX_Marshal(b []byte, deterministic bool) ([]byte, error)

func (*RecordedSpan) XXX_Merge

func (m *RecordedSpan) XXX_Merge(src proto.Message)

func (*RecordedSpan) XXX_Size

func (m *RecordedSpan) XXX_Size() int

func (*RecordedSpan) XXX_Unmarshal

func (m *RecordedSpan) XXX_Unmarshal(b []byte) error

type Recording

type Recording []RecordedSpan

Recording represents a group of RecordedSpans, as returned by GetRecording. Spans are sorted by StartTime.

func GetRecording

func GetRecording(os opentracing.Span) Recording

GetRecording retrieves the current recording, if the span has recording enabled. This can be called while spans that are part of the recording are still open; it can run concurrently with operations on those spans.

func (Recording) FindLogMessage

func (r Recording) FindLogMessage(pattern string) (string, bool)

FindLogMessage returns the first log message in the recording that matches the given regexp. The bool return value is true if such a message is found.

func (Recording) FindSpan

func (r Recording) FindSpan(operation string) (RecordedSpan, bool)

FindSpan returns the span with the given operation. The bool retval is false if the span is not found.

func (Recording) OrphanSpans

func (r Recording) OrphanSpans() []RecordedSpan

OrphanSpans returns the spans with parents missing from the recording.

func (Recording) String

func (r Recording) String() string

String formats the given spans for human consumption, showing the relationship using nesting and times as both relative to the previous event and cumulative.

Child spans are inserted into the parent at the point of the child's StartTime; see the diagram on generateSessionTraceVTable() for the ordering of messages.

Each log line show the time since the beginning of the trace and since the previous log line. Span starts are shown with special "=== <operation>" lines. For a span start, the time since the relative log line can be negative when the span start follows a message from the parent that was generated after the child span started (or even after the child finished).

TODO(andrei): this should be unified with SessionTracing.generateSessionTraceVTable().

func (Recording) ToJaegerJSON

func (r Recording) ToJaegerJSON(stmt string) (string, error)

ToJaegerJSON returns the trace as a JSON that can be imported into Jaeger for visualization.

The format is described here: https://github.com/jaegertracing/jaeger-ui/issues/381#issuecomment-494150826

The statement is passed in so it can be included in the trace.

type RecordingType

type RecordingType int

RecordingType is the type of recording that a span might be performing.

const (
	// NoRecording means that the span isn't recording.
	NoRecording RecordingType = iota
	// SnowballRecording means that remote child spans (generally opened through
	// RPCs) are also recorded.
	SnowballRecording
	// SingleNodeRecording means that only spans on the current node are recorded.
	SingleNodeRecording
)

type SpanStats

type SpanStats interface {
	proto.Message
	// Stats returns the stats that the object represents as a map from stat name
	// to value to be added to span tags. The keys will be prefixed with
	// StatTagPrefix.
	Stats() map[string]string
}

SpanStats are stats that can be added to a span.

type TraceCollection

type TraceCollection struct {
	// Comment is a dummy field we use to put instructions on how to load the trace.
	Comment string             `json:"_comment"`
	Data    []jaegerjson.Trace `json:"data"`
}

TraceCollection is the format accepted by the Jaegar upload feature, as per https://github.com/jaegertracing/jaeger-ui/issues/381#issuecomment-494150826

type Tracer

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

Tracer is our own custom implementation of opentracing.Tracer. It supports:

  • forwarding events to x/net/trace instances

  • recording traces. Recording is started automatically for spans that have the Snowball baggage and can be started explicitly as well. Recorded events can be retrieved at any time.

  • lightstep traces. This is implemented by maintaining a "shadow" lightstep span inside each of our spans.

Even when tracing is disabled, we still use this Tracer (with x/net/trace and lightstep disabled) because of its recording capability (snowball tracing needs to work in all cases).

Tracer is currently stateless so we could have a single instance; however, this won't be the case if the cluster settings move away from using global state.

func NewTracer

func NewTracer() *Tracer

NewTracer creates a Tracer. It initially tries to run with minimal overhead and collects essentially nothing; use Configure() to enable various tracing backends.

func (*Tracer) AlwaysTrace

func (t *Tracer) AlwaysTrace() bool

AlwaysTrace returns true if operations should be traced regardless of the context.

func (*Tracer) Close

func (t *Tracer) Close()

Close cleans up any resources associated with a Tracer.

func (*Tracer) Configure

func (t *Tracer) Configure(sv *settings.Values)

Configure sets up the Tracer according to the cluster settings (and keeps it updated if they change).

func (*Tracer) Extract

func (t *Tracer) Extract(format interface{}, carrier interface{}) (opentracing.SpanContext, error)

Extract is part of the opentracing.Tracer interface. It always returns a valid context, even in error cases (this is assumed by the grpc-opentracing interceptor).

func (*Tracer) Inject

func (t *Tracer) Inject(
	osc opentracing.SpanContext, format interface{}, carrier interface{},
) error

Inject is part of the opentracing.Tracer interface.

func (*Tracer) SetForceRealSpans

func (t *Tracer) SetForceRealSpans(v bool) bool

SetForceRealSpans sets forceRealSpans option to v and returns the previous value.

func (*Tracer) StartRootSpan

func (t *Tracer) StartRootSpan(
	opName string, logTags *logtags.Buffer, recordable RecordableOpt,
) opentracing.Span

StartRootSpan creates a root span. This is functionally equivalent to: parentSpan.Tracer().(*Tracer).StartSpan(opName, LogTags(...), Recordable) Compared to that, it's more efficient, particularly in terms of memory allocations because the opentracing.StartSpanOption interface is not used.

logTags can be nil.

func (*Tracer) StartSpan

func (t *Tracer) StartSpan(
	operationName string, opts ...opentracing.StartSpanOption,
) opentracing.Span

StartSpan is part of the opentracing.Tracer interface.

Avoid using this method in favor of Tracer.StartRootSpan() or tracing.StartChildSpan() (or higher-level methods like EnsureContext() or AmbientContext.AnnotateCtxWithSpan()) when possible. Those are more efficient because they don't have to use the StartSpanOption interface and so a bunch of allocations are avoided. However, we need to implement this standard StartSpan() too because grpc integrates with a generic opentracing.Tracer.

Jump to

Keyboard shortcuts

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