summaryrefslogtreecommitdiff
path: root/vendor/go.opentelemetry.io/otel/sdk/trace/evictedqueue.go
blob: 821c83faa1dd368d7284c55c18854d5299427a51 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

package trace // import "go.opentelemetry.io/otel/sdk/trace"

import (
	"slices"
	"sync"

	"go.opentelemetry.io/otel/internal/global"
)

// evictedQueue is a FIFO queue with a configurable capacity.
type evictedQueue[T any] struct {
	queue        []T
	capacity     int
	droppedCount int
	logDropped   func()
}

func newEvictedQueueEvent(capacity int) evictedQueue[Event] {
	// Do not pre-allocate queue, do this lazily.
	return evictedQueue[Event]{
		capacity:   capacity,
		logDropped: sync.OnceFunc(func() { global.Warn("limit reached: dropping trace trace.Event") }),
	}
}

func newEvictedQueueLink(capacity int) evictedQueue[Link] {
	// Do not pre-allocate queue, do this lazily.
	return evictedQueue[Link]{
		capacity:   capacity,
		logDropped: sync.OnceFunc(func() { global.Warn("limit reached: dropping trace trace.Link") }),
	}
}

// add adds value to the evictedQueue eq. If eq is at capacity, the oldest
// queued value will be discarded and the drop count incremented.
func (eq *evictedQueue[T]) add(value T) {
	if eq.capacity == 0 {
		eq.droppedCount++
		eq.logDropped()
		return
	}

	if eq.capacity > 0 && len(eq.queue) == eq.capacity {
		// Drop first-in while avoiding allocating more capacity to eq.queue.
		copy(eq.queue[:eq.capacity-1], eq.queue[1:])
		eq.queue = eq.queue[:eq.capacity-1]
		eq.droppedCount++
		eq.logDropped()
	}
	eq.queue = append(eq.queue, value)
}

// copy returns a copy of the evictedQueue.
func (eq *evictedQueue[T]) copy() []T {
	return slices.Clone(eq.queue)
}