blob: 8c308dd60a93ada2d2a69f5279174f7fca522bd6 [file] [log] [blame]
Abhay Kumara2ae5992025-11-10 14:02:24 +00001// Copyright The OpenTelemetry Authors
2// SPDX-License-Identifier: Apache-2.0
3
4package trace // import "go.opentelemetry.io/otel/sdk/trace"
5
6import (
7 "slices"
8 "sync"
9
10 "go.opentelemetry.io/otel/internal/global"
11)
12
13// evictedQueue is a FIFO queue with a configurable capacity.
14type evictedQueue[T any] struct {
15 queue []T
16 capacity int
17 droppedCount int
18 logDroppedMsg string
19 logDroppedOnce sync.Once
20}
21
22func newEvictedQueueEvent(capacity int) evictedQueue[Event] {
23 // Do not pre-allocate queue, do this lazily.
24 return evictedQueue[Event]{
25 capacity: capacity,
26 logDroppedMsg: "limit reached: dropping trace trace.Event",
27 }
28}
29
30func newEvictedQueueLink(capacity int) evictedQueue[Link] {
31 // Do not pre-allocate queue, do this lazily.
32 return evictedQueue[Link]{
33 capacity: capacity,
34 logDroppedMsg: "limit reached: dropping trace trace.Link",
35 }
36}
37
38// add adds value to the evictedQueue eq. If eq is at capacity, the oldest
39// queued value will be discarded and the drop count incremented.
40func (eq *evictedQueue[T]) add(value T) {
41 if eq.capacity == 0 {
42 eq.droppedCount++
43 eq.logDropped()
44 return
45 }
46
47 if eq.capacity > 0 && len(eq.queue) == eq.capacity {
48 // Drop first-in while avoiding allocating more capacity to eq.queue.
49 copy(eq.queue[:eq.capacity-1], eq.queue[1:])
50 eq.queue = eq.queue[:eq.capacity-1]
51 eq.droppedCount++
52 eq.logDropped()
53 }
54 eq.queue = append(eq.queue, value)
55}
56
57func (eq *evictedQueue[T]) logDropped() {
58 eq.logDroppedOnce.Do(func() { global.Warn(eq.logDroppedMsg) })
59}
60
61// copy returns a copy of the evictedQueue.
62func (eq *evictedQueue[T]) copy() []T {
63 return slices.Clone(eq.queue)
64}