func copyAttributes(m map[string]interface{}, attributes []Attribute) {
	for _, a := range attributes {
		switch a := a.(type) {
		case BoolAttribute:
			m[a.Key] = a.Value
		case Int64Attribute:
			m[a.Key] = a.Value
		case StringAttribute:
			m[a.Key] = a.Value
		}
	}
}
copyAttributes copies a slice of Attributes into a map.
package trace
import (
	"context"
	crand "crypto/rand"
	"encoding/binary"
	"fmt"
	"math/rand"
	"runtime"
	"sync"
	"time"
)
type Span struct {
	data        *SpanData
	mu          sync.Mutex  
	spanContext SpanContext
	*spanStore
}
func IsRecordingEvents(ctx context.Context) bool {
	s, ok := ctx.Value(contextKey{}).(*Span)
	if !ok {
		return false
	}
	return s.IsRecordingEvents()
}
func (s *Span) IsRecordingEvents() bool {
	if s == nil {
		return false
	}
	return s.data != nil
}
type TraceOptions uint32
func IsSampled(ctx context.Context) bool {
	s, ok := ctx.Value(contextKey{}).(*Span)
	if !ok {
		return false
	}
	return s.IsSampled()
}
func (s *Span) IsSampled() bool {
	if s == nil {
		return false
	}
	return s.spanContext.IsSampled()
}
func (sc SpanContext) IsSampled() bool {
	return sc.TraceOptions.IsSampled()
}
func (sc *SpanContext) setIsSampled(sampled bool) {
	if sampled {
		sc.TraceOptions |= 1
	} else {
		sc.TraceOptions &= ^TraceOptions(1)
	}
}
func (t TraceOptions) IsSampled() bool {
	return t&1 == 1
}
type SpanContext struct {
	TraceID
	SpanID
	TraceOptions
}
type contextKey struct{}
func FromContext(ctx context.Context) *Span {
	s, _ := ctx.Value(contextKey{}).(*Span)
	return s
}
func WithSpan(parent context.Context, s *Span) context.Context {
	return context.WithValue(parent, contextKey{}, s)
}
type StartSpanOptions struct {
	RecordEvents bool
	Sampler       
	RegisterNameForLocalSpanStore bool
}
func StartSpan(ctx context.Context, name string) context.Context {
	parentSpan, _ := ctx.Value(contextKey{}).(*Span)
	return WithSpan(ctx, parentSpan.StartSpanWithOptions(name, StartSpanOptions{}))
}
func StartSpanWithOptions(ctx context.Context, name string, o StartSpanOptions) context.Context {
	parentSpan, _ := ctx.Value(contextKey{}).(*Span)
	return WithSpan(ctx, parentSpan.StartSpanWithOptions(name, o))
}
func StartSpanWithRemoteParent(ctx context.Context, name string, parent SpanContext, o StartSpanOptions) context.Context {
	return WithSpan(ctx, NewSpanWithRemoteParent(name, parent, o))
}
func (s *Span) StartSpan(name string) *Span {
	return s.StartSpanWithOptions(name, StartSpanOptions{})
}
func (s *Span) StartSpanWithOptions(name string, o StartSpanOptions) *Span {
	if s != nil {
		return startSpanInternal(name, true, s.spanContext, false, o)
	}
	return startSpanInternal(name, false, SpanContext{}, false, o)
}
func NewSpan(name string, o StartSpanOptions) *Span {
	return startSpanInternal(name, false, SpanContext{}, false, o)
}
func NewSpanWithRemoteParent(name string, parent SpanContext, o StartSpanOptions) *Span {
	return startSpanInternal(name, true, parent, true, o)
}
func startSpanInternal(name string, hasParent bool, parent SpanContext, remoteParent bool, o StartSpanOptions) *Span {
	span := &Span{}
	span.spanContext = parent
	mu.Lock()
	if !hasParent {
		span.spanContext.TraceID = newTraceIDLocked()
	}
	span.spanContext.SpanID = newSpanIDLocked()
	sampler := defaultSampler
	mu.Unlock()
	if !hasParent || remoteParent || o.Sampler != nil {
		if o.Sampler != nil {
			sampler = o.Sampler
		}
		span.spanContext.setIsSampled(sampler.Sample(SamplingParameters{
			ParentContext:   parent,
			TraceID:         span.spanContext.TraceID,
			SpanID:          span.spanContext.SpanID,
			Name:            name,
			HasRemoteParent: remoteParent}).Sample)
	}
	if !o.RecordEvents && !span.spanContext.IsSampled() {
		return span
	}
	span.data = &SpanData{
		SpanContext:     span.spanContext,
		StartTime:       time.Now(),
		Name:            name,
		HasRemoteParent: remoteParent,
	}
	if hasParent {
		span.data.ParentSpanID = parent.SpanID
	}
	if o.RecordEvents {
		var ss *spanStore
		if o.RegisterNameForLocalSpanStore {
			ss = spanStoreForNameCreateIfNew(name)
		} else {
			ss = spanStoreForName(name)
		}
		if ss != nil {
			span.spanStore = ss
			ss.add(span)
		}
	}
	return span
}
func EndSpan(ctx context.Context) {
	s, ok := ctx.Value(contextKey{}).(*Span)
	if !ok {
		return
	}
	s.End()
}
func (s *Span) End() {
	if !s.IsRecordingEvents() {
		return
	}
	sd := s.makeSpanData()
	sd.EndTime = time.Now()
	if s.spanStore != nil {
		s.spanStore.finished(s, sd)
	}
	if s.spanContext.IsSampled() {
		exportersMu.Lock()
		for e := range exporters {
			e.Export(sd)
		}
		exportersMu.Unlock()
	}
}
func (s *Span) makeSpanData() *SpanData {
	var sd SpanData
	s.mu.Lock()
	sd = *s.data
	if s.data.Attributes != nil {
		sd.Attributes = make(map[string]interface{})
		for k, v := range s.data.Attributes {
			sd.Attributes[k] = v
		}
	}
	s.mu.Unlock()
	return &sd
}
func SpanContextFromContext(ctx context.Context) (SpanContext, bool) {
	s, _ := ctx.Value(contextKey{}).(*Span)
	if s == nil {
		return SpanContext{}, false
	}
	return s.SpanContext(), true
}
func (s *Span) SpanContext() SpanContext {
	if s == nil {
		return SpanContext{}
	}
	return s.spanContext
}
func SetSpanStatus(ctx context.Context, status Status) {
	s, ok := ctx.Value(contextKey{}).(*Span)
	if !ok {
		return
	}
	s.SetStatus(status)
}
func (s *Span) SetStatus(status Status) {
	if !s.IsRecordingEvents() {
		return
	}
	s.mu.Lock()
	s.data.Status = status
	s.mu.Unlock()
}
func SetSpanAttributes(ctx context.Context, attributes ...Attribute) {
	s, ok := ctx.Value(contextKey{}).(*Span)
	if !ok {
		return
	}
	s.SetAttributes(attributes...)
}
func (s *Span) SetAttributes(attributes ...Attribute) {
	if !s.IsRecordingEvents() {
		return
	}
	s.mu.Lock()
	if s.data.Attributes == nil {
		s.data.Attributes = make(map[string]interface{})
	}
	copyAttributes(s.data.Attributes, attributes)
	s.mu.Unlock()
}