mirror of
https://github.com/ceph/ceph-csi.git
synced 2025-06-13 18:43:34 +00:00
rebase: update kubernetes and libraries to v1.22.0 version
Kubernetes v1.22 version has been released and this update ceph csi dependencies to use the same version. Signed-off-by: Humble Chirammal <hchiramm@redhat.com>
This commit is contained in:
committed by
mergify[bot]
parent
e077c1fdf5
commit
aa698bc3e1
91
vendor/go.opentelemetry.io/otel/sdk/trace/attributesmap.go
generated
vendored
Normal file
91
vendor/go.opentelemetry.io/otel/sdk/trace/attributesmap.go
generated
vendored
Normal file
@ -0,0 +1,91 @@
|
||||
// Copyright The OpenTelemetry 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 "go.opentelemetry.io/otel/sdk/trace"
|
||||
|
||||
import (
|
||||
"container/list"
|
||||
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
)
|
||||
|
||||
// attributesMap is a capped map of attributes, holding the most recent attributes.
|
||||
// Eviction is done via a LRU method, the oldest entry is removed to create room for a new entry.
|
||||
// Updates are allowed and they refresh the usage of the key.
|
||||
//
|
||||
// This is based from https://github.com/hashicorp/golang-lru/blob/master/simplelru/lru.go
|
||||
// With a subset of the its operations and specific for holding attribute.KeyValue
|
||||
type attributesMap struct {
|
||||
attributes map[attribute.Key]*list.Element
|
||||
evictList *list.List
|
||||
droppedCount int
|
||||
capacity int
|
||||
}
|
||||
|
||||
func newAttributesMap(capacity int) *attributesMap {
|
||||
lm := &attributesMap{
|
||||
attributes: make(map[attribute.Key]*list.Element),
|
||||
evictList: list.New(),
|
||||
capacity: capacity,
|
||||
}
|
||||
return lm
|
||||
}
|
||||
|
||||
func (am *attributesMap) add(kv attribute.KeyValue) {
|
||||
// Check for existing item
|
||||
if ent, ok := am.attributes[kv.Key]; ok {
|
||||
am.evictList.MoveToFront(ent)
|
||||
ent.Value = &kv
|
||||
return
|
||||
}
|
||||
|
||||
// Add new item
|
||||
entry := am.evictList.PushFront(&kv)
|
||||
am.attributes[kv.Key] = entry
|
||||
|
||||
// Verify size not exceeded
|
||||
if am.evictList.Len() > am.capacity {
|
||||
am.removeOldest()
|
||||
am.droppedCount++
|
||||
}
|
||||
}
|
||||
|
||||
// toKeyValue copies the attributesMap into a slice of attribute.KeyValue and
|
||||
// returns it. If the map is empty, a nil is returned.
|
||||
// TODO: Is it more efficient to return a pointer to the slice?
|
||||
func (am *attributesMap) toKeyValue() []attribute.KeyValue {
|
||||
len := am.evictList.Len()
|
||||
if len == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
attributes := make([]attribute.KeyValue, 0, len)
|
||||
for ent := am.evictList.Back(); ent != nil; ent = ent.Prev() {
|
||||
if value, ok := ent.Value.(*attribute.KeyValue); ok {
|
||||
attributes = append(attributes, *value)
|
||||
}
|
||||
}
|
||||
|
||||
return attributes
|
||||
}
|
||||
|
||||
// removeOldest removes the oldest item from the cache.
|
||||
func (am *attributesMap) removeOldest() {
|
||||
ent := am.evictList.Back()
|
||||
if ent != nil {
|
||||
am.evictList.Remove(ent)
|
||||
kv := ent.Value.(*attribute.KeyValue)
|
||||
delete(am.attributes, kv.Key)
|
||||
}
|
||||
}
|
328
vendor/go.opentelemetry.io/otel/sdk/trace/batch_span_processor.go
generated
vendored
Normal file
328
vendor/go.opentelemetry.io/otel/sdk/trace/batch_span_processor.go
generated
vendored
Normal file
@ -0,0 +1,328 @@
|
||||
// Copyright The OpenTelemetry 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 "go.opentelemetry.io/otel/sdk/trace"
|
||||
|
||||
import (
|
||||
"context"
|
||||
"runtime"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"go.opentelemetry.io/otel"
|
||||
)
|
||||
|
||||
const (
|
||||
DefaultMaxQueueSize = 2048
|
||||
DefaultBatchTimeout = 5000 * time.Millisecond
|
||||
DefaultExportTimeout = 30000 * time.Millisecond
|
||||
DefaultMaxExportBatchSize = 512
|
||||
)
|
||||
|
||||
type BatchSpanProcessorOption func(o *BatchSpanProcessorOptions)
|
||||
|
||||
type BatchSpanProcessorOptions struct {
|
||||
// MaxQueueSize is the maximum queue size to buffer spans for delayed processing. If the
|
||||
// queue gets full it drops the spans. Use BlockOnQueueFull to change this behavior.
|
||||
// The default value of MaxQueueSize is 2048.
|
||||
MaxQueueSize int
|
||||
|
||||
// BatchTimeout is the maximum duration for constructing a batch. Processor
|
||||
// forcefully sends available spans when timeout is reached.
|
||||
// The default value of BatchTimeout is 5000 msec.
|
||||
BatchTimeout time.Duration
|
||||
|
||||
// ExportTimeout specifies the maximum duration for exporting spans. If the timeout
|
||||
// is reached, the export will be cancelled.
|
||||
// The default value of ExportTimeout is 30000 msec.
|
||||
ExportTimeout time.Duration
|
||||
|
||||
// MaxExportBatchSize is the maximum number of spans to process in a single batch.
|
||||
// If there are more than one batch worth of spans then it processes multiple batches
|
||||
// of spans one batch after the other without any delay.
|
||||
// The default value of MaxExportBatchSize is 512.
|
||||
MaxExportBatchSize int
|
||||
|
||||
// BlockOnQueueFull blocks onEnd() and onStart() method if the queue is full
|
||||
// AND if BlockOnQueueFull is set to true.
|
||||
// Blocking option should be used carefully as it can severely affect the performance of an
|
||||
// application.
|
||||
BlockOnQueueFull bool
|
||||
}
|
||||
|
||||
// batchSpanProcessor is a SpanProcessor that batches asynchronously-received
|
||||
// SpanSnapshots and sends them to a trace.Exporter when complete.
|
||||
type batchSpanProcessor struct {
|
||||
e SpanExporter
|
||||
o BatchSpanProcessorOptions
|
||||
|
||||
queue chan *SpanSnapshot
|
||||
dropped uint32
|
||||
|
||||
batch []*SpanSnapshot
|
||||
batchMutex sync.Mutex
|
||||
timer *time.Timer
|
||||
stopWait sync.WaitGroup
|
||||
stopOnce sync.Once
|
||||
stopCh chan struct{}
|
||||
}
|
||||
|
||||
var _ SpanProcessor = (*batchSpanProcessor)(nil)
|
||||
|
||||
// NewBatchSpanProcessor creates a new SpanProcessor that will send completed
|
||||
// span batches to the exporter with the supplied options.
|
||||
//
|
||||
// If the exporter is nil, the span processor will preform no action.
|
||||
func NewBatchSpanProcessor(exporter SpanExporter, options ...BatchSpanProcessorOption) SpanProcessor {
|
||||
o := BatchSpanProcessorOptions{
|
||||
BatchTimeout: DefaultBatchTimeout,
|
||||
ExportTimeout: DefaultExportTimeout,
|
||||
MaxQueueSize: DefaultMaxQueueSize,
|
||||
MaxExportBatchSize: DefaultMaxExportBatchSize,
|
||||
}
|
||||
for _, opt := range options {
|
||||
opt(&o)
|
||||
}
|
||||
bsp := &batchSpanProcessor{
|
||||
e: exporter,
|
||||
o: o,
|
||||
batch: make([]*SpanSnapshot, 0, o.MaxExportBatchSize),
|
||||
timer: time.NewTimer(o.BatchTimeout),
|
||||
queue: make(chan *SpanSnapshot, o.MaxQueueSize),
|
||||
stopCh: make(chan struct{}),
|
||||
}
|
||||
|
||||
bsp.stopWait.Add(1)
|
||||
go func() {
|
||||
defer bsp.stopWait.Done()
|
||||
bsp.processQueue()
|
||||
bsp.drainQueue()
|
||||
}()
|
||||
|
||||
return bsp
|
||||
}
|
||||
|
||||
// OnStart method does nothing.
|
||||
func (bsp *batchSpanProcessor) OnStart(parent context.Context, s ReadWriteSpan) {}
|
||||
|
||||
// OnEnd method enqueues a ReadOnlySpan for later processing.
|
||||
func (bsp *batchSpanProcessor) OnEnd(s ReadOnlySpan) {
|
||||
// Do not enqueue spans if we are just going to drop them.
|
||||
if bsp.e == nil {
|
||||
return
|
||||
}
|
||||
bsp.enqueue(s.Snapshot())
|
||||
}
|
||||
|
||||
// Shutdown flushes the queue and waits until all spans are processed.
|
||||
// It only executes once. Subsequent call does nothing.
|
||||
func (bsp *batchSpanProcessor) Shutdown(ctx context.Context) error {
|
||||
var err error
|
||||
bsp.stopOnce.Do(func() {
|
||||
wait := make(chan struct{})
|
||||
go func() {
|
||||
close(bsp.stopCh)
|
||||
bsp.stopWait.Wait()
|
||||
if bsp.e != nil {
|
||||
if err := bsp.e.Shutdown(ctx); err != nil {
|
||||
otel.Handle(err)
|
||||
}
|
||||
}
|
||||
close(wait)
|
||||
}()
|
||||
// Wait until the wait group is done or the context is cancelled
|
||||
select {
|
||||
case <-wait:
|
||||
case <-ctx.Done():
|
||||
err = ctx.Err()
|
||||
}
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
// ForceFlush exports all ended spans that have not yet been exported.
|
||||
func (bsp *batchSpanProcessor) ForceFlush(ctx context.Context) error {
|
||||
var err error
|
||||
if bsp.e != nil {
|
||||
wait := make(chan struct{})
|
||||
go func() {
|
||||
if err := bsp.exportSpans(ctx); err != nil {
|
||||
otel.Handle(err)
|
||||
}
|
||||
close(wait)
|
||||
}()
|
||||
// Wait until the export is finished or the context is cancelled/timed out
|
||||
select {
|
||||
case <-wait:
|
||||
case <-ctx.Done():
|
||||
err = ctx.Err()
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func WithMaxQueueSize(size int) BatchSpanProcessorOption {
|
||||
return func(o *BatchSpanProcessorOptions) {
|
||||
o.MaxQueueSize = size
|
||||
}
|
||||
}
|
||||
|
||||
func WithMaxExportBatchSize(size int) BatchSpanProcessorOption {
|
||||
return func(o *BatchSpanProcessorOptions) {
|
||||
o.MaxExportBatchSize = size
|
||||
}
|
||||
}
|
||||
|
||||
func WithBatchTimeout(delay time.Duration) BatchSpanProcessorOption {
|
||||
return func(o *BatchSpanProcessorOptions) {
|
||||
o.BatchTimeout = delay
|
||||
}
|
||||
}
|
||||
|
||||
func WithExportTimeout(timeout time.Duration) BatchSpanProcessorOption {
|
||||
return func(o *BatchSpanProcessorOptions) {
|
||||
o.ExportTimeout = timeout
|
||||
}
|
||||
}
|
||||
|
||||
func WithBlocking() BatchSpanProcessorOption {
|
||||
return func(o *BatchSpanProcessorOptions) {
|
||||
o.BlockOnQueueFull = true
|
||||
}
|
||||
}
|
||||
|
||||
// exportSpans is a subroutine of processing and draining the queue.
|
||||
func (bsp *batchSpanProcessor) exportSpans(ctx context.Context) error {
|
||||
bsp.timer.Reset(bsp.o.BatchTimeout)
|
||||
|
||||
bsp.batchMutex.Lock()
|
||||
defer bsp.batchMutex.Unlock()
|
||||
|
||||
if bsp.o.ExportTimeout > 0 {
|
||||
var cancel context.CancelFunc
|
||||
ctx, cancel = context.WithTimeout(ctx, bsp.o.ExportTimeout)
|
||||
defer cancel()
|
||||
}
|
||||
|
||||
if len(bsp.batch) > 0 {
|
||||
if err := bsp.e.ExportSpans(ctx, bsp.batch); err != nil {
|
||||
return err
|
||||
}
|
||||
bsp.batch = bsp.batch[:0]
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// processQueue removes spans from the `queue` channel until processor
|
||||
// is shut down. It calls the exporter in batches of up to MaxExportBatchSize
|
||||
// waiting up to BatchTimeout to form a batch.
|
||||
func (bsp *batchSpanProcessor) processQueue() {
|
||||
defer bsp.timer.Stop()
|
||||
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
for {
|
||||
select {
|
||||
case <-bsp.stopCh:
|
||||
return
|
||||
case <-bsp.timer.C:
|
||||
if err := bsp.exportSpans(ctx); err != nil {
|
||||
otel.Handle(err)
|
||||
}
|
||||
case sd := <-bsp.queue:
|
||||
bsp.batchMutex.Lock()
|
||||
bsp.batch = append(bsp.batch, sd)
|
||||
shouldExport := len(bsp.batch) == bsp.o.MaxExportBatchSize
|
||||
bsp.batchMutex.Unlock()
|
||||
if shouldExport {
|
||||
if !bsp.timer.Stop() {
|
||||
<-bsp.timer.C
|
||||
}
|
||||
if err := bsp.exportSpans(ctx); err != nil {
|
||||
otel.Handle(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// drainQueue awaits the any caller that had added to bsp.stopWait
|
||||
// to finish the enqueue, then exports the final batch.
|
||||
func (bsp *batchSpanProcessor) drainQueue() {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
for {
|
||||
select {
|
||||
case sd := <-bsp.queue:
|
||||
if sd == nil {
|
||||
if err := bsp.exportSpans(ctx); err != nil {
|
||||
otel.Handle(err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
bsp.batchMutex.Lock()
|
||||
bsp.batch = append(bsp.batch, sd)
|
||||
shouldExport := len(bsp.batch) == bsp.o.MaxExportBatchSize
|
||||
bsp.batchMutex.Unlock()
|
||||
|
||||
if shouldExport {
|
||||
if err := bsp.exportSpans(ctx); err != nil {
|
||||
otel.Handle(err)
|
||||
}
|
||||
}
|
||||
default:
|
||||
close(bsp.queue)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (bsp *batchSpanProcessor) enqueue(sd *SpanSnapshot) {
|
||||
if !sd.SpanContext.IsSampled() {
|
||||
return
|
||||
}
|
||||
|
||||
// This ensures the bsp.queue<- below does not panic as the
|
||||
// processor shuts down.
|
||||
defer func() {
|
||||
x := recover()
|
||||
switch err := x.(type) {
|
||||
case nil:
|
||||
return
|
||||
case runtime.Error:
|
||||
if err.Error() == "send on closed channel" {
|
||||
return
|
||||
}
|
||||
}
|
||||
panic(x)
|
||||
}()
|
||||
|
||||
select {
|
||||
case <-bsp.stopCh:
|
||||
return
|
||||
default:
|
||||
}
|
||||
|
||||
if bsp.o.BlockOnQueueFull {
|
||||
bsp.queue <- sd
|
||||
return
|
||||
}
|
||||
|
||||
select {
|
||||
case bsp.queue <- sd:
|
||||
default:
|
||||
atomic.AddUint32(&bsp.dropped, 1)
|
||||
}
|
||||
}
|
68
vendor/go.opentelemetry.io/otel/sdk/trace/config.go
generated
vendored
Normal file
68
vendor/go.opentelemetry.io/otel/sdk/trace/config.go
generated
vendored
Normal file
@ -0,0 +1,68 @@
|
||||
// Copyright The OpenTelemetry 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 "go.opentelemetry.io/otel/sdk/trace"
|
||||
|
||||
// SpanLimits represents the limits of a span.
|
||||
type SpanLimits struct {
|
||||
// AttributeCountLimit is the maximum allowed span attribute count.
|
||||
AttributeCountLimit int
|
||||
|
||||
// EventCountLimit is the maximum allowed span event count.
|
||||
EventCountLimit int
|
||||
|
||||
// LinkCountLimit is the maximum allowed span link count.
|
||||
LinkCountLimit int
|
||||
|
||||
// AttributePerEventCountLimit is the maximum allowed attribute per span event count.
|
||||
AttributePerEventCountLimit int
|
||||
|
||||
// AttributePerLinkCountLimit is the maximum allowed attribute per span link count.
|
||||
AttributePerLinkCountLimit int
|
||||
}
|
||||
|
||||
func (sl *SpanLimits) ensureDefault() {
|
||||
if sl.EventCountLimit <= 0 {
|
||||
sl.EventCountLimit = DefaultEventCountLimit
|
||||
}
|
||||
if sl.AttributeCountLimit <= 0 {
|
||||
sl.AttributeCountLimit = DefaultAttributeCountLimit
|
||||
}
|
||||
if sl.LinkCountLimit <= 0 {
|
||||
sl.LinkCountLimit = DefaultLinkCountLimit
|
||||
}
|
||||
if sl.AttributePerEventCountLimit <= 0 {
|
||||
sl.AttributePerEventCountLimit = DefaultAttributePerEventCountLimit
|
||||
}
|
||||
if sl.AttributePerLinkCountLimit <= 0 {
|
||||
sl.AttributePerLinkCountLimit = DefaultAttributePerLinkCountLimit
|
||||
}
|
||||
}
|
||||
|
||||
const (
|
||||
// DefaultAttributeCountLimit is the default maximum allowed span attribute count.
|
||||
DefaultAttributeCountLimit = 128
|
||||
|
||||
// DefaultEventCountLimit is the default maximum allowed span event count.
|
||||
DefaultEventCountLimit = 128
|
||||
|
||||
// DefaultLinkCountLimit is the default maximum allowed span link count.
|
||||
DefaultLinkCountLimit = 128
|
||||
|
||||
// DefaultAttributePerEventCountLimit is the default maximum allowed attribute per span event count.
|
||||
DefaultAttributePerEventCountLimit = 128
|
||||
|
||||
// DefaultAttributePerLinkCountLimit is the default maximum allowed attribute per span link count.
|
||||
DefaultAttributePerLinkCountLimit = 128
|
||||
)
|
25
vendor/go.opentelemetry.io/otel/sdk/trace/doc.go
generated
vendored
Normal file
25
vendor/go.opentelemetry.io/otel/sdk/trace/doc.go
generated
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
// Copyright The OpenTelemetry 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 contains support for OpenTelemetry distributed tracing.
|
||||
|
||||
This package is currently in a pre-GA phase. Backwards incompatible changes
|
||||
may be introduced in subsequent minor version releases as we work to track the
|
||||
evolving OpenTelemetry specification and user feedback.
|
||||
|
||||
The following assumes a basic familiarity with OpenTelemetry concepts.
|
||||
See https://opentelemetry.io.
|
||||
*/
|
||||
package trace // import "go.opentelemetry.io/otel/sdk/trace"
|
38
vendor/go.opentelemetry.io/otel/sdk/trace/evictedqueue.go
generated
vendored
Normal file
38
vendor/go.opentelemetry.io/otel/sdk/trace/evictedqueue.go
generated
vendored
Normal file
@ -0,0 +1,38 @@
|
||||
// Copyright The OpenTelemetry 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 "go.opentelemetry.io/otel/sdk/trace"
|
||||
|
||||
type evictedQueue struct {
|
||||
queue []interface{}
|
||||
capacity int
|
||||
droppedCount int
|
||||
}
|
||||
|
||||
func newEvictedQueue(capacity int) *evictedQueue {
|
||||
eq := &evictedQueue{
|
||||
capacity: capacity,
|
||||
queue: make([]interface{}, 0),
|
||||
}
|
||||
|
||||
return eq
|
||||
}
|
||||
|
||||
func (eq *evictedQueue) add(value interface{}) {
|
||||
if len(eq.queue) == eq.capacity {
|
||||
eq.queue = eq.queue[1:]
|
||||
eq.droppedCount++
|
||||
}
|
||||
eq.queue = append(eq.queue, value)
|
||||
}
|
67
vendor/go.opentelemetry.io/otel/sdk/trace/id_generator.go
generated
vendored
Normal file
67
vendor/go.opentelemetry.io/otel/sdk/trace/id_generator.go
generated
vendored
Normal file
@ -0,0 +1,67 @@
|
||||
// Copyright The OpenTelemetry 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 "go.opentelemetry.io/otel/sdk/trace"
|
||||
|
||||
import (
|
||||
"context"
|
||||
crand "crypto/rand"
|
||||
"encoding/binary"
|
||||
"math/rand"
|
||||
"sync"
|
||||
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
)
|
||||
|
||||
// IDGenerator allows custom generators for TraceID and SpanID.
|
||||
type IDGenerator interface {
|
||||
NewIDs(ctx context.Context) (trace.TraceID, trace.SpanID)
|
||||
NewSpanID(ctx context.Context, traceID trace.TraceID) trace.SpanID
|
||||
}
|
||||
|
||||
type randomIDGenerator struct {
|
||||
sync.Mutex
|
||||
randSource *rand.Rand
|
||||
}
|
||||
|
||||
var _ IDGenerator = &randomIDGenerator{}
|
||||
|
||||
// NewSpanID returns a non-zero span ID from a randomly-chosen sequence.
|
||||
func (gen *randomIDGenerator) NewSpanID(ctx context.Context, traceID trace.TraceID) trace.SpanID {
|
||||
gen.Lock()
|
||||
defer gen.Unlock()
|
||||
sid := trace.SpanID{}
|
||||
gen.randSource.Read(sid[:])
|
||||
return sid
|
||||
}
|
||||
|
||||
// NewIDs returns a non-zero trace ID and a non-zero span ID from a
|
||||
// randomly-chosen sequence.
|
||||
func (gen *randomIDGenerator) NewIDs(ctx context.Context) (trace.TraceID, trace.SpanID) {
|
||||
gen.Lock()
|
||||
defer gen.Unlock()
|
||||
tid := trace.TraceID{}
|
||||
gen.randSource.Read(tid[:])
|
||||
sid := trace.SpanID{}
|
||||
gen.randSource.Read(sid[:])
|
||||
return tid, sid
|
||||
}
|
||||
|
||||
func defaultIDGenerator() IDGenerator {
|
||||
gen := &randomIDGenerator{}
|
||||
var rngSeed int64
|
||||
_ = binary.Read(crand.Reader, binary.LittleEndian, &rngSeed)
|
||||
gen.randSource = rand.New(rand.NewSource(rngSeed))
|
||||
return gen
|
||||
}
|
324
vendor/go.opentelemetry.io/otel/sdk/trace/provider.go
generated
vendored
Normal file
324
vendor/go.opentelemetry.io/otel/sdk/trace/provider.go
generated
vendored
Normal file
@ -0,0 +1,324 @@
|
||||
// Copyright The OpenTelemetry 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 "go.opentelemetry.io/otel/sdk/trace"
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
|
||||
"go.opentelemetry.io/otel"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
|
||||
"go.opentelemetry.io/otel/sdk/instrumentation"
|
||||
"go.opentelemetry.io/otel/sdk/resource"
|
||||
)
|
||||
|
||||
const (
|
||||
defaultTracerName = "go.opentelemetry.io/otel/sdk/tracer"
|
||||
)
|
||||
|
||||
// TODO (MrAlias): unify this API option design:
|
||||
// https://github.com/open-telemetry/opentelemetry-go/issues/536
|
||||
|
||||
// TracerProviderConfig
|
||||
type TracerProviderConfig struct {
|
||||
processors []SpanProcessor
|
||||
|
||||
// sampler is the default sampler used when creating new spans.
|
||||
sampler Sampler
|
||||
|
||||
// idGenerator is used to generate all Span and Trace IDs when needed.
|
||||
idGenerator IDGenerator
|
||||
|
||||
// spanLimits defines the attribute, event, and link limits for spans.
|
||||
spanLimits SpanLimits
|
||||
|
||||
// resource contains attributes representing an entity that produces telemetry.
|
||||
resource *resource.Resource
|
||||
}
|
||||
|
||||
type TracerProviderOption func(*TracerProviderConfig)
|
||||
|
||||
type TracerProvider struct {
|
||||
mu sync.Mutex
|
||||
namedTracer map[instrumentation.Library]*tracer
|
||||
spanProcessors atomic.Value
|
||||
sampler Sampler
|
||||
idGenerator IDGenerator
|
||||
spanLimits SpanLimits
|
||||
resource *resource.Resource
|
||||
}
|
||||
|
||||
var _ trace.TracerProvider = &TracerProvider{}
|
||||
|
||||
// NewTracerProvider returns a new and configured TracerProvider.
|
||||
//
|
||||
// By default the returned TracerProvider is configured with:
|
||||
// - a ParentBased(AlwaysSample) Sampler
|
||||
// - a random number IDGenerator
|
||||
// - the resource.Default() Resource
|
||||
// - the default SpanLimits.
|
||||
//
|
||||
// The passed opts are used to override these default values and configure the
|
||||
// returned TracerProvider appropriately.
|
||||
func NewTracerProvider(opts ...TracerProviderOption) *TracerProvider {
|
||||
o := &TracerProviderConfig{}
|
||||
|
||||
for _, opt := range opts {
|
||||
opt(o)
|
||||
}
|
||||
|
||||
ensureValidTracerProviderConfig(o)
|
||||
|
||||
tp := &TracerProvider{
|
||||
namedTracer: make(map[instrumentation.Library]*tracer),
|
||||
sampler: o.sampler,
|
||||
idGenerator: o.idGenerator,
|
||||
spanLimits: o.spanLimits,
|
||||
resource: o.resource,
|
||||
}
|
||||
|
||||
for _, sp := range o.processors {
|
||||
tp.RegisterSpanProcessor(sp)
|
||||
}
|
||||
|
||||
return tp
|
||||
}
|
||||
|
||||
// Tracer returns a Tracer with the given name and options. If a Tracer for
|
||||
// the given name and options does not exist it is created, otherwise the
|
||||
// existing Tracer is returned.
|
||||
//
|
||||
// If name is empty, DefaultTracerName is used instead.
|
||||
//
|
||||
// This method is safe to be called concurrently.
|
||||
func (p *TracerProvider) Tracer(name string, opts ...trace.TracerOption) trace.Tracer {
|
||||
c := trace.NewTracerConfig(opts...)
|
||||
|
||||
p.mu.Lock()
|
||||
defer p.mu.Unlock()
|
||||
if name == "" {
|
||||
name = defaultTracerName
|
||||
}
|
||||
il := instrumentation.Library{
|
||||
Name: name,
|
||||
Version: c.InstrumentationVersion,
|
||||
}
|
||||
t, ok := p.namedTracer[il]
|
||||
if !ok {
|
||||
t = &tracer{
|
||||
provider: p,
|
||||
instrumentationLibrary: il,
|
||||
}
|
||||
p.namedTracer[il] = t
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
||||
// RegisterSpanProcessor adds the given SpanProcessor to the list of SpanProcessors
|
||||
func (p *TracerProvider) RegisterSpanProcessor(s SpanProcessor) {
|
||||
p.mu.Lock()
|
||||
defer p.mu.Unlock()
|
||||
new := spanProcessorStates{}
|
||||
if old, ok := p.spanProcessors.Load().(spanProcessorStates); ok {
|
||||
new = append(new, old...)
|
||||
}
|
||||
newSpanSync := &spanProcessorState{
|
||||
sp: s,
|
||||
state: &sync.Once{},
|
||||
}
|
||||
new = append(new, newSpanSync)
|
||||
p.spanProcessors.Store(new)
|
||||
}
|
||||
|
||||
// UnregisterSpanProcessor removes the given SpanProcessor from the list of SpanProcessors
|
||||
func (p *TracerProvider) UnregisterSpanProcessor(s SpanProcessor) {
|
||||
p.mu.Lock()
|
||||
defer p.mu.Unlock()
|
||||
spss := spanProcessorStates{}
|
||||
old, ok := p.spanProcessors.Load().(spanProcessorStates)
|
||||
if !ok || len(old) == 0 {
|
||||
return
|
||||
}
|
||||
spss = append(spss, old...)
|
||||
|
||||
// stop the span processor if it is started and remove it from the list
|
||||
var stopOnce *spanProcessorState
|
||||
var idx int
|
||||
for i, sps := range spss {
|
||||
if sps.sp == s {
|
||||
stopOnce = sps
|
||||
idx = i
|
||||
}
|
||||
}
|
||||
if stopOnce != nil {
|
||||
stopOnce.state.Do(func() {
|
||||
if err := s.Shutdown(context.Background()); err != nil {
|
||||
otel.Handle(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
if len(spss) > 1 {
|
||||
copy(spss[idx:], spss[idx+1:])
|
||||
}
|
||||
spss[len(spss)-1] = nil
|
||||
spss = spss[:len(spss)-1]
|
||||
|
||||
p.spanProcessors.Store(spss)
|
||||
}
|
||||
|
||||
// ForceFlush immediately exports all spans that have not yet been exported for
|
||||
// all the registered span processors.
|
||||
func (p *TracerProvider) ForceFlush(ctx context.Context) error {
|
||||
spss, ok := p.spanProcessors.Load().(spanProcessorStates)
|
||||
if !ok {
|
||||
return fmt.Errorf("failed to load span processors")
|
||||
}
|
||||
if len(spss) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, sps := range spss {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
default:
|
||||
}
|
||||
|
||||
if err := sps.sp.ForceFlush(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Shutdown shuts down the span processors in the order they were registered.
|
||||
func (p *TracerProvider) Shutdown(ctx context.Context) error {
|
||||
spss, ok := p.spanProcessors.Load().(spanProcessorStates)
|
||||
if !ok {
|
||||
return fmt.Errorf("failed to load span processors")
|
||||
}
|
||||
if len(spss) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, sps := range spss {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
default:
|
||||
}
|
||||
|
||||
var err error
|
||||
sps.state.Do(func() {
|
||||
err = sps.sp.Shutdown(ctx)
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// WithSyncer registers the exporter with the TracerProvider using a
|
||||
// SimpleSpanProcessor.
|
||||
func WithSyncer(e SpanExporter) TracerProviderOption {
|
||||
return WithSpanProcessor(NewSimpleSpanProcessor(e))
|
||||
}
|
||||
|
||||
// WithBatcher registers the exporter with the TracerProvider using a
|
||||
// BatchSpanProcessor configured with the passed opts.
|
||||
func WithBatcher(e SpanExporter, opts ...BatchSpanProcessorOption) TracerProviderOption {
|
||||
return WithSpanProcessor(NewBatchSpanProcessor(e, opts...))
|
||||
}
|
||||
|
||||
// WithSpanProcessor registers the SpanProcessor with a TracerProvider.
|
||||
func WithSpanProcessor(sp SpanProcessor) TracerProviderOption {
|
||||
return func(opts *TracerProviderConfig) {
|
||||
opts.processors = append(opts.processors, sp)
|
||||
}
|
||||
}
|
||||
|
||||
// WithResource returns a TracerProviderOption that will configure the
|
||||
// Resource r as a TracerProvider's Resource. The configured Resource is
|
||||
// referenced by all the Tracers the TracerProvider creates. It represents the
|
||||
// entity producing telemetry.
|
||||
//
|
||||
// If this option is not used, the TracerProvider will use the
|
||||
// resource.Default() Resource by default.
|
||||
func WithResource(r *resource.Resource) TracerProviderOption {
|
||||
return func(opts *TracerProviderConfig) {
|
||||
opts.resource = resource.Merge(resource.Environment(), r)
|
||||
}
|
||||
}
|
||||
|
||||
// WithIDGenerator returns a TracerProviderOption that will configure the
|
||||
// IDGenerator g as a TracerProvider's IDGenerator. The configured IDGenerator
|
||||
// is used by the Tracers the TracerProvider creates to generate new Span and
|
||||
// Trace IDs.
|
||||
//
|
||||
// If this option is not used, the TracerProvider will use a random number
|
||||
// IDGenerator by default.
|
||||
func WithIDGenerator(g IDGenerator) TracerProviderOption {
|
||||
return func(opts *TracerProviderConfig) {
|
||||
if g != nil {
|
||||
opts.idGenerator = g
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// WithSampler returns a TracerProviderOption that will configure the Sampler
|
||||
// s as a TracerProvider's Sampler. The configured Sampler is used by the
|
||||
// Tracers the TracerProvider creates to make their sampling decisions for the
|
||||
// Spans they create.
|
||||
//
|
||||
// If this option is not used, the TracerProvider will use a
|
||||
// ParentBased(AlwaysSample) Sampler by default.
|
||||
func WithSampler(s Sampler) TracerProviderOption {
|
||||
return func(opts *TracerProviderConfig) {
|
||||
if s != nil {
|
||||
opts.sampler = s
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// WithSpanLimits returns a TracerProviderOption that will configure the
|
||||
// SpanLimits sl as a TracerProvider's SpanLimits. The configured SpanLimits
|
||||
// are used used by the Tracers the TracerProvider and the Spans they create
|
||||
// to limit tracing resources used.
|
||||
//
|
||||
// If this option is not used, the TracerProvider will use the default
|
||||
// SpanLimits.
|
||||
func WithSpanLimits(sl SpanLimits) TracerProviderOption {
|
||||
return func(opts *TracerProviderConfig) {
|
||||
opts.spanLimits = sl
|
||||
}
|
||||
}
|
||||
|
||||
// ensureValidTracerProviderConfig ensures that given TracerProviderConfig is valid.
|
||||
func ensureValidTracerProviderConfig(cfg *TracerProviderConfig) {
|
||||
if cfg.sampler == nil {
|
||||
cfg.sampler = ParentBased(AlwaysSample())
|
||||
}
|
||||
if cfg.idGenerator == nil {
|
||||
cfg.idGenerator = defaultIDGenerator()
|
||||
}
|
||||
cfg.spanLimits.ensureDefault()
|
||||
if cfg.resource == nil {
|
||||
cfg.resource = resource.Default()
|
||||
}
|
||||
}
|
290
vendor/go.opentelemetry.io/otel/sdk/trace/sampling.go
generated
vendored
Normal file
290
vendor/go.opentelemetry.io/otel/sdk/trace/sampling.go
generated
vendored
Normal file
@ -0,0 +1,290 @@
|
||||
// Copyright The OpenTelemetry 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 "go.opentelemetry.io/otel/sdk/trace"
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
)
|
||||
|
||||
// Sampler decides whether a trace should be sampled and exported.
|
||||
type Sampler interface {
|
||||
ShouldSample(parameters SamplingParameters) SamplingResult
|
||||
Description() string
|
||||
}
|
||||
|
||||
// SamplingParameters contains the values passed to a Sampler.
|
||||
type SamplingParameters struct {
|
||||
ParentContext context.Context
|
||||
TraceID trace.TraceID
|
||||
Name string
|
||||
Kind trace.SpanKind
|
||||
Attributes []attribute.KeyValue
|
||||
Links []trace.Link
|
||||
}
|
||||
|
||||
// SamplingDecision indicates whether a span is dropped, recorded and/or sampled.
|
||||
type SamplingDecision uint8
|
||||
|
||||
// Valid sampling decisions
|
||||
const (
|
||||
// Drop will not record the span and all attributes/events will be dropped
|
||||
Drop SamplingDecision = iota
|
||||
|
||||
// Record indicates the span's `IsRecording() == true`, but `Sampled` flag
|
||||
// *must not* be set
|
||||
RecordOnly
|
||||
|
||||
// RecordAndSample has span's `IsRecording() == true` and `Sampled` flag
|
||||
// *must* be set
|
||||
RecordAndSample
|
||||
)
|
||||
|
||||
// SamplingResult conveys a SamplingDecision, set of Attributes and a Tracestate.
|
||||
type SamplingResult struct {
|
||||
Decision SamplingDecision
|
||||
Attributes []attribute.KeyValue
|
||||
Tracestate trace.TraceState
|
||||
}
|
||||
|
||||
type traceIDRatioSampler struct {
|
||||
traceIDUpperBound uint64
|
||||
description string
|
||||
}
|
||||
|
||||
func (ts traceIDRatioSampler) ShouldSample(p SamplingParameters) SamplingResult {
|
||||
psc := trace.SpanContextFromContext(p.ParentContext)
|
||||
x := binary.BigEndian.Uint64(p.TraceID[0:8]) >> 1
|
||||
if x < ts.traceIDUpperBound {
|
||||
return SamplingResult{
|
||||
Decision: RecordAndSample,
|
||||
Tracestate: psc.TraceState(),
|
||||
}
|
||||
}
|
||||
return SamplingResult{
|
||||
Decision: Drop,
|
||||
Tracestate: psc.TraceState(),
|
||||
}
|
||||
}
|
||||
|
||||
func (ts traceIDRatioSampler) Description() string {
|
||||
return ts.description
|
||||
}
|
||||
|
||||
// TraceIDRatioBased samples a given fraction of traces. Fractions >= 1 will
|
||||
// always sample. Fractions < 0 are treated as zero. To respect the
|
||||
// parent trace's `SampledFlag`, the `TraceIDRatioBased` sampler should be used
|
||||
// as a delegate of a `Parent` sampler.
|
||||
//nolint:golint // golint complains about stutter of `trace.TraceIDRatioBased`
|
||||
func TraceIDRatioBased(fraction float64) Sampler {
|
||||
if fraction >= 1 {
|
||||
return AlwaysSample()
|
||||
}
|
||||
|
||||
if fraction <= 0 {
|
||||
fraction = 0
|
||||
}
|
||||
|
||||
return &traceIDRatioSampler{
|
||||
traceIDUpperBound: uint64(fraction * (1 << 63)),
|
||||
description: fmt.Sprintf("TraceIDRatioBased{%g}", fraction),
|
||||
}
|
||||
}
|
||||
|
||||
type alwaysOnSampler struct{}
|
||||
|
||||
func (as alwaysOnSampler) ShouldSample(p SamplingParameters) SamplingResult {
|
||||
return SamplingResult{
|
||||
Decision: RecordAndSample,
|
||||
Tracestate: trace.SpanContextFromContext(p.ParentContext).TraceState(),
|
||||
}
|
||||
}
|
||||
|
||||
func (as alwaysOnSampler) Description() string {
|
||||
return "AlwaysOnSampler"
|
||||
}
|
||||
|
||||
// AlwaysSample returns a Sampler that samples every trace.
|
||||
// Be careful about using this sampler in a production application with
|
||||
// significant traffic: a new trace will be started and exported for every
|
||||
// request.
|
||||
func AlwaysSample() Sampler {
|
||||
return alwaysOnSampler{}
|
||||
}
|
||||
|
||||
type alwaysOffSampler struct{}
|
||||
|
||||
func (as alwaysOffSampler) ShouldSample(p SamplingParameters) SamplingResult {
|
||||
return SamplingResult{
|
||||
Decision: Drop,
|
||||
Tracestate: trace.SpanContextFromContext(p.ParentContext).TraceState(),
|
||||
}
|
||||
}
|
||||
|
||||
func (as alwaysOffSampler) Description() string {
|
||||
return "AlwaysOffSampler"
|
||||
}
|
||||
|
||||
// NeverSample returns a Sampler that samples no traces.
|
||||
func NeverSample() Sampler {
|
||||
return alwaysOffSampler{}
|
||||
}
|
||||
|
||||
// ParentBased returns a composite sampler which behaves differently,
|
||||
// based on the parent of the span. If the span has no parent,
|
||||
// the root(Sampler) is used to make sampling decision. If the span has
|
||||
// a parent, depending on whether the parent is remote and whether it
|
||||
// is sampled, one of the following samplers will apply:
|
||||
// - remoteParentSampled(Sampler) (default: AlwaysOn)
|
||||
// - remoteParentNotSampled(Sampler) (default: AlwaysOff)
|
||||
// - localParentSampled(Sampler) (default: AlwaysOn)
|
||||
// - localParentNotSampled(Sampler) (default: AlwaysOff)
|
||||
func ParentBased(root Sampler, samplers ...ParentBasedSamplerOption) Sampler {
|
||||
return parentBased{
|
||||
root: root,
|
||||
config: configureSamplersForParentBased(samplers),
|
||||
}
|
||||
}
|
||||
|
||||
type parentBased struct {
|
||||
root Sampler
|
||||
config config
|
||||
}
|
||||
|
||||
func configureSamplersForParentBased(samplers []ParentBasedSamplerOption) config {
|
||||
c := config{
|
||||
remoteParentSampled: AlwaysSample(),
|
||||
remoteParentNotSampled: NeverSample(),
|
||||
localParentSampled: AlwaysSample(),
|
||||
localParentNotSampled: NeverSample(),
|
||||
}
|
||||
|
||||
for _, so := range samplers {
|
||||
so.Apply(&c)
|
||||
}
|
||||
|
||||
return c
|
||||
}
|
||||
|
||||
// config is a group of options for parentBased sampler.
|
||||
type config struct {
|
||||
remoteParentSampled, remoteParentNotSampled Sampler
|
||||
localParentSampled, localParentNotSampled Sampler
|
||||
}
|
||||
|
||||
// ParentBasedSamplerOption configures the sampler for a particular sampling case.
|
||||
type ParentBasedSamplerOption interface {
|
||||
Apply(*config)
|
||||
|
||||
// A private method to prevent users implementing the
|
||||
// interface and so future additions to it will not
|
||||
// violate compatibility.
|
||||
private()
|
||||
}
|
||||
|
||||
// WithRemoteParentSampled sets the sampler for the case of sampled remote parent.
|
||||
func WithRemoteParentSampled(s Sampler) ParentBasedSamplerOption {
|
||||
return remoteParentSampledOption{s}
|
||||
}
|
||||
|
||||
type remoteParentSampledOption struct {
|
||||
s Sampler
|
||||
}
|
||||
|
||||
func (o remoteParentSampledOption) Apply(config *config) {
|
||||
config.remoteParentSampled = o.s
|
||||
}
|
||||
|
||||
func (remoteParentSampledOption) private() {}
|
||||
|
||||
// WithRemoteParentNotSampled sets the sampler for the case of remote parent
|
||||
// which is not sampled.
|
||||
func WithRemoteParentNotSampled(s Sampler) ParentBasedSamplerOption {
|
||||
return remoteParentNotSampledOption{s}
|
||||
}
|
||||
|
||||
type remoteParentNotSampledOption struct {
|
||||
s Sampler
|
||||
}
|
||||
|
||||
func (o remoteParentNotSampledOption) Apply(config *config) {
|
||||
config.remoteParentNotSampled = o.s
|
||||
}
|
||||
|
||||
func (remoteParentNotSampledOption) private() {}
|
||||
|
||||
// WithLocalParentSampled sets the sampler for the case of sampled local parent.
|
||||
func WithLocalParentSampled(s Sampler) ParentBasedSamplerOption {
|
||||
return localParentSampledOption{s}
|
||||
}
|
||||
|
||||
type localParentSampledOption struct {
|
||||
s Sampler
|
||||
}
|
||||
|
||||
func (o localParentSampledOption) Apply(config *config) {
|
||||
config.localParentSampled = o.s
|
||||
}
|
||||
|
||||
func (localParentSampledOption) private() {}
|
||||
|
||||
// WithLocalParentNotSampled sets the sampler for the case of local parent
|
||||
// which is not sampled.
|
||||
func WithLocalParentNotSampled(s Sampler) ParentBasedSamplerOption {
|
||||
return localParentNotSampledOption{s}
|
||||
}
|
||||
|
||||
type localParentNotSampledOption struct {
|
||||
s Sampler
|
||||
}
|
||||
|
||||
func (o localParentNotSampledOption) Apply(config *config) {
|
||||
config.localParentNotSampled = o.s
|
||||
}
|
||||
|
||||
func (localParentNotSampledOption) private() {}
|
||||
|
||||
func (pb parentBased) ShouldSample(p SamplingParameters) SamplingResult {
|
||||
psc := trace.SpanContextFromContext(p.ParentContext)
|
||||
if psc.IsValid() {
|
||||
if psc.IsRemote() {
|
||||
if psc.IsSampled() {
|
||||
return pb.config.remoteParentSampled.ShouldSample(p)
|
||||
}
|
||||
return pb.config.remoteParentNotSampled.ShouldSample(p)
|
||||
}
|
||||
|
||||
if psc.IsSampled() {
|
||||
return pb.config.localParentSampled.ShouldSample(p)
|
||||
}
|
||||
return pb.config.localParentNotSampled.ShouldSample(p)
|
||||
}
|
||||
return pb.root.ShouldSample(p)
|
||||
}
|
||||
|
||||
func (pb parentBased) Description() string {
|
||||
return fmt.Sprintf("ParentBased{root:%s,remoteParentSampled:%s,"+
|
||||
"remoteParentNotSampled:%s,localParentSampled:%s,localParentNotSampled:%s}",
|
||||
pb.root.Description(),
|
||||
pb.config.remoteParentSampled.Description(),
|
||||
pb.config.remoteParentNotSampled.Description(),
|
||||
pb.config.localParentSampled.Description(),
|
||||
pb.config.localParentNotSampled.Description(),
|
||||
)
|
||||
}
|
80
vendor/go.opentelemetry.io/otel/sdk/trace/simple_span_processor.go
generated
vendored
Normal file
80
vendor/go.opentelemetry.io/otel/sdk/trace/simple_span_processor.go
generated
vendored
Normal file
@ -0,0 +1,80 @@
|
||||
// Copyright The OpenTelemetry 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 "go.opentelemetry.io/otel/sdk/trace"
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
|
||||
"go.opentelemetry.io/otel"
|
||||
)
|
||||
|
||||
// simpleSpanProcessor is a SpanProcessor that synchronously sends all
|
||||
// completed Spans to a trace.Exporter immediately.
|
||||
type simpleSpanProcessor struct {
|
||||
exporterMu sync.RWMutex
|
||||
exporter SpanExporter
|
||||
stopOnce sync.Once
|
||||
}
|
||||
|
||||
var _ SpanProcessor = (*simpleSpanProcessor)(nil)
|
||||
|
||||
// NewSimpleSpanProcessor returns a new SpanProcessor that will synchronously
|
||||
// send completed spans to the exporter immediately.
|
||||
func NewSimpleSpanProcessor(exporter SpanExporter) SpanProcessor {
|
||||
ssp := &simpleSpanProcessor{
|
||||
exporter: exporter,
|
||||
}
|
||||
return ssp
|
||||
}
|
||||
|
||||
// OnStart does nothing.
|
||||
func (ssp *simpleSpanProcessor) OnStart(context.Context, ReadWriteSpan) {}
|
||||
|
||||
// OnEnd immediately exports a ReadOnlySpan.
|
||||
func (ssp *simpleSpanProcessor) OnEnd(s ReadOnlySpan) {
|
||||
ssp.exporterMu.RLock()
|
||||
defer ssp.exporterMu.RUnlock()
|
||||
|
||||
if ssp.exporter != nil && s.SpanContext().TraceFlags().IsSampled() {
|
||||
ss := s.Snapshot()
|
||||
if err := ssp.exporter.ExportSpans(context.Background(), []*SpanSnapshot{ss}); err != nil {
|
||||
otel.Handle(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Shutdown shuts down the exporter this SimpleSpanProcessor exports to.
|
||||
func (ssp *simpleSpanProcessor) Shutdown(ctx context.Context) error {
|
||||
var err error
|
||||
ssp.stopOnce.Do(func() {
|
||||
ssp.exporterMu.Lock()
|
||||
exporter := ssp.exporter
|
||||
// Set exporter to nil so subsequent calls to OnEnd are ignored
|
||||
// gracefully.
|
||||
ssp.exporter = nil
|
||||
ssp.exporterMu.Unlock()
|
||||
|
||||
// Clear the ssp.exporter prior to shutting it down so if that creates
|
||||
// a span that needs to be exported there is no deadlock.
|
||||
err = exporter.Shutdown(ctx)
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
// ForceFlush does nothing as there is no data to flush.
|
||||
func (ssp *simpleSpanProcessor) ForceFlush(context.Context) error {
|
||||
return nil
|
||||
}
|
617
vendor/go.opentelemetry.io/otel/sdk/trace/span.go
generated
vendored
Normal file
617
vendor/go.opentelemetry.io/otel/sdk/trace/span.go
generated
vendored
Normal file
@ -0,0 +1,617 @@
|
||||
// Copyright The OpenTelemetry 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 "go.opentelemetry.io/otel/sdk/trace"
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/codes"
|
||||
"go.opentelemetry.io/otel/semconv"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
|
||||
"go.opentelemetry.io/otel/sdk/instrumentation"
|
||||
"go.opentelemetry.io/otel/sdk/internal"
|
||||
"go.opentelemetry.io/otel/sdk/resource"
|
||||
)
|
||||
|
||||
// ReadOnlySpan allows reading information from the data structure underlying a
|
||||
// trace.Span. It is used in places where reading information from a span is
|
||||
// necessary but changing the span isn't necessary or allowed.
|
||||
// TODO: Should we make the methods unexported? The purpose of this interface
|
||||
// is controlling access to `span` fields, not having multiple implementations.
|
||||
type ReadOnlySpan interface {
|
||||
Name() string
|
||||
SpanContext() trace.SpanContext
|
||||
Parent() trace.SpanContext
|
||||
SpanKind() trace.SpanKind
|
||||
StartTime() time.Time
|
||||
EndTime() time.Time
|
||||
Attributes() []attribute.KeyValue
|
||||
Links() []trace.Link
|
||||
Events() []trace.Event
|
||||
StatusCode() codes.Code
|
||||
StatusMessage() string
|
||||
Tracer() trace.Tracer
|
||||
IsRecording() bool
|
||||
InstrumentationLibrary() instrumentation.Library
|
||||
Resource() *resource.Resource
|
||||
Snapshot() *SpanSnapshot
|
||||
|
||||
// A private method to prevent users implementing the
|
||||
// interface and so future additions to it will not
|
||||
// violate compatibility.
|
||||
private()
|
||||
}
|
||||
|
||||
// ReadWriteSpan exposes the same methods as trace.Span and in addition allows
|
||||
// reading information from the underlying data structure.
|
||||
// This interface exposes the union of the methods of trace.Span (which is a
|
||||
// "write-only" span) and ReadOnlySpan. New methods for writing or reading span
|
||||
// information should be added under trace.Span or ReadOnlySpan, respectively.
|
||||
type ReadWriteSpan interface {
|
||||
trace.Span
|
||||
ReadOnlySpan
|
||||
}
|
||||
|
||||
// span is an implementation of the OpenTelemetry Span API representing the
|
||||
// individual component of a trace.
|
||||
type span struct {
|
||||
// mu protects the contents of this span.
|
||||
mu sync.Mutex
|
||||
|
||||
// parent holds the parent span of this span as a trace.SpanContext.
|
||||
parent trace.SpanContext
|
||||
|
||||
// spanKind represents the kind of this span as a trace.SpanKind.
|
||||
spanKind trace.SpanKind
|
||||
|
||||
// name is the name of this span.
|
||||
name string
|
||||
|
||||
// startTime is the time at which this span was started.
|
||||
startTime time.Time
|
||||
|
||||
// endTime is the time at which this span was ended. It contains the zero
|
||||
// value of time.Time until the span is ended.
|
||||
endTime time.Time
|
||||
|
||||
// statusCode represents the status of this span as a codes.Code value.
|
||||
statusCode codes.Code
|
||||
|
||||
// statusMessage represents the status of this span as a string.
|
||||
statusMessage string
|
||||
|
||||
// childSpanCount holds the number of child spans created for this span.
|
||||
childSpanCount int
|
||||
|
||||
// resource contains attributes representing an entity that produced this
|
||||
// span.
|
||||
resource *resource.Resource
|
||||
|
||||
// instrumentationLibrary defines the instrumentation library used to
|
||||
// provide instrumentation.
|
||||
instrumentationLibrary instrumentation.Library
|
||||
|
||||
// spanContext holds the SpanContext of this span.
|
||||
spanContext trace.SpanContext
|
||||
|
||||
// attributes are capped at configured limit. When the capacity is reached
|
||||
// an oldest entry is removed to create room for a new entry.
|
||||
attributes *attributesMap
|
||||
|
||||
// messageEvents are stored in FIFO queue capped by configured limit.
|
||||
messageEvents *evictedQueue
|
||||
|
||||
// links are stored in FIFO queue capped by configured limit.
|
||||
links *evictedQueue
|
||||
|
||||
// executionTracerTaskEnd ends the execution tracer span.
|
||||
executionTracerTaskEnd func()
|
||||
|
||||
// tracer is the SDK tracer that created this span.
|
||||
tracer *tracer
|
||||
|
||||
// spanLimits holds the limits to this span.
|
||||
spanLimits SpanLimits
|
||||
}
|
||||
|
||||
var _ trace.Span = &span{}
|
||||
|
||||
// SpanContext returns the SpanContext of this span.
|
||||
func (s *span) SpanContext() trace.SpanContext {
|
||||
if s == nil {
|
||||
return trace.SpanContext{}
|
||||
}
|
||||
return s.spanContext
|
||||
}
|
||||
|
||||
// IsRecording returns if this span is being recorded. If this span has ended
|
||||
// this will return false.
|
||||
func (s *span) IsRecording() bool {
|
||||
if s == nil {
|
||||
return false
|
||||
}
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
|
||||
return !s.startTime.IsZero() && s.endTime.IsZero()
|
||||
}
|
||||
|
||||
// SetStatus sets the status of this span in the form of a code and a
|
||||
// message. This overrides the existing value of this span's status if one
|
||||
// exists. Message will be set only if status is error. If this span is not being
|
||||
// recorded than this method does nothing.
|
||||
func (s *span) SetStatus(code codes.Code, msg string) {
|
||||
if !s.IsRecording() {
|
||||
return
|
||||
}
|
||||
s.mu.Lock()
|
||||
s.statusCode = code
|
||||
if code == codes.Error {
|
||||
s.statusMessage = msg
|
||||
}
|
||||
s.mu.Unlock()
|
||||
}
|
||||
|
||||
// SetAttributes sets attributes of this span.
|
||||
//
|
||||
// If a key from attributes already exists the value associated with that key
|
||||
// will be overwritten with the value contained in attributes.
|
||||
//
|
||||
// If this span is not being recorded than this method does nothing.
|
||||
func (s *span) SetAttributes(attributes ...attribute.KeyValue) {
|
||||
if !s.IsRecording() {
|
||||
return
|
||||
}
|
||||
s.copyToCappedAttributes(attributes...)
|
||||
}
|
||||
|
||||
// End ends the span. This method does nothing if the span is already ended or
|
||||
// is not being recorded.
|
||||
//
|
||||
// The only SpanOption currently supported is WithTimestamp which will set the
|
||||
// end time for a Span's life-cycle.
|
||||
//
|
||||
// If this method is called while panicking an error event is added to the
|
||||
// Span before ending it and the panic is continued.
|
||||
func (s *span) End(options ...trace.SpanOption) {
|
||||
// Do not start by checking if the span is being recorded which requires
|
||||
// acquiring a lock. Make a minimal check that the span is not nil.
|
||||
if s == nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Store the end time as soon as possible to avoid artificially increasing
|
||||
// the span's duration in case some operation below takes a while.
|
||||
et := internal.MonotonicEndTime(s.startTime)
|
||||
|
||||
// Do relative expensive check now that we have an end time and see if we
|
||||
// need to do any more processing.
|
||||
if !s.IsRecording() {
|
||||
return
|
||||
}
|
||||
|
||||
if recovered := recover(); recovered != nil {
|
||||
// Record but don't stop the panic.
|
||||
defer panic(recovered)
|
||||
s.addEvent(
|
||||
semconv.ExceptionEventName,
|
||||
trace.WithAttributes(
|
||||
semconv.ExceptionTypeKey.String(typeStr(recovered)),
|
||||
semconv.ExceptionMessageKey.String(fmt.Sprint(recovered)),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
if s.executionTracerTaskEnd != nil {
|
||||
s.executionTracerTaskEnd()
|
||||
}
|
||||
|
||||
config := trace.NewSpanConfig(options...)
|
||||
|
||||
s.mu.Lock()
|
||||
// Setting endTime to non-zero marks the span as ended and not recording.
|
||||
if config.Timestamp.IsZero() {
|
||||
s.endTime = et
|
||||
} else {
|
||||
s.endTime = config.Timestamp
|
||||
}
|
||||
s.mu.Unlock()
|
||||
|
||||
sps, ok := s.tracer.provider.spanProcessors.Load().(spanProcessorStates)
|
||||
mustExportOrProcess := ok && len(sps) > 0
|
||||
if mustExportOrProcess {
|
||||
for _, sp := range sps {
|
||||
sp.sp.OnEnd(s)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// RecordError will record err as a span event for this span. An additional call to
|
||||
// SetStatus is required if the Status of the Span should be set to Error, this method
|
||||
// does not change the Span status. If this span is not being recorded or err is nil
|
||||
// than this method does nothing.
|
||||
func (s *span) RecordError(err error, opts ...trace.EventOption) {
|
||||
if s == nil || err == nil || !s.IsRecording() {
|
||||
return
|
||||
}
|
||||
|
||||
opts = append(opts, trace.WithAttributes(
|
||||
semconv.ExceptionTypeKey.String(typeStr(err)),
|
||||
semconv.ExceptionMessageKey.String(err.Error()),
|
||||
))
|
||||
s.addEvent(semconv.ExceptionEventName, opts...)
|
||||
}
|
||||
|
||||
func typeStr(i interface{}) string {
|
||||
t := reflect.TypeOf(i)
|
||||
if t.PkgPath() == "" && t.Name() == "" {
|
||||
// Likely a builtin type.
|
||||
return t.String()
|
||||
}
|
||||
return fmt.Sprintf("%s.%s", t.PkgPath(), t.Name())
|
||||
}
|
||||
|
||||
// Tracer returns the Tracer that created this span.
|
||||
func (s *span) Tracer() trace.Tracer {
|
||||
return s.tracer
|
||||
}
|
||||
|
||||
// AddEvent adds an event with the provided name and options. If this span is
|
||||
// not being recorded than this method does nothing.
|
||||
func (s *span) AddEvent(name string, o ...trace.EventOption) {
|
||||
if !s.IsRecording() {
|
||||
return
|
||||
}
|
||||
s.addEvent(name, o...)
|
||||
}
|
||||
|
||||
func (s *span) addEvent(name string, o ...trace.EventOption) {
|
||||
c := trace.NewEventConfig(o...)
|
||||
|
||||
// Discard over limited attributes
|
||||
var discarded int
|
||||
if len(c.Attributes) > s.spanLimits.AttributePerEventCountLimit {
|
||||
discarded = len(c.Attributes) - s.spanLimits.AttributePerEventCountLimit
|
||||
c.Attributes = c.Attributes[:s.spanLimits.AttributePerEventCountLimit]
|
||||
}
|
||||
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
s.messageEvents.add(trace.Event{
|
||||
Name: name,
|
||||
Attributes: c.Attributes,
|
||||
DroppedAttributeCount: discarded,
|
||||
Time: c.Timestamp,
|
||||
})
|
||||
}
|
||||
|
||||
// SetName sets the name of this span. If this span is not being recorded than
|
||||
// this method does nothing.
|
||||
func (s *span) SetName(name string) {
|
||||
if !s.IsRecording() {
|
||||
return
|
||||
}
|
||||
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
s.name = name
|
||||
}
|
||||
|
||||
// Name returns the name of this span.
|
||||
func (s *span) Name() string {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
return s.name
|
||||
}
|
||||
|
||||
// Name returns the SpanContext of this span's parent span.
|
||||
func (s *span) Parent() trace.SpanContext {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
return s.parent
|
||||
}
|
||||
|
||||
// SpanKind returns the SpanKind of this span.
|
||||
func (s *span) SpanKind() trace.SpanKind {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
return s.spanKind
|
||||
}
|
||||
|
||||
// StartTime returns the time this span started.
|
||||
func (s *span) StartTime() time.Time {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
return s.startTime
|
||||
}
|
||||
|
||||
// EndTime returns the time this span ended. For spans that have not yet
|
||||
// ended, the returned value will be the zero value of time.Time.
|
||||
func (s *span) EndTime() time.Time {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
return s.endTime
|
||||
}
|
||||
|
||||
// Attributes returns the attributes of this span.
|
||||
func (s *span) Attributes() []attribute.KeyValue {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
if s.attributes.evictList.Len() == 0 {
|
||||
return []attribute.KeyValue{}
|
||||
}
|
||||
return s.attributes.toKeyValue()
|
||||
}
|
||||
|
||||
// Links returns the links of this span.
|
||||
func (s *span) Links() []trace.Link {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
if len(s.links.queue) == 0 {
|
||||
return []trace.Link{}
|
||||
}
|
||||
return s.interfaceArrayToLinksArray()
|
||||
}
|
||||
|
||||
// Events returns the events of this span.
|
||||
func (s *span) Events() []trace.Event {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
if len(s.messageEvents.queue) == 0 {
|
||||
return []trace.Event{}
|
||||
}
|
||||
return s.interfaceArrayToMessageEventArray()
|
||||
}
|
||||
|
||||
// StatusCode returns the status code of this span.
|
||||
func (s *span) StatusCode() codes.Code {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
return s.statusCode
|
||||
}
|
||||
|
||||
// StatusMessage returns the status message of this span.
|
||||
func (s *span) StatusMessage() string {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
return s.statusMessage
|
||||
}
|
||||
|
||||
// InstrumentationLibrary returns the instrumentation.Library associated with
|
||||
// the Tracer that created this span.
|
||||
func (s *span) InstrumentationLibrary() instrumentation.Library {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
return s.instrumentationLibrary
|
||||
}
|
||||
|
||||
// Resource returns the Resource associated with the Tracer that created this
|
||||
// span.
|
||||
func (s *span) Resource() *resource.Resource {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
return s.resource
|
||||
}
|
||||
|
||||
func (s *span) addLink(link trace.Link) {
|
||||
if !s.IsRecording() {
|
||||
return
|
||||
}
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
|
||||
// Discard over limited attributes
|
||||
if len(link.Attributes) > s.spanLimits.AttributePerLinkCountLimit {
|
||||
link.DroppedAttributeCount = len(link.Attributes) - s.spanLimits.AttributePerLinkCountLimit
|
||||
link.Attributes = link.Attributes[:s.spanLimits.AttributePerLinkCountLimit]
|
||||
}
|
||||
|
||||
s.links.add(link)
|
||||
}
|
||||
|
||||
// Snapshot creates a snapshot representing the current state of the span as an
|
||||
// export.SpanSnapshot and returns a pointer to it.
|
||||
func (s *span) Snapshot() *SpanSnapshot {
|
||||
var sd SpanSnapshot
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
|
||||
sd.ChildSpanCount = s.childSpanCount
|
||||
sd.EndTime = s.endTime
|
||||
sd.InstrumentationLibrary = s.instrumentationLibrary
|
||||
sd.Name = s.name
|
||||
sd.Parent = s.parent
|
||||
sd.Resource = s.resource
|
||||
sd.SpanContext = s.spanContext
|
||||
sd.SpanKind = s.spanKind
|
||||
sd.StartTime = s.startTime
|
||||
sd.StatusCode = s.statusCode
|
||||
sd.StatusMessage = s.statusMessage
|
||||
|
||||
if s.attributes.evictList.Len() > 0 {
|
||||
sd.Attributes = s.attributes.toKeyValue()
|
||||
sd.DroppedAttributeCount = s.attributes.droppedCount
|
||||
}
|
||||
if len(s.messageEvents.queue) > 0 {
|
||||
sd.MessageEvents = s.interfaceArrayToMessageEventArray()
|
||||
sd.DroppedMessageEventCount = s.messageEvents.droppedCount
|
||||
}
|
||||
if len(s.links.queue) > 0 {
|
||||
sd.Links = s.interfaceArrayToLinksArray()
|
||||
sd.DroppedLinkCount = s.links.droppedCount
|
||||
}
|
||||
return &sd
|
||||
}
|
||||
|
||||
func (s *span) interfaceArrayToLinksArray() []trace.Link {
|
||||
linkArr := make([]trace.Link, 0)
|
||||
for _, value := range s.links.queue {
|
||||
linkArr = append(linkArr, value.(trace.Link))
|
||||
}
|
||||
return linkArr
|
||||
}
|
||||
|
||||
func (s *span) interfaceArrayToMessageEventArray() []trace.Event {
|
||||
messageEventArr := make([]trace.Event, 0)
|
||||
for _, value := range s.messageEvents.queue {
|
||||
messageEventArr = append(messageEventArr, value.(trace.Event))
|
||||
}
|
||||
return messageEventArr
|
||||
}
|
||||
|
||||
func (s *span) copyToCappedAttributes(attributes ...attribute.KeyValue) {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
for _, a := range attributes {
|
||||
// Ensure attributes conform to the specification:
|
||||
// https://github.com/open-telemetry/opentelemetry-specification/blob/v1.0.1/specification/common/common.md#attributes
|
||||
if a.Valid() {
|
||||
s.attributes.add(a)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (s *span) addChild() {
|
||||
if !s.IsRecording() {
|
||||
return
|
||||
}
|
||||
s.mu.Lock()
|
||||
s.childSpanCount++
|
||||
s.mu.Unlock()
|
||||
}
|
||||
|
||||
func (*span) private() {}
|
||||
|
||||
func startSpanInternal(ctx context.Context, tr *tracer, name string, o *trace.SpanConfig) *span {
|
||||
span := &span{}
|
||||
|
||||
provider := tr.provider
|
||||
|
||||
// If told explicitly to make this a new root use a zero value SpanContext
|
||||
// as a parent which contains an invalid trace ID and is not remote.
|
||||
var psc trace.SpanContext
|
||||
if !o.NewRoot {
|
||||
psc = trace.SpanContextFromContext(ctx)
|
||||
}
|
||||
|
||||
// If there is a valid parent trace ID, use it to ensure the continuity of
|
||||
// the trace. Always generate a new span ID so other components can rely
|
||||
// on a unique span ID, even if the Span is non-recording.
|
||||
var tid trace.TraceID
|
||||
var sid trace.SpanID
|
||||
if !psc.TraceID().IsValid() {
|
||||
tid, sid = provider.idGenerator.NewIDs(ctx)
|
||||
} else {
|
||||
tid = psc.TraceID()
|
||||
sid = provider.idGenerator.NewSpanID(ctx, tid)
|
||||
}
|
||||
|
||||
spanLimits := provider.spanLimits
|
||||
span.attributes = newAttributesMap(spanLimits.AttributeCountLimit)
|
||||
span.messageEvents = newEvictedQueue(spanLimits.EventCountLimit)
|
||||
span.links = newEvictedQueue(spanLimits.LinkCountLimit)
|
||||
span.spanLimits = spanLimits
|
||||
|
||||
samplingResult := provider.sampler.ShouldSample(SamplingParameters{
|
||||
ParentContext: ctx,
|
||||
TraceID: tid,
|
||||
Name: name,
|
||||
Kind: o.SpanKind,
|
||||
Attributes: o.Attributes,
|
||||
Links: o.Links,
|
||||
})
|
||||
|
||||
scc := trace.SpanContextConfig{
|
||||
TraceID: tid,
|
||||
SpanID: sid,
|
||||
TraceState: samplingResult.Tracestate,
|
||||
}
|
||||
if isSampled(samplingResult) {
|
||||
scc.TraceFlags = psc.TraceFlags() | trace.FlagsSampled
|
||||
} else {
|
||||
scc.TraceFlags = psc.TraceFlags() &^ trace.FlagsSampled
|
||||
}
|
||||
span.spanContext = trace.NewSpanContext(scc)
|
||||
|
||||
if !isRecording(samplingResult) {
|
||||
return span
|
||||
}
|
||||
|
||||
startTime := o.Timestamp
|
||||
if startTime.IsZero() {
|
||||
startTime = time.Now()
|
||||
}
|
||||
span.startTime = startTime
|
||||
|
||||
span.spanKind = trace.ValidateSpanKind(o.SpanKind)
|
||||
span.name = name
|
||||
span.parent = psc
|
||||
span.resource = provider.resource
|
||||
span.instrumentationLibrary = tr.instrumentationLibrary
|
||||
|
||||
span.SetAttributes(samplingResult.Attributes...)
|
||||
|
||||
return span
|
||||
}
|
||||
|
||||
func isRecording(s SamplingResult) bool {
|
||||
return s.Decision == RecordOnly || s.Decision == RecordAndSample
|
||||
}
|
||||
|
||||
func isSampled(s SamplingResult) bool {
|
||||
return s.Decision == RecordAndSample
|
||||
}
|
||||
|
||||
// SpanSnapshot is a snapshot of a span which contains all the information
|
||||
// collected by the span. Its main purpose is exporting completed spans.
|
||||
// Although SpanSnapshot fields can be accessed and potentially modified,
|
||||
// SpanSnapshot should be treated as immutable. Changes to the span from which
|
||||
// the SpanSnapshot was created are NOT reflected in the SpanSnapshot.
|
||||
type SpanSnapshot struct {
|
||||
SpanContext trace.SpanContext
|
||||
Parent trace.SpanContext
|
||||
SpanKind trace.SpanKind
|
||||
Name string
|
||||
StartTime time.Time
|
||||
// The wall clock time of EndTime will be adjusted to always be offset
|
||||
// from StartTime by the duration of the span.
|
||||
EndTime time.Time
|
||||
Attributes []attribute.KeyValue
|
||||
MessageEvents []trace.Event
|
||||
Links []trace.Link
|
||||
StatusCode codes.Code
|
||||
StatusMessage string
|
||||
|
||||
// DroppedAttributeCount contains dropped attributes for the span itself.
|
||||
DroppedAttributeCount int
|
||||
DroppedMessageEventCount int
|
||||
DroppedLinkCount int
|
||||
|
||||
// ChildSpanCount holds the number of child span created for this span.
|
||||
ChildSpanCount int
|
||||
|
||||
// Resource contains attributes representing an entity that produced this span.
|
||||
Resource *resource.Resource
|
||||
|
||||
// InstrumentationLibrary defines the instrumentation library used to
|
||||
// provide instrumentation.
|
||||
InstrumentationLibrary instrumentation.Library
|
||||
}
|
39
vendor/go.opentelemetry.io/otel/sdk/trace/span_exporter.go
generated
vendored
Normal file
39
vendor/go.opentelemetry.io/otel/sdk/trace/span_exporter.go
generated
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
// Copyright The OpenTelemetry 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 "go.opentelemetry.io/otel/sdk/trace"
|
||||
|
||||
import "context"
|
||||
|
||||
// SpanExporter handles the delivery of SpanSnapshot structs to external
|
||||
// receivers. This is the final component in the trace export pipeline.
|
||||
type SpanExporter interface {
|
||||
// ExportSpans exports a batch of SpanSnapshots.
|
||||
//
|
||||
// This function is called synchronously, so there is no concurrency
|
||||
// safety requirement. However, due to the synchronous calling pattern,
|
||||
// it is critical that all timeouts and cancellations contained in the
|
||||
// passed context must be honored.
|
||||
//
|
||||
// Any retry logic must be contained in this function. The SDK that
|
||||
// calls this function will not implement any retry logic. All errors
|
||||
// returned by this function are considered unrecoverable and will be
|
||||
// reported to a configured error Handler.
|
||||
ExportSpans(ctx context.Context, ss []*SpanSnapshot) error
|
||||
// Shutdown notifies the exporter of a pending halt to operations. The
|
||||
// exporter is expected to preform any cleanup or synchronization it
|
||||
// requires while honoring all timeouts and cancellations contained in
|
||||
// the passed context.
|
||||
Shutdown(ctx context.Context) error
|
||||
}
|
56
vendor/go.opentelemetry.io/otel/sdk/trace/span_processor.go
generated
vendored
Normal file
56
vendor/go.opentelemetry.io/otel/sdk/trace/span_processor.go
generated
vendored
Normal file
@ -0,0 +1,56 @@
|
||||
// Copyright The OpenTelemetry 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 "go.opentelemetry.io/otel/sdk/trace"
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// SpanProcessor is a processing pipeline for spans in the trace signal.
|
||||
// SpanProcessors registered with a TracerProvider and are called at the start
|
||||
// and end of a Span's lifecycle, and are called in the order they are
|
||||
// registered.
|
||||
type SpanProcessor interface {
|
||||
// OnStart is called when a span is started. It is called synchronously
|
||||
// and should not block.
|
||||
OnStart(parent context.Context, s ReadWriteSpan)
|
||||
|
||||
// OnEnd is called when span is finished. It is called synchronously and
|
||||
// hence not block.
|
||||
OnEnd(s ReadOnlySpan)
|
||||
|
||||
// Shutdown is called when the SDK shuts down. Any cleanup or release of
|
||||
// resources held by the processor should be done in this call.
|
||||
//
|
||||
// Calls to OnStart, OnEnd, or ForceFlush after this has been called
|
||||
// should be ignored.
|
||||
//
|
||||
// All timeouts and cancellations contained in ctx must be honored, this
|
||||
// should not block indefinitely.
|
||||
Shutdown(ctx context.Context) error
|
||||
|
||||
// ForceFlush exports all ended spans to the configured Exporter that have not yet
|
||||
// been exported. It should only be called when absolutely necessary, such as when
|
||||
// using a FaaS provider that may suspend the process after an invocation, but before
|
||||
// the Processor can export the completed spans.
|
||||
ForceFlush(ctx context.Context) error
|
||||
}
|
||||
|
||||
type spanProcessorState struct {
|
||||
sp SpanProcessor
|
||||
state *sync.Once
|
||||
}
|
||||
type spanProcessorStates []*spanProcessorState
|
75
vendor/go.opentelemetry.io/otel/sdk/trace/tracer.go
generated
vendored
Normal file
75
vendor/go.opentelemetry.io/otel/sdk/trace/tracer.go
generated
vendored
Normal file
@ -0,0 +1,75 @@
|
||||
// Copyright The OpenTelemetry 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 "go.opentelemetry.io/otel/sdk/trace"
|
||||
|
||||
import (
|
||||
"context"
|
||||
rt "runtime/trace"
|
||||
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
|
||||
"go.opentelemetry.io/otel/sdk/instrumentation"
|
||||
)
|
||||
|
||||
type tracer struct {
|
||||
provider *TracerProvider
|
||||
instrumentationLibrary instrumentation.Library
|
||||
}
|
||||
|
||||
var _ trace.Tracer = &tracer{}
|
||||
|
||||
// Start starts a Span and returns it along with a context containing it.
|
||||
//
|
||||
// The Span is created with the provided name and as a child of any existing
|
||||
// span context found in the passed context. The created Span will be
|
||||
// configured appropriately by any SpanOption passed. Any Timestamp option
|
||||
// passed will be used as the start time of the Span's life-cycle.
|
||||
func (tr *tracer) Start(ctx context.Context, name string, options ...trace.SpanOption) (context.Context, trace.Span) {
|
||||
config := trace.NewSpanConfig(options...)
|
||||
|
||||
// For local spans created by this SDK, track child span count.
|
||||
if p := trace.SpanFromContext(ctx); p != nil {
|
||||
if sdkSpan, ok := p.(*span); ok {
|
||||
sdkSpan.addChild()
|
||||
}
|
||||
}
|
||||
|
||||
span := startSpanInternal(ctx, tr, name, config)
|
||||
for _, l := range config.Links {
|
||||
span.addLink(l)
|
||||
}
|
||||
span.SetAttributes(config.Attributes...)
|
||||
|
||||
span.tracer = tr
|
||||
|
||||
if span.IsRecording() {
|
||||
sps, _ := tr.provider.spanProcessors.Load().(spanProcessorStates)
|
||||
for _, sp := range sps {
|
||||
sp.sp.OnStart(ctx, span)
|
||||
}
|
||||
}
|
||||
|
||||
ctx, span.executionTracerTaskEnd = func(ctx context.Context) (context.Context, func()) {
|
||||
if !rt.IsEnabled() {
|
||||
// Avoid additional overhead if
|
||||
// runtime/trace is not enabled.
|
||||
return ctx, func() {}
|
||||
}
|
||||
nctx, task := rt.NewTask(ctx, name)
|
||||
return nctx, task.End
|
||||
}(ctx)
|
||||
|
||||
return trace.ContextWithSpan(ctx, span), span
|
||||
}
|
Reference in New Issue
Block a user