From 725e134680e27f0987a2610c0ea2a096bf3ce6a3 Mon Sep 17 00:00:00 2001 From: mamunto <96148746+mamunto@users.noreply.github.com> Date: Fri, 15 Nov 2024 16:24:26 -0500 Subject: [PATCH] Added max value length per span attribute (#634) --- .../Trace/RecordEventsReadableSpan.swift | 11 ++++++++++- Sources/OpenTelemetrySdk/Trace/SpanLimits.swift | 10 ++++++++++ .../Trace/RecordEventsReadableSpanTests.swift | 15 +++++++++++++++ 3 files changed, 35 insertions(+), 1 deletion(-) diff --git a/Sources/OpenTelemetrySdk/Trace/RecordEventsReadableSpan.swift b/Sources/OpenTelemetrySdk/Trace/RecordEventsReadableSpan.swift index 1d244198..0460d637 100644 --- a/Sources/OpenTelemetrySdk/Trace/RecordEventsReadableSpan.swift +++ b/Sources/OpenTelemetrySdk/Trace/RecordEventsReadableSpan.swift @@ -46,6 +46,8 @@ public class RecordEventsReadableSpan: ReadableSpan { public private(set) var totalRecordedLinks: Int /// Max number of attributes per span. public private(set) var maxNumberOfAttributes: Int + /// Max value length of attribute per span. + public private(set) var maxValueLengthPerSpanAttribute: Int /// Max number of attributes per event. public private(set) var maxNumberOfAttributesPerEvent: Int @@ -140,6 +142,7 @@ public class RecordEventsReadableSpan: ReadableSpan { events = ArrayWithCapacity(capacity: spanLimits.eventCountLimit) maxNumberOfAttributes = spanLimits.attributeCountLimit maxNumberOfAttributesPerEvent = spanLimits.attributePerEventCountLimit + maxValueLengthPerSpanAttribute = spanLimits.attributeValueLengthLimit } /// Creates and starts a span with the given configuration. @@ -253,7 +256,13 @@ public class RecordEventsReadableSpan: ReadableSpan { if attributes[key] == nil, totalAttributeCount > maxNumberOfAttributes { return } - attributes[key] = value + /// Process only `string` type value + if case .string(let value) = value { + let formattedValue = value.count > maxValueLengthPerSpanAttribute ? String(value.prefix(maxValueLengthPerSpanAttribute)) : value + attributes[key] = AttributeValue(formattedValue) + } else { + attributes[key] = value + } } } diff --git a/Sources/OpenTelemetrySdk/Trace/SpanLimits.swift b/Sources/OpenTelemetrySdk/Trace/SpanLimits.swift index 03211bd5..0dd1bd59 100644 --- a/Sources/OpenTelemetrySdk/Trace/SpanLimits.swift +++ b/Sources/OpenTelemetrySdk/Trace/SpanLimits.swift @@ -21,6 +21,9 @@ public struct SpanLimits: Equatable { public private(set) var attributePerEventCountLimit: Int = 128 /// the global default max number of attributes per Link. public private(set) var attributePerLinkCountLimit: Int = 128 + /// the global default attributes value max length + public private(set) var attributeValueLengthLimit: Int = Int.max + /// Returns the defaultSpanLimits. public init() {} @@ -30,6 +33,12 @@ public struct SpanLimits: Equatable { return spanLimits } + @discardableResult public func settingAttributeValueLengthLimit(_ number: UInt) -> Self { + var spanLimits = self + spanLimits.attributeValueLengthLimit = number > 0 ? Int(number) : 0 + return spanLimits + } + @discardableResult public func settingEventCountLimit(_ number: UInt) -> Self { var spanLimits = self spanLimits.eventCountLimit = number > 0 ? Int(number) : 0 @@ -56,6 +65,7 @@ public struct SpanLimits: Equatable { public static func == (lhs: SpanLimits, rhs: SpanLimits) -> Bool { return lhs.attributeCountLimit == rhs.attributeCountLimit && + lhs.attributeValueLengthLimit == rhs.attributeValueLengthLimit && lhs.eventCountLimit == rhs.eventCountLimit && lhs.linkCountLimit == rhs.linkCountLimit && lhs.attributePerEventCountLimit == rhs.attributePerEventCountLimit && diff --git a/Tests/OpenTelemetrySdkTests/Trace/RecordEventsReadableSpanTests.swift b/Tests/OpenTelemetrySdkTests/Trace/RecordEventsReadableSpanTests.swift index bfba0b70..6aab0543 100644 --- a/Tests/OpenTelemetrySdkTests/Trace/RecordEventsReadableSpanTests.swift +++ b/Tests/OpenTelemetrySdkTests/Trace/RecordEventsReadableSpanTests.swift @@ -417,6 +417,21 @@ class RecordEventsReadableSpanTest: XCTestCase { XCTAssertEqual(spanData.totalAttributeCount, 2 * maxNumberOfAttributes) } + func testAttributesValueLength() { + let maxValueLength = 8 + let spanLimits = SpanLimits().settingAttributeValueLengthLimit(UInt(maxValueLength)) + let span = createTestSpan(config: spanLimits) + span.setAttribute(key: "max_value_length", value: .string("this is a big text that is longer than \(maxValueLength) characters")) + span.end() + let spanData = span.toSpanData() + if case .string(let value) = spanData.attributes["max_value_length"] { + XCTAssertEqual(span.maxValueLengthPerSpanAttribute, maxValueLength) + XCTAssertEqual(value, "this is ") + } else { + XCTFail() + } + } + func testDroppingAndAddingAttributes() { let maxNumberOfAttributes = 8 let spanLimits = SpanLimits().settingAttributeCountLimit(UInt(maxNumberOfAttributes))