From 09f0f9871f22bf899742de08d8e159ac4dc2b6f2 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Tue, 21 Mar 2023 07:22:02 +0900 Subject: [PATCH] Provide explicit set/get to avoid SpanAttributeConvertible wrapping **Motivation:** Provide more control and allow avoiding the existential SpanAtrributeConvertible access when using the subscript. **Modifications:** additional API to avoid the existential **Result:** There is a way to use the API completely avoiding existentials --- Sources/Tracing/SpanProtocol.swift | 10 ++++++++ Tests/TracingTests/SpanTests.swift | 37 ++++++++++++++++++++++++++++-- 2 files changed, 45 insertions(+), 2 deletions(-) diff --git a/Sources/Tracing/SpanProtocol.swift b/Sources/Tracing/SpanProtocol.swift index 7ec5d1e..30eef12 100644 --- a/Sources/Tracing/SpanProtocol.swift +++ b/Sources/Tracing/SpanProtocol.swift @@ -537,6 +537,16 @@ extension SpanAttributes { } } + /// Similar to `subscript(_:)` however returns the stored `SpanAttribute` rather than going through `SpanAttributeConvertible`. + public func get(_ name: String) -> SpanAttribute? { + self._attributes[name] + } + + /// Similar to `subscript(_:)` however accepts a `SpanAttribute` rather than going through `SpanAttributeConvertible`. + public mutating func set(_ name: String, value: SpanAttribute?) { + self._attributes[name] = value + } + /// - Parameter callback: The function to call for each attribute. public func forEach(_ callback: (String, SpanAttribute) -> Void) { self._attributes.forEach { diff --git a/Tests/TracingTests/SpanTests.swift b/Tests/TracingTests/SpanTests.swift index 85d6009..1ddd03b 100644 --- a/Tests/TracingTests/SpanTests.swift +++ b/Tests/TracingTests/SpanTests.swift @@ -181,15 +181,48 @@ final class SpanTests: XCTestCase { XCTAssertEqual(child.links.count, 1) XCTAssertEqual(child.links[0].baggage[TestBaggageContextKey.self], "test") - #if swift(>=5.2) XCTAssertEqual(child.links[0].attributes.sampleHttp.statusCode, 418) - #endif guard case .some(.int64(let statusCode)) = child.links[0].attributes["http.status_code"]?.toSpanAttribute() else { XCTFail("Expected int value for http.status_code") return } XCTAssertEqual(statusCode, 418) } + + func testSpanAttributeSetterGetter() { + var parentBaggage = Baggage.topLevel + parentBaggage[TestBaggageContextKey.self] = "test" + + let parent = TestSpan( + operationName: "client", + startTime: .now(), + baggage: parentBaggage, + kind: .client, + onEnd: { _ in } + ) + let childBaggage = Baggage.topLevel + let child = TestSpan( + operationName: "server", + startTime: .now(), + baggage: childBaggage, + kind: .server, + onEnd: { _ in } + ) + + var attributes = SpanAttributes() + attributes.set("http.status_code", value: .int32(418)) + child.addLink(parent, attributes: attributes) + + XCTAssertEqual(child.links.count, 1) + XCTAssertEqual(child.links[0].baggage[TestBaggageContextKey.self], "test") + XCTAssertEqual(child.links[0].attributes.sampleHttp.statusCode, 418) + guard case .some(.int32(let statusCode)) = child.links[0].attributes["http.status_code"]?.toSpanAttribute() else { + XCTFail("Expected int value for http.status_code") + return + } + XCTAssertEqual(statusCode, 418) + XCTAssertEqual(attributes.get("http.status_code"), SpanAttribute.int32(418)) + } } // ==== ----------------------------------------------------------------------------------------------------------------