Copyright 2017, OpenCensus Authors Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

package trace

import (
	
	crand 
	
	
	
	
	
	

	
	
)
Span represents a span of a trace. It has an associated SpanContext, and stores data accumulated while the span is active. Ideally users should interact with Spans by calling the functions in this package that take a Context parameter.
data contains information recorded about the span. It will be non-nil if we are exporting the span or recording events for it. Otherwise, data is nil, and the Span is simply a carrier for the SpanContext, so that the trace ID is propagated.
	data        *SpanData
	mu          sync.Mutex // protects the contents of *data (but not the pointer value.)
	spanContext SpanContext
lruAttributes are capped at configured limit. When the capacity is reached an oldest entry is removed to create room for a new entry.
annotations are stored in FIFO queue capped by configured limit.
messageEvents are stored in FIFO queue capped by configured limit.
links are stored in FIFO queue capped by configured limit.
spanStore is the spanStore this span belongs to, if any, otherwise it is nil.
	*spanStore
	endOnce sync.Once

	executionTracerTaskEnd func() // ends the execution tracer span
}
IsRecordingEvents returns true if events are being recorded for this span. Use this check to avoid computing expensive annotations when they will never be used.
func ( *Span) () bool {
	if  == nil {
		return false
	}
	return .data != nil
}
TraceOptions contains options associated with a trace span.
IsSampled returns true if the span will be exported.
func ( SpanContext) () bool {
	return .TraceOptions.IsSampled()
}
setIsSampled sets the TraceOptions bit that determines whether the span will be exported.
func ( *SpanContext) ( bool) {
	if  {
		.TraceOptions |= 1
	} else {
		.TraceOptions &= ^TraceOptions(1)
	}
}
IsSampled returns true if the span will be exported.
func ( TraceOptions) () bool {
	return &1 == 1
}
SpanContext contains the state that must propagate across process boundaries. SpanContext is not an implementation of context.Context. TODO: add reference to external Census docs for SpanContext.
FromContext returns the Span stored in a context, or nil if there isn't one.
func ( context.Context) *Span {
	,  := .Value(contextKey{}).(*Span)
	return 
}
NewContext returns a new context with the given Span attached.
func ( context.Context,  *Span) context.Context {
	return context.WithValue(, contextKey{}, )
}
All available span kinds. Span kind must be either one of these values.
StartOptions contains options concerning how a span is started.
Sampler to consult for this Span. If provided, it is always consulted. If not provided, then the behavior differs based on whether the parent of this Span is remote, local, or there is no parent. In the case of a remote parent or no parent, the default sampler (see Config) will be consulted. Otherwise, when there is a non-remote parent, no new sampling decision will be made: we will preserve the sampling of the parent.
SpanKind represents the kind of a span. If none is set, SpanKindUnspecified is used.
StartOption apply changes to StartOptions.
WithSpanKind makes new spans to be created with the given kind.
func ( int) StartOption {
	return func( *StartOptions) {
		.SpanKind = 
	}
}
WithSampler makes new spans to be be created with a custom sampler. Otherwise, the global sampler is used.
func ( Sampler) StartOption {
	return func( *StartOptions) {
		.Sampler = 
	}
}
StartSpan starts a new child span of the current span in the context. If there is no span in the context, creates a new trace and span. Returned context contains the newly created span. You can use it to propagate the returned span in process.
func ( context.Context,  string,  ...StartOption) (context.Context, *Span) {
	var  StartOptions
	var  SpanContext
	if  := FromContext();  != nil {
		.addChild()
		 = .spanContext
	}
	for ,  := range  {
		(&)
	}
	 := startSpanInternal(,  != SpanContext{}, , false, )

	,  := startExecutionTracerTask(, )
	.executionTracerTaskEnd = 
	return NewContext(, ), 
}
StartSpanWithRemoteParent starts a new child span of the span from the given parent. If the incoming context contains a parent, it ignores. StartSpanWithRemoteParent is preferred for cases where the parent is propagated via an incoming request. Returned context contains the newly created span. You can use it to propagate the returned span in process.
func ( context.Context,  string,  SpanContext,  ...StartOption) (context.Context, *Span) {
	var  StartOptions
	for ,  := range  {
		(&)
	}
	 := startSpanInternal(,  != SpanContext{}, , true, )
	,  := startExecutionTracerTask(, )
	.executionTracerTaskEnd = 
	return NewContext(, ), 
}

func ( string,  bool,  SpanContext,  bool,  StartOptions) *Span {
	 := &Span{}
	.spanContext = 

	 := config.Load().(*Config)

	if ! {
		.spanContext.TraceID = .IDGenerator.NewTraceID()
	}
	.spanContext.SpanID = .IDGenerator.NewSpanID()
	 := .DefaultSampler

If this span is the child of a local span and no Sampler is set in the options, keep the parent's TraceOptions. Otherwise, consult the Sampler in the options if it is non-nil, otherwise the default sampler.
End ends the span.
func ( *Span) () {
	if  == nil {
		return
	}
	if .executionTracerTaskEnd != nil {
		.executionTracerTaskEnd()
	}
	if !.IsRecordingEvents() {
		return
	}
	.endOnce.Do(func() {
		,  := exporters.Load().(exportersMap)
		 := .spanContext.IsSampled() && len() > 0
		if .spanStore != nil ||  {
			 := .makeSpanData()
			.EndTime = internal.MonotonicEndTime(.StartTime)
			if .spanStore != nil {
				.spanStore.finished(, )
			}
			if  {
				for  := range  {
					.ExportSpan()
				}
			}
		}
	})
}
makeSpanData produces a SpanData representing the current state of the Span. It requires that s.data is non-nil.
SpanContext returns the SpanContext of the span.
func ( *Span) () SpanContext {
	if  == nil {
		return SpanContext{}
	}
	return .spanContext
}
SetName sets the name of the span, if it is recording events.
func ( *Span) ( string) {
	if !.IsRecordingEvents() {
		return
	}
	.mu.Lock()
	.data.Name = 
	.mu.Unlock()
}
SetStatus sets the status of the span, if it is recording events.
func ( *Span) ( Status) {
	if !.IsRecordingEvents() {
		return
	}
	.mu.Lock()
	.data.Status = 
	.mu.Unlock()
}

func ( *Span) () []Link {
	 := make([]Link, 0, len(.links.queue))
	for ,  := range .links.queue {
		 = append(, .(Link))
	}
	return 
}

func ( *Span) () []MessageEvent {
	 := make([]MessageEvent, 0, len(.messageEvents.queue))
	for ,  := range .messageEvents.queue {
		 = append(, .(MessageEvent))
	}
	return 
}

func ( *Span) () []Annotation {
	 := make([]Annotation, 0, len(.annotations.queue))
	for ,  := range .annotations.queue {
		 = append(, .(Annotation))
	}
	return 
}

func ( *Span) () map[string]interface{} {
	 := make(map[string]interface{}, .lruAttributes.len())
	for ,  := range .lruAttributes.keys() {
		,  := .lruAttributes.get()
		if  {
			 := .(string)
			[] = 
		}
	}
	return 
}

func ( *Span) ( []Attribute) {
	for ,  := range  {
		.lruAttributes.add(.key, .value)
	}
}

func ( *Span) () {
	if !.IsRecordingEvents() {
		return
	}
	.mu.Lock()
	.data.ChildSpanCount++
	.mu.Unlock()
}
AddAttributes sets attributes in the span. Existing attributes whose keys appear in the attributes parameter are overwritten.
func ( *Span) ( ...Attribute) {
	if !.IsRecordingEvents() {
		return
	}
	.mu.Lock()
	.copyToCappedAttributes()
	.mu.Unlock()
}
copyAttributes copies a slice of Attributes into a map.
func ( map[string]interface{},  []Attribute) {
	for ,  := range  {
		[.key] = .value
	}
}

func ( *Span) ( []Attribute,  string,  ...interface{}) {
	 := time.Now()
	 := fmt.Sprintf(, ...)
	var  map[string]interface{}
	.mu.Lock()
	if len() != 0 {
		 = make(map[string]interface{}, len())
		copyAttributes(, )
	}
	.annotations.add(Annotation{
		Time:       ,
		Message:    ,
		Attributes: ,
	})
	.mu.Unlock()
}

func ( *Span) ( []Attribute,  string) {
	 := time.Now()
	var  map[string]interface{}
	.mu.Lock()
	if len() != 0 {
		 = make(map[string]interface{}, len())
		copyAttributes(, )
	}
	.annotations.add(Annotation{
		Time:       ,
		Message:    ,
		Attributes: ,
	})
	.mu.Unlock()
}
Annotate adds an annotation with attributes. Attributes can be nil.
func ( *Span) ( []Attribute,  string) {
	if !.IsRecordingEvents() {
		return
	}
	.printStringInternal(, )
}
Annotatef adds an annotation with attributes.
func ( *Span) ( []Attribute,  string,  ...interface{}) {
	if !.IsRecordingEvents() {
		return
	}
	.lazyPrintfInternal(, , ...)
}
AddMessageSendEvent adds a message send event to the span. messageID is an identifier for the message, which is recommended to be unique in this span and the same between the send event and the receive event (this allows to identify a message between the sender and receiver). For example, this could be a sequence id.
func ( *Span) (, ,  int64) {
	if !.IsRecordingEvents() {
		return
	}
	 := time.Now()
	.mu.Lock()
	.messageEvents.add(MessageEvent{
		Time:                 ,
		EventType:            MessageEventTypeSent,
		MessageID:            ,
		UncompressedByteSize: ,
		CompressedByteSize:   ,
	})
	.mu.Unlock()
}
AddMessageReceiveEvent adds a message receive event to the span. messageID is an identifier for the message, which is recommended to be unique in this span and the same between the send event and the receive event (this allows to identify a message between the sender and receiver). For example, this could be a sequence id.
func ( *Span) (, ,  int64) {
	if !.IsRecordingEvents() {
		return
	}
	 := time.Now()
	.mu.Lock()
	.messageEvents.add(MessageEvent{
		Time:                 ,
		EventType:            MessageEventTypeRecv,
		MessageID:            ,
		UncompressedByteSize: ,
		CompressedByteSize:   ,
	})
	.mu.Unlock()
}
AddLink adds a link to the span.
func ( *Span) ( Link) {
	if !.IsRecordingEvents() {
		return
	}
	.mu.Lock()
	.links.add()
	.mu.Unlock()
}

func ( *Span) () string {
	if  == nil {
		return "<nil>"
	}
	if .data == nil {
		return fmt.Sprintf("span %s", .spanContext.SpanID)
	}
	.mu.Lock()
	 := fmt.Sprintf("span %s %q", .spanContext.SpanID, .data.Name)
	.mu.Unlock()
	return 
}

var config atomic.Value // access atomically

func () {
Please keep these as the first fields so that these 8 byte fields will be aligned on addresses divisible by 8, on both 32-bit and 64-bit machines when performing atomic increments and accesses. See: * https://github.com/census-instrumentation/opencensus-go/issues/587 * https://github.com/census-instrumentation/opencensus-go/issues/865 * https://golang.org/pkg/sync/atomic/#pkg-note-BUG
NewSpanID returns a non-zero span ID from a randomly-chosen sequence.
func ( *defaultIDGenerator) () [8]byte {
	var  uint64
	for  == 0 {
		 = atomic.AddUint64(&.nextSpanID, .spanIDInc)
	}
	var  [8]byte
	binary.LittleEndian.PutUint64([:], )
	return 
}
NewTraceID returns a non-zero trace ID from a randomly-chosen sequence. mu should be held while this function is called.
func ( *defaultIDGenerator) () [16]byte {
Construct the trace ID from two outputs of traceIDRand, with a constant added to each half for additional entropy.
	.Lock()
	binary.LittleEndian.PutUint64([0:8], .traceIDRand.Uint64()+.traceIDAdd[0])
	binary.LittleEndian.PutUint64([8:16], .traceIDRand.Uint64()+.traceIDAdd[1])
	.Unlock()
	return