Analytics | Report expected UTDs as HistoricalMessage error

This commit is contained in:
Valere
2024-04-04 13:01:19 +02:00
parent c6761c8b43
commit 047be10692
6 changed files with 477 additions and 21 deletions
@@ -21,23 +21,34 @@ extension DecryptionFailure {
public func toAnalyticsEvent() -> AnalyticsEvent.Error {
let timeToDecryptMillis: Int = if self.timeToDecrypt != nil {
Int(self.timeToDecrypt! * 1000)
let timeToDecryptMillis: Int = if let ttd = self.timeToDecrypt {
Int(ttd * 1000)
} else {
-1
}
let isHistoricalEvent = if let localAge = self.eventLocalAgeMillis {
localAge < 0
} else { false }
let errorName = if isHistoricalEvent && self.trustOwnIdentityAtTimeOfFailure == false {
AnalyticsEvent.Error.Name.HistoricalMessage
} else {
self.reason.errorName
}
return AnalyticsEvent.Error(
context: self.context,
cryptoModule: .Rust,
cryptoSDK: .Rust,
domain: .E2EE,
eventLocalAgeMillis: nil,
eventLocalAgeMillis: self.eventLocalAgeMillis,
isFederated: nil,
isMatrixDotOrg: nil,
name: self.reason.errorName,
name: errorName,
timeToDecryptMillis: timeToDecryptMillis,
userTrustsOwnIdentity: nil,
userTrustsOwnIdentity: self.trustOwnIdentityAtTimeOfFailure,
wasVisibleToUser: nil
)
}
@@ -47,6 +47,11 @@ import AnalyticsEvents
/// UTDs can be permanent or temporary. If temporary, this field will contain the time it took to decrypt the message in milliseconds. If permanent should be nil
var timeToDecrypt: TimeInterval?
/// Was the current cross-signing identity trusted at the time of decryption
var trustOwnIdentityAtTimeOfFailure: Bool?
var eventLocalAgeMillis: Int?
init(failedEventId: String, reason: DecryptionFailureReason, context: String, ts: TimeInterval) {
self.failedEventId = failedEventId
self.reason = reason
@@ -62,14 +62,14 @@ class DecryptionFailureTracker: NSObject {
selector: #selector(eventDidDecrypt(_:)),
name: .mxEventDidDecrypt,
object: nil)
}
@objc
func reportUnableToDecryptError(forEvent event: MXEvent, withRoomState roomState: MXRoomState, myUser userId: String) {
func reportUnableToDecryptError(forEvent event: MXEvent, withRoomState roomState: MXRoomState, mySession: MXSession) {
if reportedFailures[event.eventId] != nil || trackedEvents.contains(event.eventId) {
return
}
guard let userId = mySession.myUserId else { return }
// Filter out "expected" UTDs
// We cannot decrypt messages sent before the user joined the room
@@ -82,6 +82,12 @@ class DecryptionFailureTracker: NSObject {
guard let error = event.decryptionError as? NSError else { return }
let eventOrigin = event.originServerTs
let deviceTimestamp = mySession.crypto.deviceCreationTs
// If negative it's an historical event relative to the current session
let eventRelativeAgeMillis = Int(eventOrigin) - Int(deviceTimestamp)
let isSessionVerified = mySession.crypto.crossSigning.canTrustCrossSigning
var reason = DecryptionFailureReason.unspecified
if error.code == MXDecryptingErrorUnknownInboundSessionIdCode.rawValue {
@@ -92,7 +98,13 @@ class DecryptionFailureTracker: NSObject {
let context = String(format: "code: %ld, description: %@", error.code, event.decryptionError.localizedDescription)
reportedFailures[failedEventId] = DecryptionFailure(failedEventId: failedEventId, reason: reason, context: context, ts: self.timeProvider.nowTs())
let failure = DecryptionFailure(failedEventId: failedEventId, reason: reason, context: context, ts: self.timeProvider.nowTs())
failure.eventLocalAgeMillis = Int(exactly: eventRelativeAgeMillis)
failure.trustOwnIdentityAtTimeOfFailure = isSessionVerified
reportedFailures[failedEventId] = failure
// Start the ticker if needed. There is no need to have a ticker if no failures are tracked
if checkFailuresTimer == nil {