Repository: open-telemetry/opentelemetry-swift (swift)

Issue:
Events are not limited in the correct order
The spec states:

> SDK Spans MAY also discard links and events that would increase the number of elements of each collection beyond the configured limit.

While links are correctly limited at the `SpanBuilder` level (`addLink`), `addEvent` (which is implemented in `RecordEventsReadableSpan`) relies on the events property, which is implemented as an `ArrayWithCapacity`. When adding a new event, the SDK uses the append method and works as shown below:

```swift
public struct ArrayWithCapacity<T> {
  private(set) var array = [T]()
  public let capacity: Int

  public init(capacity: Int) {
    self.capacity = capacity
  }

  public mutating func append(_ item: T) {
    array.append(item)
    if array.count > capacity {
      _ = array.removeFirst()
    }
  }
```

This implementation removes the oldest items (i.e., the first ones added), rather than preventing the addition of new items that would exceed the collection’s limit — which is not consistent with the intent of the spec.

Pull request:
# Overview
Now, as long as an event exceeds the established limits, it will simply be dropped (the first inserted event will no longer be removed, as it used to be).

Fixes #771

Patch:
diff --git a/Sources/OpenTelemetrySdk/Trace/ArrayWithCapacity.swift b/Sources/OpenTelemetrySdk/Trace/ArrayWithCapacity.swift
index 659042fb7..999c08449 100644
--- a/Sources/OpenTelemetrySdk/Trace/ArrayWithCapacity.swift
+++ b/Sources/OpenTelemetrySdk/Trace/ArrayWithCapacity.swift
@@ -16,9 +16,8 @@ public struct ArrayWithCapacity<T> {
   }
 
   public mutating func append(_ item: T) {
-    array.append(item)
-    if array.count > capacity {
-      _ = array.removeFirst()
+    if array.count != capacity {
+      array.append(item)
     }
   }
 }


Test patch:
diff --git a/Tests/OpenTelemetrySdkTests/Trace/RecordEventsReadableSpanTests.swift b/Tests/OpenTelemetrySdkTests/Trace/RecordEventsReadableSpanTests.swift
index 2996936ee..597a4ef66 100644
--- a/Tests/OpenTelemetrySdkTests/Trace/RecordEventsReadableSpanTests.swift
+++ b/Tests/OpenTelemetrySdkTests/Trace/RecordEventsReadableSpanTests.swift
@@ -459,26 +459,39 @@ class RecordEventsReadableSpanTest: XCTestCase {
     span.end()
   }
 
-  func testDroppingEvents() {
+  func testAddingEventsAboveLimitShouldntBeAllowed() {
     let maxNumberOfEvents = 8
     let spanLimits = SpanLimits().settingEventCountLimit(UInt(maxNumberOfEvents))
     let span = createTestSpan(config: spanLimits)
+
     for _ in 0 ..< 2 * maxNumberOfEvents {
       span.addEvent(name: "event2", attributes: [String: AttributeValue]())
       testClock.advanceMillis(millisPerSecond)
     }
+
     var spanData = span.toSpanData()
-    XCTAssertEqual(spanData.events.count, maxNumberOfEvents) //
+
+    XCTAssertEqual(spanData.events.count, maxNumberOfEvents)
     for i in 0 ..< maxNumberOfEvents {
-      let expectedEvent = SpanData.Event(name: "event2", timestamp: startTime.addingTimeInterval(TimeInterval(maxNumberOfEvents + i)), attributes: [String: AttributeValue]())
+      let expectedEvent = SpanData.Event(
+        name: "event2",
+        timestamp: startTime.addingTimeInterval(TimeInterval(i)),
+        attributes: [String: AttributeValue]()
+      )
       XCTAssertEqual(spanData.events[i], expectedEvent)
       XCTAssertEqual(spanData.totalRecordedEvents, 2 * maxNumberOfEvents)
     }
+
     span.end()
     spanData = span.toSpanData()
+
     XCTAssertEqual(spanData.events.count, maxNumberOfEvents)
     for i in 0 ..< maxNumberOfEvents {
-      let expectedEvent = SpanData.Event(name: "event2", timestamp: startTime.addingTimeInterval(TimeInterval(maxNumberOfEvents + i)), attributes: [String: AttributeValue]())
+      let expectedEvent = SpanData.Event(
+        name: "event2",
+        timestamp: startTime.addingTimeInterval(TimeInterval(i)),
+        attributes: [String: AttributeValue]()
+      )
       XCTAssertEqual(spanData.events[i], expectedEvent)
     }
   }