From 176abd5841eb331b90c8c6472dabe66e9ef9f125 Mon Sep 17 00:00:00 2001 From: Valere Date: Mon, 6 May 2024 17:07:05 +0200 Subject: [PATCH] Bump posthog SDK version to 3.2.0 (#2788) Co-authored-by: Mauro <34335419+Velin92@users.noreply.github.com> --- ElementX.xcodeproj/project.pbxproj | 2 +- .../xcshareddata/swiftpm/Package.resolved | 4 +- .../Mocks/Generated/GeneratedMocks.swift | 57 +++++++++---------- ElementX/Sources/Mocks/PHGPostHogMock.swift | 7 +-- .../Analytics/PHGPostHogConfiguration.swift | 9 +-- .../Analytics/PHGPostHogProtocol.swift | 15 +++-- .../Analytics/PostHogAnalyticsClient.swift | 20 ++++--- UnitTests/Sources/AnalyticsTests.swift | 34 +++++++++++ changelog.d/2788.misc | 1 + project.yml | 2 +- 10 files changed, 91 insertions(+), 60 deletions(-) create mode 100644 changelog.d/2788.misc diff --git a/ElementX.xcodeproj/project.pbxproj b/ElementX.xcodeproj/project.pbxproj index 652062df5..6ac507e5f 100644 --- a/ElementX.xcodeproj/project.pbxproj +++ b/ElementX.xcodeproj/project.pbxproj @@ -7352,7 +7352,7 @@ repositoryURL = "https://github.com/PostHog/posthog-ios"; requirement = { kind = upToNextMinorVersion; - minimumVersion = 2.0.3; + minimumVersion = 3.2.4; }; }; 9A472EE0218FE7DCF5283429 /* XCRemoteSwiftPackageReference "SwiftUI-Introspect" */ = { diff --git a/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 6a230d25b..b16fd01f1 100644 --- a/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -166,8 +166,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/PostHog/posthog-ios", "state" : { - "revision" : "9298825fe26899a58b976d400254e0b050daa578", - "version" : "2.0.5" + "revision" : "d127599034e08f12f340e5e2da13090a894d55d6", + "version" : "3.2.4" } }, { diff --git a/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift b/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift index ed4395194..31137a4fb 100644 --- a/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift +++ b/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift @@ -6625,23 +6625,18 @@ class OrientationManagerMock: OrientationManagerProtocol { } } class PHGPostHogMock: PHGPostHogProtocol { - var enabled: Bool { - get { return underlyingEnabled } - set(value) { underlyingEnabled = value } - } - var underlyingEnabled: Bool! - //MARK: - enable + //MARK: - optIn - var enableUnderlyingCallsCount = 0 - var enableCallsCount: Int { + var optInUnderlyingCallsCount = 0 + var optInCallsCount: Int { get { if Thread.isMainThread { - return enableUnderlyingCallsCount + return optInUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = enableUnderlyingCallsCount + returnValue = optInUnderlyingCallsCount } return returnValue! @@ -6649,34 +6644,34 @@ class PHGPostHogMock: PHGPostHogProtocol { } set { if Thread.isMainThread { - enableUnderlyingCallsCount = newValue + optInUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - enableUnderlyingCallsCount = newValue + optInUnderlyingCallsCount = newValue } } } } - var enableCalled: Bool { - return enableCallsCount > 0 + var optInCalled: Bool { + return optInCallsCount > 0 } - var enableClosure: (() -> Void)? + var optInClosure: (() -> Void)? - func enable() { - enableCallsCount += 1 - enableClosure?() + func optIn() { + optInCallsCount += 1 + optInClosure?() } - //MARK: - disable + //MARK: - optOut - var disableUnderlyingCallsCount = 0 - var disableCallsCount: Int { + var optOutUnderlyingCallsCount = 0 + var optOutCallsCount: Int { get { if Thread.isMainThread { - return disableUnderlyingCallsCount + return optOutUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = disableUnderlyingCallsCount + returnValue = optOutUnderlyingCallsCount } return returnValue! @@ -6684,22 +6679,22 @@ class PHGPostHogMock: PHGPostHogProtocol { } set { if Thread.isMainThread { - disableUnderlyingCallsCount = newValue + optOutUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - disableUnderlyingCallsCount = newValue + optOutUnderlyingCallsCount = newValue } } } } - var disableCalled: Bool { - return disableCallsCount > 0 + var optOutCalled: Bool { + return optOutCallsCount > 0 } - var disableClosure: (() -> Void)? + var optOutClosure: (() -> Void)? - func disable() { - disableCallsCount += 1 - disableClosure?() + func optOut() { + optOutCallsCount += 1 + optOutClosure?() } //MARK: - reset diff --git a/ElementX/Sources/Mocks/PHGPostHogMock.swift b/ElementX/Sources/Mocks/PHGPostHogMock.swift index 4a637c480..30e6ab07e 100644 --- a/ElementX/Sources/Mocks/PHGPostHogMock.swift +++ b/ElementX/Sources/Mocks/PHGPostHogMock.swift @@ -19,9 +19,8 @@ import PostHog extension PHGPostHogMock { func configureMockBehavior() { - enableClosure = { - self.enabled = true - } + // We don't need custom configuration anymore since update of the posthog SDK + // Keeping boilerplate code in case needed later? } } @@ -32,7 +31,7 @@ class MockPostHogFactory: PostHogFactory { self.mock = mock } - func createPostHog(config: PHGPostHogConfiguration) -> ElementX.PHGPostHogProtocol { + func createPostHog(config: PostHogConfig) -> ElementX.PHGPostHogProtocol { mock } } diff --git a/ElementX/Sources/Services/Analytics/PHGPostHogConfiguration.swift b/ElementX/Sources/Services/Analytics/PHGPostHogConfiguration.swift index 76d1d1449..64db62400 100644 --- a/ElementX/Sources/Services/Analytics/PHGPostHogConfiguration.swift +++ b/ElementX/Sources/Services/Analytics/PHGPostHogConfiguration.swift @@ -16,12 +16,13 @@ import PostHog -extension PHGPostHogConfiguration { - static func standard(analyticsConfiguration: AnalyticsConfiguration) -> PHGPostHogConfiguration? { +extension PostHogConfig { + static func standard(analyticsConfiguration: AnalyticsConfiguration) -> PostHogConfig? { guard analyticsConfiguration.isEnabled else { return nil } - let postHogConfiguration = PHGPostHogConfiguration(apiKey: analyticsConfiguration.apiKey, host: analyticsConfiguration.host) - postHogConfiguration.shouldSendDeviceID = false + let postHogConfiguration = PostHogConfig(apiKey: analyticsConfiguration.apiKey, host: analyticsConfiguration.host) + // We capture screens manually + postHogConfiguration.captureScreenViews = false return postHogConfiguration } diff --git a/ElementX/Sources/Services/Analytics/PHGPostHogProtocol.swift b/ElementX/Sources/Services/Analytics/PHGPostHogProtocol.swift index a567dd79d..5e4d77316 100644 --- a/ElementX/Sources/Services/Analytics/PHGPostHogProtocol.swift +++ b/ElementX/Sources/Services/Analytics/PHGPostHogProtocol.swift @@ -19,11 +19,9 @@ import PostHog // sourcery: AutoMockable protocol PHGPostHogProtocol { - var enabled: Bool { get } + func optIn() - func enable() - - func disable() + func optOut() func reset() @@ -33,13 +31,14 @@ protocol PHGPostHogProtocol { } protocol PostHogFactory { - func createPostHog(config: PHGPostHogConfiguration) -> PHGPostHogProtocol + func createPostHog(config: PostHogConfig) -> PHGPostHogProtocol } class DefaultPostHogFactory: PostHogFactory { - func createPostHog(config: PHGPostHogConfiguration) -> PHGPostHogProtocol { - PHGPostHog(configuration: config) + func createPostHog(config: PostHogConfig) -> PHGPostHogProtocol { + PostHogSDK.shared.setup(config) + return PostHogSDK.shared } } -extension PHGPostHog: PHGPostHogProtocol { } +extension PostHogSDK: PHGPostHogProtocol { } diff --git a/ElementX/Sources/Services/Analytics/PostHogAnalyticsClient.swift b/ElementX/Sources/Services/Analytics/PostHogAnalyticsClient.swift index 941cdc51c..0fa3a0b1e 100644 --- a/ElementX/Sources/Services/Analytics/PostHogAnalyticsClient.swift +++ b/ElementX/Sources/Services/Analytics/PostHogAnalyticsClient.swift @@ -38,19 +38,23 @@ class PostHogAnalyticsClient: AnalyticsClientProtocol { /// Not persisted for now, should be set on start. private var superProperties: AnalyticsEvent.SuperProperties? - var isRunning: Bool { postHog?.enabled ?? false } + var isRunning: Bool { postHog != nil } func start(analyticsConfiguration: AnalyticsConfiguration) { // Only start if analytics have been configured in BuildSettings - guard let configuration = PHGPostHogConfiguration.standard(analyticsConfiguration: analyticsConfiguration) else { return } + guard let configuration = PostHogConfig.standard(analyticsConfiguration: analyticsConfiguration) else { return } - if postHog == nil { - postHog = posthogFactory.createPostHog(config: configuration) + if postHog != nil { + // start has been called twice in a row without calling stop()? + // Anyhow it's no-op if it's the case, but log for sanity + MXLog.failure("Posthog should always be nil when it's being started") } + postHog = posthogFactory.createPostHog(config: configuration) + // Add super property cryptoSDK to the captured events, to allow easy // filtering of events across different client by using same filter. superProperties = AnalyticsEvent.SuperProperties(appPlatform: nil, cryptoSDK: .Rust, cryptoSDKVersion: nil) - postHog?.enable() + postHog?.optIn() } func reset() { @@ -59,10 +63,8 @@ class PostHogAnalyticsClient: AnalyticsClientProtocol { } func stop() { - postHog?.disable() - - // As of PostHog 1.4.4, setting the client to nil here doesn't release - // it. Keep it around to avoid having multiple instances if the user re-enables + postHog?.optOut() + postHog = nil } func capture(_ event: AnalyticsEventProtocol) { diff --git a/UnitTests/Sources/AnalyticsTests.swift b/UnitTests/Sources/AnalyticsTests.swift index 8cdbc19fa..d35d02faf 100644 --- a/UnitTests/Sources/AnalyticsTests.swift +++ b/UnitTests/Sources/AnalyticsTests.swift @@ -265,4 +265,38 @@ class AnalyticsTests: XCTestCase { XCTAssertEqual(capturedEvent2?.properties?["appPlatform"] as? String, "A thing") XCTAssertEqual(capturedEvent2?.properties?["cryptoSDKVersion"] as? String, "001") } + + func testShouldNotReportIfNotStarted() { + // Given a client with user properties set + let client = PostHogAnalyticsClient(posthogFactory: MockPostHogFactory(mock: posthogMock)) + + // No call to start + + client.screen(AnalyticsEvent.MobileScreen(durationMs: nil, screenName: .Home)) + + XCTAssertEqual(posthogMock.screenPropertiesCalled, false) + + // It should be the same for any event + let someEvent = AnalyticsEvent.Error(context: nil, + cryptoModule: .Rust, + cryptoSDK: .Rust, + domain: .E2EE, + eventLocalAgeMillis: nil, + isFederated: nil, + isMatrixDotOrg: nil, + name: .OlmKeysNotSentError, + timeToDecryptMillis: nil, + userTrustsOwnIdentity: nil, + wasVisibleToUser: nil) + client.capture(someEvent) + + XCTAssertEqual(posthogMock.capturePropertiesCalled, false) + + // start now + client.start(analyticsConfiguration: appSettings.analyticsConfiguration) + XCTAssertEqual(posthogMock.optInCalled, true) + + client.capture(someEvent) + XCTAssertEqual(posthogMock.capturePropertiesCalled, true) + } } diff --git a/changelog.d/2788.misc b/changelog.d/2788.misc new file mode 100644 index 000000000..ca4e5c07d --- /dev/null +++ b/changelog.d/2788.misc @@ -0,0 +1 @@ +Bump posthog sdk version to 3.2.0 diff --git a/project.yml b/project.yml index b439d9665..8032a79a1 100644 --- a/project.yml +++ b/project.yml @@ -107,7 +107,7 @@ packages: minorVersion: 5.13.0 PostHog: url: https://github.com/PostHog/posthog-ios - minorVersion: 2.0.3 + minorVersion: 3.2.4 Prefire: url: https://github.com/BarredEwe/Prefire minorVersion: 2.0.4