diff --git a/Sources/OpenTelemetrySdk/Metrics/Stable/NoopAttributesProcessor.swift b/Sources/OpenTelemetrySdk/Metrics/Stable/NoopAttributesProcessor.swift deleted file mode 100644 index 71fce2d9..00000000 --- a/Sources/OpenTelemetrySdk/Metrics/Stable/NoopAttributesProcessor.swift +++ /dev/null @@ -1,17 +0,0 @@ -// -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 -// - -import Foundation -import OpenTelemetryApi - - -class NoopAttributesProcessor : AttributeProcessorProtocol { - - func process(incoming attributes: [String : OpenTelemetryApi.AttributeValue]) -> [String: OpenTelemetryApi.AttributeValue] { - return attributes - } - - public static let noop = NoopAttributesProcessor() -} diff --git a/Sources/OpenTelemetrySdk/Metrics/Stable/View/AttributeProcessor.swift b/Sources/OpenTelemetrySdk/Metrics/Stable/View/AttributeProcessor.swift index f50166c5..9dfb9b13 100644 --- a/Sources/OpenTelemetrySdk/Metrics/Stable/View/AttributeProcessor.swift +++ b/Sources/OpenTelemetrySdk/Metrics/Stable/View/AttributeProcessor.swift @@ -6,12 +6,12 @@ import Foundation import OpenTelemetryApi -public protocol AttributeProcessorProtocol { +public protocol AttributeProcessor { func process(incoming : [String: AttributeValue]) -> [String: AttributeValue] } -public class AttributeProcessor : AttributeProcessorProtocol { - - public func then(other : AttributeProcessor) -> AttributeProcessor { + +public extension AttributeProcessor { + func then(other : AttributeProcessor) -> AttributeProcessor { if type(of: other) == NoopAttributeProcessor.self { return self } @@ -19,18 +19,29 @@ public class AttributeProcessor : AttributeProcessorProtocol { return other } - if type(of: other) == JoinedAttributeProcessor.self { - return (other as! JoinedAttributeProcessor).prepend(processor:self) + if let joined = self as? JoinedAttributeProcessor { + return joined.append(processor:other) } + if let joined = other as? JoinedAttributeProcessor { + return joined.prepend(processor:self) + } + return JoinedAttributeProcessor([self, other]) } +} + +public class SimpleAttributeProcessor : AttributeProcessor { + let attributeProcessor : ([String: AttributeValue]) -> [String:AttributeValue] + init(attributeProcessor : @escaping ([String: AttributeValue]) -> [String: AttributeValue]) { + self.attributeProcessor = attributeProcessor + } public func process(incoming: [String : AttributeValue]) -> [String : AttributeValue] { - return incoming + return attributeProcessor(incoming) } - public static func filterByKeyName( nameFilter : @escaping (String) -> Bool) -> AttributeProcessor { + static func filterByKeyName( nameFilter : @escaping (String) -> Bool) -> AttributeProcessor { return SimpleAttributeProcessor { attributes in attributes.filter { key, value in nameFilter(key) @@ -38,37 +49,19 @@ public class AttributeProcessor : AttributeProcessorProtocol { } } - public static func append(attributes: [String : AttributeValue]) -> AttributeProcessor { + static func append(attributes: [String : AttributeValue]) -> AttributeProcessor { SimpleAttributeProcessor { incoming in incoming.merging(attributes) { a, b in b } } } - - -} - -internal class SimpleAttributeProcessor : AttributeProcessor { - - let attributeProcessor : ([String: AttributeValue]) -> [String:AttributeValue] - - init(attributeProcessor : @escaping ([String: AttributeValue]) -> [String: AttributeValue]) { - self.attributeProcessor = attributeProcessor - - } - - override func process(incoming: [String : OpenTelemetryApi.AttributeValue]) -> [String : OpenTelemetryApi.AttributeValue] { - return attributeProcessor(incoming) - } - - } public class JoinedAttributeProcessor : AttributeProcessor { - override public func process(incoming: [String : OpenTelemetryApi.AttributeValue]) -> [String : OpenTelemetryApi.AttributeValue] { + public func process(incoming: [String : AttributeValue]) -> [String : AttributeValue] { var result = incoming for processor in processors { result = processor.process(incoming: result) @@ -76,17 +69,17 @@ public class JoinedAttributeProcessor : AttributeProcessor { return result } - override public func then(other: AttributeProcessor) -> AttributeProcessor { + public func append(processor: AttributeProcessor) -> JoinedAttributeProcessor { var newList = processors - if let otherJoined = other as? JoinedAttributeProcessor { - newList.append(contentsOf: otherJoined.processors) + if let joinedProcessor = processor as? JoinedAttributeProcessor { + newList.append(contentsOf: joinedProcessor.processors) } else { - newList.append(other) + newList.append(processor) } return JoinedAttributeProcessor(newList) } - public func prepend(processor: AttributeProcessor) -> AttributeProcessor { + public func prepend(processor: AttributeProcessor) -> JoinedAttributeProcessor { var newProcessors = [processor] newProcessors.append(contentsOf: processors) return JoinedAttributeProcessor(newProcessors) @@ -101,8 +94,8 @@ public class JoinedAttributeProcessor : AttributeProcessor { public class NoopAttributeProcessor : AttributeProcessor { static let noop = NoopAttributeProcessor() - private override init() {} - override public func process(incoming: [String : AttributeValue]) -> [String : AttributeValue] { + private init() {} + public func process(incoming: [String : AttributeValue]) -> [String : AttributeValue] { return incoming } } diff --git a/Sources/OpenTelemetrySdk/Metrics/Stable/View/ViewBuilder.swift b/Sources/OpenTelemetrySdk/Metrics/Stable/View/ViewBuilder.swift index 14098d3f..46dc459c 100644 --- a/Sources/OpenTelemetrySdk/Metrics/Stable/View/ViewBuilder.swift +++ b/Sources/OpenTelemetrySdk/Metrics/Stable/View/ViewBuilder.swift @@ -30,8 +30,13 @@ public class ViewBuilder { return self } + public func withAttributeProcessor(processor: AttributeProcessor) -> Self { + self.processor = processor + return self + } + public func addAttributeFilter(keyFilter: @escaping (String) -> Bool) -> Self { - addAttributeProcessor(processor: AttributeProcessor.filterByKeyName(nameFilter: keyFilter)) + addAttributeProcessor(processor: SimpleAttributeProcessor.filterByKeyName(nameFilter: keyFilter)) } public func addAttributeProcessor(processor: AttributeProcessor) -> Self { diff --git a/Tests/OpenTelemetrySdkTests/Metrics/StableMetrics/AttributeProcessorTests.swift b/Tests/OpenTelemetrySdkTests/Metrics/StableMetrics/AttributeProcessorTests.swift new file mode 100644 index 00000000..a1fbaa4e --- /dev/null +++ b/Tests/OpenTelemetrySdkTests/Metrics/StableMetrics/AttributeProcessorTests.swift @@ -0,0 +1,44 @@ +// +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 +// + +import Foundation + +import OpenTelemetryApi +@testable import OpenTelemetrySdk +import XCTest + +class AttributeProcessorTests : XCTestCase { + func testStaticNoop() { + XCTAssertNotNil(NoopAttributeProcessor.noop) + XCTAssertEqual(NoopAttributeProcessor.noop.process(incoming: ["hello": AttributeValue.string("world")]), ["hello" : AttributeValue.string("world")]) + } + + func testSimpleProcessor() { + let incoming = ["hello": AttributeValue("world")] + + var processor: AttributeProcessor = SimpleAttributeProcessor.append(attributes: ["foo" : .string("bar")]) + XCTAssertEqual(processor.process(incoming: incoming), ["hello" : .string("world"), "foo": .string("bar")]) + + processor = processor.then(other: SimpleAttributeProcessor.filterByKeyName(nameFilter: { $0 == "foo" })) + XCTAssertEqual(processor.process(incoming: incoming), ["foo": .string("bar")]) + } + + func testJoinedProcessor() { + let incoming = ["hello": AttributeValue("world")] + + let processor0 = SimpleAttributeProcessor.append(attributes: ["foo" : .string("bar0")]) + let processor1 = SimpleAttributeProcessor.append(attributes: ["foo" : .string("bar1")]) + let processor2 = SimpleAttributeProcessor.append(attributes: ["foo" : .string("bar2")]) + + var processor = JoinedAttributeProcessor([processor0]) + XCTAssertEqual(processor.process(incoming: incoming), ["hello" : .string("world"), "foo": .string("bar0")]) + + processor = processor.prepend(processor: processor1) + XCTAssertEqual(processor.process(incoming: incoming), ["hello" : .string("world"), "foo": .string("bar0")]) + + processor = processor.append(processor: processor2) + XCTAssertEqual(processor.process(incoming: incoming), ["hello" : .string("world"), "foo": .string("bar2")]) + } +} diff --git a/Tests/OpenTelemetrySdkTests/Metrics/StableMetrics/NoopAttributesProcessorTests.swift b/Tests/OpenTelemetrySdkTests/Metrics/StableMetrics/NoopAttributesProcessorTests.swift deleted file mode 100644 index 433ae3c4..00000000 --- a/Tests/OpenTelemetrySdkTests/Metrics/StableMetrics/NoopAttributesProcessorTests.swift +++ /dev/null @@ -1,17 +0,0 @@ -// -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 -// - -import Foundation - -import OpenTelemetryApi -@testable import OpenTelemetrySdk -import XCTest - -class NoopAttributesProcessorTests : XCTestCase { - func testStaticNoop() { - XCTAssertNotNil(NoopAttributeProcessor.noop) - XCTAssertEqual(NoopAttributeProcessor.noop.process(incoming: ["hello": AttributeValue.string("world")]), ["hello" : AttributeValue.string("world")]) - } -}