Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UTD posthog reporting add more properties to captured event #8780

Merged
merged 11 commits into from
Apr 2, 2024
1 change: 1 addition & 0 deletions changelog.d/8780.misc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Improve UTD reporting by adding additional fields to the report.
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package org.matrix.android.sdk.api.session

import org.matrix.android.sdk.api.session.crypto.MXCryptoError
import org.matrix.android.sdk.api.session.events.model.Event
import org.matrix.android.sdk.api.util.JsonDict

Expand All @@ -27,7 +28,7 @@ interface LiveEventListener {

fun onEventDecrypted(event: Event, clearEvent: JsonDict)

fun onEventDecryptionError(event: Event, throwable: Throwable)
fun onEventDecryptionError(event: Event, cryptoError: MXCryptoError)

fun onLiveToDeviceEvent(event: Event)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -172,8 +172,6 @@ internal class Device @AssistedInject constructor(
* This will not fetch out fresh data from the Rust side.
**/
internal fun toCryptoDeviceInfo(): CryptoDeviceInfo {
// val keys = innerDevice.keys.map { (keyId, key) -> keyId to key }.toMap()

return CryptoDeviceInfo(
deviceId = innerDevice.deviceId,
userId = innerDevice.userId,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -189,18 +189,21 @@ internal class OlmMachine @Inject constructor(
is OwnUserIdentity -> ownIdentity.trustsOurOwnDevice()
else -> false
}
val ownDevice = inner.getDevice(userId(), deviceId, 0u)!!
val creationTime = ownDevice.firstTimeSeenTs.toLong()

return CryptoDeviceInfo(
deviceId(),
userId(),
// TODO pass the algorithms here.
listOf(),
ownDevice.algorithms,
keys,
mapOf(),
UnsignedDeviceInfo(),
UnsignedDeviceInfo(
deviceDisplayName = ownDevice.displayName
),
DeviceTrustLevel(crossSigningVerified, locallyVerified = true),
false,
null
creationTime
)
}

Expand Down Expand Up @@ -291,7 +294,7 @@ internal class OlmMachine @Inject constructor(
// checking the returned to devices to check for room keys.
// XXX Anyhow there is now proper signaling we should soon stop parsing them manually
receiveSyncChanges.toDeviceEvents.map {
outAdapter.fromJson(it) ?: Event()
outAdapter.fromJson(it) ?: Event()
}
}

Expand Down Expand Up @@ -882,6 +885,7 @@ internal class OlmMachine @Inject constructor(
inner.queryMissingSecretsFromOtherSessions()
}
}

@Throws(CryptoStoreException::class)
suspend fun enableBackupV1(key: String, version: String) {
return withContext(coroutineDispatchers.computation) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.launch
import org.matrix.android.sdk.api.extensions.tryOrNull
import org.matrix.android.sdk.api.session.LiveEventListener
import org.matrix.android.sdk.api.session.crypto.MXCryptoError
import org.matrix.android.sdk.api.session.crypto.model.MXEventDecryptionResult
import org.matrix.android.sdk.api.session.events.model.Event
import timber.log.Timber
Expand Down Expand Up @@ -75,7 +76,7 @@ internal class StreamEventsManager @Inject constructor() {
}
}

fun dispatchLiveEventDecryptionFailed(event: Event, error: Throwable) {
fun dispatchLiveEventDecryptionFailed(event: Event, error: MXCryptoError) {
Timber.v("## dispatchLiveEventDecryptionFailed ${event.eventId}")
coroutineScope.launch {
listeners.forEach {
Expand Down
3 changes: 3 additions & 0 deletions vector-app/src/main/java/im/vector/app/VectorApplication.kt
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ import im.vector.app.core.debug.LeakDetector
import im.vector.app.core.di.ActiveSessionHolder
import im.vector.app.core.pushers.FcmHelper
import im.vector.app.core.resources.BuildMeta
import im.vector.app.features.analytics.DecryptionFailureTracker
import im.vector.app.features.analytics.VectorAnalytics
import im.vector.app.features.call.webrtc.WebRtcCallManager
import im.vector.app.features.configuration.VectorConfiguration
Expand Down Expand Up @@ -100,6 +101,7 @@ class VectorApplication :
@Inject lateinit var callManager: WebRtcCallManager
@Inject lateinit var invitesAcceptor: InvitesAcceptor
@Inject lateinit var autoRageShaker: AutoRageShaker
@Inject lateinit var decryptionFailureTracker: DecryptionFailureTracker
@Inject lateinit var vectorFileLogger: VectorFileLogger
@Inject lateinit var vectorAnalytics: VectorAnalytics
@Inject lateinit var flipperProxy: FlipperProxy
Expand Down Expand Up @@ -130,6 +132,7 @@ class VectorApplication :
vectorAnalytics.init()
invitesAcceptor.initialize()
autoRageShaker.initialize()
decryptionFailureTracker.start()
vectorUncaughtExceptionHandler.activate()

// Remove Log handler statically added by Jitsi
Expand Down
3 changes: 2 additions & 1 deletion vector/src/main/java/im/vector/app/UISIDetector.kt
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package im.vector.app

import org.matrix.android.sdk.api.extensions.orFalse
import org.matrix.android.sdk.api.session.LiveEventListener
import org.matrix.android.sdk.api.session.crypto.MXCryptoError
import org.matrix.android.sdk.api.session.events.model.Event
import org.matrix.android.sdk.api.session.events.model.content.EncryptedEventContent
import org.matrix.android.sdk.api.session.events.model.toModel
Expand Down Expand Up @@ -84,7 +85,7 @@ class UISIDetector(private val timeoutMillis: Long = 30_000L) : LiveEventListene
}
}

override fun onEventDecryptionError(event: Event, throwable: Throwable) {
override fun onEventDecryptionError(event: Event, cryptoError: MXCryptoError) {
val eventId = event.eventId
val roomId = event.roomId
if (!enabled || eventId == null || roomId == null) return
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ import im.vector.app.core.pushers.UnregisterUnifiedPushUseCase
import im.vector.app.core.services.GuardServiceStarter
import im.vector.app.core.session.ConfigureAndStartSessionUseCase
import im.vector.app.features.analytics.DecryptionFailureTracker
import im.vector.app.features.analytics.plan.Error
import im.vector.app.features.call.webrtc.WebRtcCallManager
import im.vector.app.features.crypto.keysrequest.KeyRequestHandler
import im.vector.app.features.crypto.verification.IncomingVerificationRequestHandler
Expand Down Expand Up @@ -75,11 +74,6 @@ class ActiveSessionHolder @Inject constructor(
session.callSignalingService().addCallListener(callManager)
imageManager.onSessionStarted(session)
guardServiceStarter.start()
decryptionFailureTracker.currentModule = if (session.cryptoService().name() == "rust-sdk") {
Error.CryptoModule.Rust
} else {
Error.CryptoModule.Native
}
}

suspend fun clearActiveSession() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/*
* Copyright (c) 2024 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package im.vector.app.features.analytics

import im.vector.app.features.analytics.plan.Error
import org.matrix.android.sdk.api.session.crypto.MXCryptoError

data class DecryptionFailure(
val timeStamp: Long,
val roomId: String,
val failedEventId: String,
val error: MXCryptoError,
val wasVisibleOnScreen: Boolean,
val ownIdentityTrustedAtTimeOfDecryptionFailure: Boolean,
// If this is set, it means that the event was decrypted but late. Will be -1 if
// the event was not decrypted after the maximum wait time.
val timeToDecryptMillis: Long? = null,
val isMatrixDotOrg: Boolean,
val isFederated: Boolean? = null,
val eventLocalAgeAtDecryptionFailure: Long? = null
)

fun DecryptionFailure.toAnalyticsEvent(): Error {
val errorMsg = (error as? MXCryptoError.Base)?.technicalMessage ?: error.message
return Error(
context = "mxc_crypto_error_type|${errorMsg}",
domain = Error.Domain.E2EE,
name = this.toAnalyticsErrorName(),
// this is deprecated keep for backward compatibility
cryptoModule = Error.CryptoModule.Rust,
cryptoSDK = Error.CryptoSDK.Rust,
eventLocalAgeMillis = eventLocalAgeAtDecryptionFailure?.toInt(),
isFederated = isFederated,
isMatrixDotOrg = isMatrixDotOrg,
timeToDecryptMillis = timeToDecryptMillis?.toInt() ?: -1,
wasVisibleToUser = wasVisibleOnScreen,
userTrustsOwnIdentity = ownIdentityTrustedAtTimeOfDecryptionFailure,
)
}

private fun DecryptionFailure.toAnalyticsErrorName(): Error.Name {
val error = this.error
val name = if (error is MXCryptoError.Base) {
when (error.errorType) {
MXCryptoError.ErrorType.UNKNOWN_INBOUND_SESSION_ID,
MXCryptoError.ErrorType.KEYS_WITHHELD -> Error.Name.OlmKeysNotSentError
MXCryptoError.ErrorType.OLM -> Error.Name.OlmUnspecifiedError
MXCryptoError.ErrorType.UNKNOWN_MESSAGE_INDEX -> Error.Name.OlmIndexError
else -> Error.Name.UnknownError
}
} else {
Error.Name.UnknownError
}
// check if it's an expected UTD!
val localAge = this.eventLocalAgeAtDecryptionFailure
val isHistorical = localAge != null && localAge < 0
if (isHistorical && !this.ownIdentityTrustedAtTimeOfDecryptionFailure) {
return Error.Name.HistoricalMessage
}

return name
}
Loading
Loading