| 
									
										
										
										
											2023-05-09 19:19:48 +02:00
										 |  |  | // Copyright The OpenTelemetry Authors | 
					
						
							| 
									
										
										
										
											2024-04-11 11:46:18 +02:00
										 |  |  | // SPDX-License-Identifier: Apache-2.0 | 
					
						
							| 
									
										
										
										
											2023-05-09 19:19:48 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | package trace // import "go.opentelemetry.io/otel/sdk/trace" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-26 18:05:54 +02:00
										 |  |  | import ( | 
					
						
							|  |  |  | 	"slices" | 
					
						
							|  |  |  | 	"sync" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	"go.opentelemetry.io/otel/internal/global" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-09 19:19:48 +02:00
										 |  |  | // evictedQueue is a FIFO queue with a configurable capacity. | 
					
						
							| 
									
										
										
										
											2024-08-26 18:05:54 +02:00
										 |  |  | type evictedQueue[T any] struct { | 
					
						
							|  |  |  | 	queue        []T | 
					
						
							| 
									
										
										
										
											2023-05-09 19:19:48 +02:00
										 |  |  | 	capacity     int | 
					
						
							|  |  |  | 	droppedCount int | 
					
						
							| 
									
										
										
										
											2024-08-26 18:05:54 +02:00
										 |  |  | 	logDropped   func() | 
					
						
							| 
									
										
										
										
											2023-05-09 19:19:48 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-26 18:05:54 +02:00
										 |  |  | func newEvictedQueueEvent(capacity int) evictedQueue[Event] { | 
					
						
							| 
									
										
										
										
											2023-05-09 19:19:48 +02:00
										 |  |  | 	// Do not pre-allocate queue, do this lazily. | 
					
						
							| 
									
										
										
										
											2024-08-26 18:05:54 +02:00
										 |  |  | 	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") }), | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2023-05-09 19:19:48 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // add adds value to the evictedQueue eq. If eq is at capacity, the oldest | 
					
						
							|  |  |  | // queued value will be discarded and the drop count incremented. | 
					
						
							| 
									
										
										
										
											2024-08-26 18:05:54 +02:00
										 |  |  | func (eq *evictedQueue[T]) add(value T) { | 
					
						
							| 
									
										
										
										
											2023-05-09 19:19:48 +02:00
										 |  |  | 	if eq.capacity == 0 { | 
					
						
							|  |  |  | 		eq.droppedCount++ | 
					
						
							| 
									
										
										
										
											2024-08-26 18:05:54 +02:00
										 |  |  | 		eq.logDropped() | 
					
						
							| 
									
										
										
										
											2023-05-09 19:19:48 +02:00
										 |  |  | 		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++ | 
					
						
							| 
									
										
										
										
											2024-08-26 18:05:54 +02:00
										 |  |  | 		eq.logDropped() | 
					
						
							| 
									
										
										
										
											2023-05-09 19:19:48 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	eq.queue = append(eq.queue, value) | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2024-08-26 18:05:54 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | // copy returns a copy of the evictedQueue. | 
					
						
							|  |  |  | func (eq *evictedQueue[T]) copy() []T { | 
					
						
							|  |  |  | 	return slices.Clone(eq.queue) | 
					
						
							|  |  |  | } |