From f0482ca324a7fafc3912d10043a9db7143ce2d10 Mon Sep 17 00:00:00 2001 From: Stefan Ceriu Date: Tue, 12 Mar 2024 09:12:57 +0200 Subject: [PATCH 1/3] Send UTD occurences to Posthog --- .../UserSessionFlowCoordinator.swift | 11 +++++++++++ .../Services/Analytics/AnalyticsService.swift | 6 +++++- ElementX/Sources/Services/Client/ClientProxy.swift | 13 +++++++++++++ .../Services/Client/ClientProxyProtocol.swift | 1 + 4 files changed, 30 insertions(+), 1 deletion(-) diff --git a/ElementX/Sources/FlowCoordinators/UserSessionFlowCoordinator.swift b/ElementX/Sources/FlowCoordinators/UserSessionFlowCoordinator.swift index 2403edc4b4..06e9d68e4e 100644 --- a/ElementX/Sources/FlowCoordinators/UserSessionFlowCoordinator.swift +++ b/ElementX/Sources/FlowCoordinators/UserSessionFlowCoordinator.swift @@ -139,6 +139,17 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol { } } .store(in: &cancellables) + + userSession.clientProxy.actionsPublisher + .receive(on: DispatchQueue.main) + .sink { action in + guard case .receivedDecryptionError = action else { + return + } + + analytics.trackError(context: nil, domain: .E2EE, name: .OlmKeysNotSentError) + } + .store(in: &cancellables) } func start() { diff --git a/ElementX/Sources/Services/Analytics/AnalyticsService.swift b/ElementX/Sources/Services/Analytics/AnalyticsService.swift index bd57000940..d697211f43 100644 --- a/ElementX/Sources/Services/Analytics/AnalyticsService.swift +++ b/ElementX/Sources/Services/Analytics/AnalyticsService.swift @@ -130,7 +130,11 @@ extension AnalyticsService { func trackInteraction(index: Int? = nil, name: AnalyticsEvent.Interaction.Name) { capture(event: AnalyticsEvent.Interaction(index: index, interactionType: .Touch, name: name)) } - + + func trackError(context: String?, domain: AnalyticsEvent.Error.Domain, name: AnalyticsEvent.Error.Name) { + capture(event: AnalyticsEvent.Error(context: context, cryptoModule: .Rust, domain: domain, name: name)) + } + /// Track the creation of a room /// - Parameter isDM: true if the created room is a direct message, false otherwise func trackCreatedRoom(isDM: Bool) { diff --git a/ElementX/Sources/Services/Client/ClientProxy.swift b/ElementX/Sources/Services/Client/ClientProxy.swift index e3b6052be1..2bf42670c3 100644 --- a/ElementX/Sources/Services/Client/ClientProxy.swift +++ b/ElementX/Sources/Services/Client/ClientProxy.swift @@ -589,6 +589,7 @@ class ClientProxy: ClientProxyProtocol { let syncService = try await client .syncService() .withCrossProcessLock(appIdentifier: "MainApp") + .withUtdHook(delegate: ClientDecryptionErrorDelegate(actionsSubject: actionsSubject)) .finish() let roomListService = syncService.roomListService() @@ -803,6 +804,18 @@ private class ClientDelegateWrapper: ClientDelegate { } } +private class ClientDecryptionErrorDelegate: UnableToDecryptDelegate { + private let actionsSubject: PassthroughSubject + + init(actionsSubject: PassthroughSubject) { + self.actionsSubject = actionsSubject + } + + func onUtd(info: UnableToDecryptInfo) { + actionsSubject.send(.receivedDecryptionError(info)) + } +} + private class IgnoredUsersListenerProxy: IgnoredUsersListener { private let onUpdateClosure: ([String]) -> Void diff --git a/ElementX/Sources/Services/Client/ClientProxyProtocol.swift b/ElementX/Sources/Services/Client/ClientProxyProtocol.swift index bb2a69b806..00c2d6bf44 100644 --- a/ElementX/Sources/Services/Client/ClientProxyProtocol.swift +++ b/ElementX/Sources/Services/Client/ClientProxyProtocol.swift @@ -21,6 +21,7 @@ import MatrixRustSDK enum ClientProxyAction { case receivedSyncUpdate case receivedAuthError(isSoftLogout: Bool) + case receivedDecryptionError(UnableToDecryptInfo) var isSyncUpdate: Bool { if case .receivedSyncUpdate = self { From 4cd2304b596e13f250251dac2a82f3e232f23776 Mon Sep 17 00:00:00 2001 From: Mauro Romito Date: Thu, 14 Mar 2024 16:10:05 +0100 Subject: [PATCH 2/3] bump SDK --- ElementX.xcodeproj/project.pbxproj | 2 +- .../project.xcworkspace/xcshareddata/swiftpm/Package.resolved | 4 ++-- project.yml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ElementX.xcodeproj/project.pbxproj b/ElementX.xcodeproj/project.pbxproj index 5d15778906..832d5763dd 100644 --- a/ElementX.xcodeproj/project.pbxproj +++ b/ElementX.xcodeproj/project.pbxproj @@ -7080,7 +7080,7 @@ repositoryURL = "https://github.com/matrix-org/matrix-rust-components-swift"; requirement = { kind = exactVersion; - version = 1.1.49; + version = 1.1.50; }; }; 821C67C9A7F8CC3FD41B28B4 /* XCRemoteSwiftPackageReference "emojibase-bindings" */ = { diff --git a/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index d20db52628..7d2f4b785f 100644 --- a/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -130,8 +130,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/matrix-org/matrix-rust-components-swift", "state" : { - "revision" : "0361eac2610f0007f2a6880a88c750a1bbb405b9", - "version" : "1.1.49" + "revision" : "e6b350d257aeb7395e003c3d0c26ae65c2e2e349", + "version" : "1.1.50" } }, { diff --git a/project.yml b/project.yml index 7594a6cb09..8809c02c82 100644 --- a/project.yml +++ b/project.yml @@ -48,7 +48,7 @@ packages: # Element/Matrix dependencies MatrixRustSDK: url: https://github.com/matrix-org/matrix-rust-components-swift - exactVersion: 1.1.49 + exactVersion: 1.1.50 # path: ../matrix-rust-sdk Compound: url: https://github.com/element-hq/compound-ios From 94ebe4b588d2a516c85b8c9cb8a3abb9314149b8 Mon Sep 17 00:00:00 2001 From: Mauro Romito Date: Thu, 14 Mar 2024 19:20:16 +0100 Subject: [PATCH 3/3] updated analytics and tests --- ElementX.xcodeproj/project.pbxproj | 2 +- .../xcshareddata/swiftpm/Package.resolved | 4 ++-- .../FlowCoordinators/UserSessionFlowCoordinator.swift | 11 +++++++++-- .../Sources/Services/Analytics/AnalyticsService.swift | 11 +++++++++-- UnitTests/Sources/LoggingTests.swift | 6 +++--- project.yml | 2 +- 6 files changed, 25 insertions(+), 11 deletions(-) diff --git a/ElementX.xcodeproj/project.pbxproj b/ElementX.xcodeproj/project.pbxproj index 832d5763dd..08a62be8a8 100644 --- a/ElementX.xcodeproj/project.pbxproj +++ b/ElementX.xcodeproj/project.pbxproj @@ -7128,7 +7128,7 @@ repositoryURL = "https://github.com/matrix-org/matrix-analytics-events"; requirement = { kind = upToNextMinorVersion; - minimumVersion = 0.13.0; + minimumVersion = 0.14.0; }; }; C13F55E4518415CB4C278E73 /* XCRemoteSwiftPackageReference "DTCoreText" */ = { diff --git a/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 7d2f4b785f..50300f4f3c 100644 --- a/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -121,8 +121,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/matrix-org/matrix-analytics-events", "state" : { - "revision" : "ccc4af6aa00987abe7135fa0b7cea97c8cfb3d26", - "version" : "0.13.0" + "revision" : "f756bf0756b7349a1d3ccee0d038790d1ab2ec56", + "version" : "0.14.0" } }, { diff --git a/ElementX/Sources/FlowCoordinators/UserSessionFlowCoordinator.swift b/ElementX/Sources/FlowCoordinators/UserSessionFlowCoordinator.swift index 06e9d68e4e..a13c99c9f7 100644 --- a/ElementX/Sources/FlowCoordinators/UserSessionFlowCoordinator.swift +++ b/ElementX/Sources/FlowCoordinators/UserSessionFlowCoordinator.swift @@ -143,11 +143,18 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol { userSession.clientProxy.actionsPublisher .receive(on: DispatchQueue.main) .sink { action in - guard case .receivedDecryptionError = action else { + guard case let .receivedDecryptionError(info) = action else { return } - analytics.trackError(context: nil, domain: .E2EE, name: .OlmKeysNotSentError) + let timeToDecryptMs: Int + if let unsignedTimeToDecryptMs = info.timeToDecryptMs { + timeToDecryptMs = Int(unsignedTimeToDecryptMs) + } else { + timeToDecryptMs = -1 + } + + analytics.trackError(context: nil, domain: .E2EE, name: .OlmKeysNotSentError, timeToDecryptMillis: timeToDecryptMs) } .store(in: &cancellables) } diff --git a/ElementX/Sources/Services/Analytics/AnalyticsService.swift b/ElementX/Sources/Services/Analytics/AnalyticsService.swift index d697211f43..aa5454cc53 100644 --- a/ElementX/Sources/Services/Analytics/AnalyticsService.swift +++ b/ElementX/Sources/Services/Analytics/AnalyticsService.swift @@ -131,8 +131,15 @@ extension AnalyticsService { capture(event: AnalyticsEvent.Interaction(index: index, interactionType: .Touch, name: name)) } - func trackError(context: String?, domain: AnalyticsEvent.Error.Domain, name: AnalyticsEvent.Error.Name) { - capture(event: AnalyticsEvent.Error(context: context, cryptoModule: .Rust, domain: domain, name: name)) + /// Track the presentation of a screen + /// - Parameter context: To provide additional context or description for the error + /// - Parameter domain: The domain to which the error belongs to. + /// - Parameter name: The name of the error + /// - Parameter timeToDecryptMillis: The time it took to decrypt the event in milliseconds, needs to be used only to track UTD errors, otherwise if the error is nort related to UTD it should be nil. + /// Can be found in `UnableToDecryptInfo`. In case the `UnableToDecryptInfo` contains the value as nil, pass it as `-1` + func trackError(context: String?, domain: AnalyticsEvent.Error.Domain, name: AnalyticsEvent.Error.Name, timeToDecryptMillis: Int? = nil) { + // CryptoModule is deprecated + capture(event: AnalyticsEvent.Error(context: context, cryptoModule: nil, cryptoSDK: .Rust, domain: domain, name: name, timeToDecryptMillis: timeToDecryptMillis)) } /// Track the creation of a room diff --git a/UnitTests/Sources/LoggingTests.swift b/UnitTests/Sources/LoggingTests.swift index ddc48ff691..32f3a8a202 100644 --- a/UnitTests/Sources/LoggingTests.swift +++ b/UnitTests/Sources/LoggingTests.swift @@ -223,9 +223,9 @@ class LoggingTests: XCTestCase { formatted: FormattedBody(format: .html, body: "\(emoteString)")) let pointer = Unmanaged.passRetained(NSURL(fileURLWithPath: "/tmp/file")).toOpaque() - let rustImageMessage = ImageMessageContent(body: "ImageString", source: MediaSource(unsafeFromRawPointer: pointer), info: nil) - let rustVideoMessage = VideoMessageContent(body: "VideoString", source: MediaSource(unsafeFromRawPointer: pointer), info: nil) - let rustFileMessage = FileMessageContent(body: "FileString", filename: "FileName", source: MediaSource(unsafeFromRawPointer: pointer), info: nil) + let rustImageMessage = ImageMessageContent(body: "ImageString", formatted: nil, filename: nil, source: MediaSource(unsafeFromRawPointer: pointer), info: nil) + let rustVideoMessage = VideoMessageContent(body: "VideoString", formatted: nil, filename: nil, source: MediaSource(unsafeFromRawPointer: pointer), info: nil) + let rustFileMessage = FileMessageContent(body: "FileString", formatted: nil, filename: "FileName", source: MediaSource(unsafeFromRawPointer: pointer), info: nil) // When logging that value MXLog.info(rustTextMessage) diff --git a/project.yml b/project.yml index 8809c02c82..081a4abfb8 100644 --- a/project.yml +++ b/project.yml @@ -56,7 +56,7 @@ packages: # path: ../compound-ios AnalyticsEvents: url: https://github.com/matrix-org/matrix-analytics-events - minorVersion: 0.13.0 + minorVersion: 0.14.0 # path: ../matrix-analytics-events Emojibase: url: https://github.com/matrix-org/emojibase-bindings