Skip to content

Commit

Permalink
Fixup - only batch analytics events with same sessionID (#1430)
Browse files Browse the repository at this point in the history
* Create separate FPTI POST requests per sessionID

---------

Co-authored-by: Sammy Cannillo <[email protected]>
  • Loading branch information
scannillo and scannillo authored Oct 8, 2024
1 parent 971196d commit ef2a0fe
Show file tree
Hide file tree
Showing 5 changed files with 65 additions and 17 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Braintree iOS SDK Release Notes

## unreleased
* BraintreeCore
* Fix analytics bug where sessionID value in analytics payload was inaccurate; send separate FPTI POST requests per unique sessionID

## 6.23.4 (2024-09-24)
* BraintreePayPal
* Send `isVaultRequest` for App Switch events to PayPal's analytics service (FPTI)
Expand Down
19 changes: 10 additions & 9 deletions Sources/BraintreeCore/Analytics/BTAnalyticsEventsStorage.swift
Original file line number Diff line number Diff line change
@@ -1,27 +1,28 @@
import Foundation

/// Used to store and access our array of events in a thread-safe manner
/// Used to store and access our dictionary of events in a thread-safe manner
actor BTAnalyticsEventsStorage {

private var events: [FPTIBatchData.Event]
// A list of analytic events, keyed by sessionID
private var events: [String: [FPTIBatchData.Event]]

var isEmpty: Bool {
events.isEmpty
}

var allValues: [FPTIBatchData.Event] {
var allValues: [String: [FPTIBatchData.Event]] {
events
}

init() {
self.events = []
self.events = [:]
}

func append(_ event: FPTIBatchData.Event) {
events.append(event)
func append(_ event: FPTIBatchData.Event, sessionID: String) {
events[sessionID] = (events[sessionID] ?? []) + [event]
}

func removeAll() {
events.removeAll()
func removeFor(sessionID: String) {
events.removeValue(forKey: sessionID)
}
}
23 changes: 15 additions & 8 deletions Sources/BraintreeCore/Analytics/BTAnalyticsService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,9 @@ final class BTAnalyticsService: AnalyticsSendable {

/// Exposed to be able to execute this function synchronously in unit tests
func performEventRequest(with event: FPTIBatchData.Event) async {
await events.append(event)
if let apiClient {
await events.append(event, sessionID: apiClient.metadata.sessionID)
}

if shouldBypassTimerQueue {
await self.sendQueuedAnalyticsEvents()
Expand All @@ -74,13 +76,18 @@ final class BTAnalyticsService: AnalyticsSendable {
if await !events.isEmpty, let apiClient {
do {
let configuration = try await apiClient.fetchConfiguration()
let postParameters = await createAnalyticsEvent(
config: configuration,
sessionID: apiClient.metadata.sessionID,
events: events.allValues
)
http?.post("v1/tracking/batch/events", parameters: postParameters) { _, _, _ in }
await events.removeAll()

for (sessionID, eventsPerSessionID) in await events.allValues {
let postParameters = createAnalyticsEvent(
config: configuration,
sessionID: sessionID,
events: eventsPerSessionID
)

_ = try? await http?.post("v1/tracking/batch/events", parameters: postParameters)

await events.removeFor(sessionID: sessionID)
}
} catch {
return
}
Expand Down
17 changes: 17 additions & 0 deletions Sources/BraintreeCore/BTHTTP.swift
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,23 @@ class BTHTTP: NSObject, URLSessionTaskDelegate {
completion(nil, nil, error)
}
}

func post(
_ path: String,
configuration: BTConfiguration? = nil,
parameters: Encodable,
headers: [String: String]? = nil
) async throws -> (BTJSON?, HTTPURLResponse?) {
try await withCheckedThrowingContinuation { continuation in
post(path, configuration: configuration, parameters: parameters, headers: headers) { body, response, error in
if let error {
continuation.resume(throwing: error)
} else {
continuation.resume(returning: (body, response))
}
}
}
}

// MARK: - HTTP Method Helpers

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,25 @@ final class BTAnalyticsService_Tests: XCTestCase {
self.validateMetadataParameters(mockAnalyticsHTTP.lastRequestParameters)
}

func testSendAnalyticsEvent_whenMultipleSessionIDs_sendsMultiplePOSTs() async {
let stubAPIClient: MockAPIClient = stubbedAPIClientWithAnalyticsURL("test://do-not-send.url")
let mockAnalyticsHTTP = FakeHTTP.fakeHTTP()
let sut = BTAnalyticsService.shared
sut.setAPIClient(stubAPIClient)
sut.http = mockAnalyticsHTTP

// Send events associated with 1st sessionID
stubAPIClient.metadata.sessionID = "session-id-1"
await sut.performEventRequest(with: FPTIBatchData.Event(eventName: "event1"))

// Send events associated with 2nd sessionID
stubAPIClient.metadata.sessionID = "session-id-2"
sut.shouldBypassTimerQueue = true
await sut.performEventRequest(with: FPTIBatchData.Event(eventName: "event2"))

XCTAssertEqual(mockAnalyticsHTTP.POSTRequestCount, 2)
}

// MARK: - Helper Functions

func stubbedAPIClientWithAnalyticsURL(_ analyticsURL: String? = nil) -> MockAPIClient {
Expand Down

0 comments on commit ef2a0fe

Please sign in to comment.