From d466a7f758238065db7eeec8db801248d7bc79d1 Mon Sep 17 00:00:00 2001 From: Daniel Jilg Date: Tue, 13 Aug 2024 10:17:58 +0200 Subject: [PATCH 1/2] Update to Ingest API v2 --- Sources/TelemetryClient/Signal.swift | 2 +- Sources/TelemetryClient/SignalEnricher.swift | 6 ------ Sources/TelemetryClient/SignalManager.swift | 4 ++-- 3 files changed, 3 insertions(+), 9 deletions(-) diff --git a/Sources/TelemetryClient/Signal.swift b/Sources/TelemetryClient/Signal.swift index 578e89e..67d89ea 100644 --- a/Sources/TelemetryClient/Signal.swift +++ b/Sources/TelemetryClient/Signal.swift @@ -33,7 +33,7 @@ internal struct SignalPostBody: Codable, Equatable { let floatValue: Double? /// Tags in the form "key:value" to attach to the signal - let payload: [String] + let payload: [String: String] /// If "true", mark the signal as a testing signal and only show it in a dedicated test mode UI let isTestMode: String diff --git a/Sources/TelemetryClient/SignalEnricher.swift b/Sources/TelemetryClient/SignalEnricher.swift index 09bc411..b88f4c3 100644 --- a/Sources/TelemetryClient/SignalEnricher.swift +++ b/Sources/TelemetryClient/SignalEnricher.swift @@ -14,10 +14,4 @@ extension Dictionary where Key == String, Value == String { other } } - - func toMultiValueDimension() -> [String] { - map { key, value in - key.replacingOccurrences(of: ":", with: "_") + ":" + value - } - } } diff --git a/Sources/TelemetryClient/SignalManager.swift b/Sources/TelemetryClient/SignalManager.swift index c61af7d..0e240a8 100644 --- a/Sources/TelemetryClient/SignalManager.swift +++ b/Sources/TelemetryClient/SignalManager.swift @@ -95,7 +95,7 @@ internal final class SignalManager: SignalManageable, @unchecked Sendable { sessionID: configuration.sessionID.uuidString, type: "\(signalName)", floatValue: floatValue, - payload: payload.toMultiValueDimension(), + payload: payload, isTestMode: configuration.testMode ? "true" : "false" ) @@ -184,7 +184,7 @@ private extension SignalManager { private extension SignalManager { private func send(_ signalPostBodies: [SignalPostBody], completionHandler: @escaping @Sendable (Data?, URLResponse?, Error?) -> Void) { DispatchQueue.global(qos: .utility).async { - let path = "/api/v1/apps/\(self.configuration.telemetryAppID)/signals/multiple/" + let path = "/v2/" let url = self.configuration.apiBaseURL.appendingPathComponent(path) var urlRequest = URLRequest(url: url) From cdcabd597ea5d10599e37f431b018d3e41446a97 Mon Sep 17 00:00:00 2001 From: Daniel Jilg Date: Tue, 13 Aug 2024 11:25:34 +0200 Subject: [PATCH 2/2] Update Tests to new Schema --- .../TelemetryClientTests.swift | 47 +++++++++---------- 1 file changed, 23 insertions(+), 24 deletions(-) diff --git a/Tests/TelemetryClientTests/TelemetryClientTests.swift b/Tests/TelemetryClientTests/TelemetryClientTests.swift index 360dfc5..459643a 100644 --- a/Tests/TelemetryClientTests/TelemetryClientTests.swift +++ b/Tests/TelemetryClientTests/TelemetryClientTests.swift @@ -2,7 +2,6 @@ import XCTest final class TelemetryClientTests: XCTestCase { - func testSending() { let YOUR_APP_ID = "44e0f59a-60a2-4d4a-bf27-1f96ccb4aaa3" @@ -17,21 +16,21 @@ final class TelemetryClientTests: XCTestCase { let signalCache = SignalCache(logHandler: nil) let signals: [SignalPostBody] = [ - .init(receivedAt: Date(), appID: UUID(), clientUser: "01", sessionID: "01", type: "test", floatValue: nil, payload: [], isTestMode: "true"), - .init(receivedAt: Date(), appID: UUID(), clientUser: "02", sessionID: "02", type: "test", floatValue: nil, payload: [], isTestMode: "true"), - .init(receivedAt: Date(), appID: UUID(), clientUser: "03", sessionID: "03", type: "test", floatValue: nil, payload: [], isTestMode: "true"), - .init(receivedAt: Date(), appID: UUID(), clientUser: "04", sessionID: "04", type: "test", floatValue: nil, payload: [], isTestMode: "true"), - .init(receivedAt: Date(), appID: UUID(), clientUser: "05", sessionID: "05", type: "test", floatValue: nil, payload: [], isTestMode: "true"), - .init(receivedAt: Date(), appID: UUID(), clientUser: "06", sessionID: "06", type: "test", floatValue: nil, payload: [], isTestMode: "true"), - .init(receivedAt: Date(), appID: UUID(), clientUser: "07", sessionID: "07", type: "test", floatValue: nil, payload: [], isTestMode: "true"), - .init(receivedAt: Date(), appID: UUID(), clientUser: "08", sessionID: "08", type: "test", floatValue: nil, payload: [], isTestMode: "true"), - .init(receivedAt: Date(), appID: UUID(), clientUser: "09", sessionID: "09", type: "test", floatValue: nil, payload: [], isTestMode: "true"), - .init(receivedAt: Date(), appID: UUID(), clientUser: "10", sessionID: "10", type: "test", floatValue: nil, payload: [], isTestMode: "true"), - .init(receivedAt: Date(), appID: UUID(), clientUser: "11", sessionID: "11", type: "test", floatValue: nil, payload: [], isTestMode: "true"), - .init(receivedAt: Date(), appID: UUID(), clientUser: "12", sessionID: "12", type: "test", floatValue: nil, payload: [], isTestMode: "true"), - .init(receivedAt: Date(), appID: UUID(), clientUser: "13", sessionID: "13", type: "test", floatValue: nil, payload: [], isTestMode: "true"), - .init(receivedAt: Date(), appID: UUID(), clientUser: "14", sessionID: "14", type: "test", floatValue: nil, payload: [], isTestMode: "true"), - .init(receivedAt: Date(), appID: UUID(), clientUser: "15", sessionID: "15", type: "test", floatValue: nil, payload: [], isTestMode: "true") + .init(receivedAt: Date(), appID: UUID(), clientUser: "01", sessionID: "01", type: "test", floatValue: nil, payload: [:], isTestMode: "true"), + .init(receivedAt: Date(), appID: UUID(), clientUser: "02", sessionID: "02", type: "test", floatValue: nil, payload: [:], isTestMode: "true"), + .init(receivedAt: Date(), appID: UUID(), clientUser: "03", sessionID: "03", type: "test", floatValue: nil, payload: [:], isTestMode: "true"), + .init(receivedAt: Date(), appID: UUID(), clientUser: "04", sessionID: "04", type: "test", floatValue: nil, payload: [:], isTestMode: "true"), + .init(receivedAt: Date(), appID: UUID(), clientUser: "05", sessionID: "05", type: "test", floatValue: nil, payload: [:], isTestMode: "true"), + .init(receivedAt: Date(), appID: UUID(), clientUser: "06", sessionID: "06", type: "test", floatValue: nil, payload: [:], isTestMode: "true"), + .init(receivedAt: Date(), appID: UUID(), clientUser: "07", sessionID: "07", type: "test", floatValue: nil, payload: [:], isTestMode: "true"), + .init(receivedAt: Date(), appID: UUID(), clientUser: "08", sessionID: "08", type: "test", floatValue: nil, payload: [:], isTestMode: "true"), + .init(receivedAt: Date(), appID: UUID(), clientUser: "09", sessionID: "09", type: "test", floatValue: nil, payload: [:], isTestMode: "true"), + .init(receivedAt: Date(), appID: UUID(), clientUser: "10", sessionID: "10", type: "test", floatValue: nil, payload: [:], isTestMode: "true"), + .init(receivedAt: Date(), appID: UUID(), clientUser: "11", sessionID: "11", type: "test", floatValue: nil, payload: [:], isTestMode: "true"), + .init(receivedAt: Date(), appID: UUID(), clientUser: "12", sessionID: "12", type: "test", floatValue: nil, payload: [:], isTestMode: "true"), + .init(receivedAt: Date(), appID: UUID(), clientUser: "13", sessionID: "13", type: "test", floatValue: nil, payload: [:], isTestMode: "true"), + .init(receivedAt: Date(), appID: UUID(), clientUser: "14", sessionID: "14", type: "test", floatValue: nil, payload: [:], isTestMode: "true"), + .init(receivedAt: Date(), appID: UUID(), clientUser: "15", sessionID: "15", type: "test", floatValue: nil, payload: [:], isTestMode: "true") ] for signal in signals { @@ -56,7 +55,7 @@ final class TelemetryClientTests: XCTestCase { func testSignalEnrichers() throws { struct BasicEnricher: SignalEnricher { - func enrich(signalType: String, for clientUser: String?, floatValue: Double?) -> [String : String] { + func enrich(signalType: String, for clientUser: String?, floatValue: Double?) -> [String: String] { ["isTestEnricher": "true"] } } @@ -71,12 +70,12 @@ final class TelemetryClientTests: XCTestCase { let bodyItems = signalManager.processedSignals XCTAssertEqual(bodyItems.count, 1) let bodyItem = try XCTUnwrap(bodyItems.first) - XCTAssert(bodyItem.payload.contains("isTestEnricher:true")) + XCTAssert(bodyItem.payload["isTestEnricher"] == "true") } func testSignalEnrichers_precedence() throws { struct BasicEnricher: SignalEnricher { - func enrich(signalType: String, for clientUser: String?, floatValue: Double?) -> [String : String] { + func enrich(signalType: String, for clientUser: String?, floatValue: Double?) -> [String: String] { ["item": "A", "isDebug": "banana"] } } @@ -91,8 +90,8 @@ final class TelemetryClientTests: XCTestCase { let bodyItems = signalManager.processedSignals XCTAssertEqual(bodyItems.count, 1) let bodyItem = try XCTUnwrap(bodyItems.first) - XCTAssert(bodyItem.payload.contains("item:B")) // .send takes priority over enricher - XCTAssert(bodyItem.payload.contains("isDebug:banana")) // enricher takes priority over default payload + XCTAssert(bodyItem.payload["item"] == "B") // .send takes priority over enricher + XCTAssert(bodyItem.payload["isDebug"] == "banana") // enricher takes priority over default payload } func testSendsSignals_withAnalyticsImplicitlyEnabled() { @@ -173,11 +172,11 @@ private class FakeSignalManager: SignalManageable { var processedSignals = [SignalPostBody]() @MainActor - func processSignal(_ signalType: String, parameters: [String : String], floatValue: Double?, customUserID: String?, configuration: TelemetryManagerConfiguration) { + func processSignal(_ signalType: String, parameters: [String: String], floatValue: Double?, customUserID: String?, configuration: TelemetryManagerConfiguration) { processedSignalTypes.append(signalType) let enrichedMetadata: [String: String] = configuration.metadataEnrichers .map { $0.enrich(signalType: signalType, for: customUserID, floatValue: floatValue) } - .reduce([String: String](), { $0.applying($1) }) + .reduce([String: String]()) { $0.applying($1) } let payload = DefaultSignalPayload.parameters .applying(enrichedMetadata) @@ -190,7 +189,7 @@ private class FakeSignalManager: SignalManageable { sessionID: configuration.sessionID.uuidString, type: "\(signalType)", floatValue: floatValue, - payload: payload.toMultiValueDimension(), + payload: payload, isTestMode: configuration.testMode ? "true" : "false" ) processedSignals.append(signalPostBody)