Improve logging on some backup validation errors.

This commit is contained in:
Greyson Parrelli
2025-02-14 11:40:28 -05:00
parent c1ce4ba80d
commit 16309d87cd
6 changed files with 107 additions and 18 deletions

View File

@@ -10,6 +10,8 @@ import org.signal.libsignal.messagebackup.MessageBackup
import org.signal.libsignal.messagebackup.ValidationError
import org.thoughtcrime.securesms.database.SignalDatabase
import org.thoughtcrime.securesms.keyvalue.SignalStore
import org.thoughtcrime.securesms.recipients.Recipient
import org.thoughtcrime.securesms.recipients.RecipientId
import org.thoughtcrime.securesms.util.isStory
import org.thoughtcrime.securesms.util.isStoryReaction
import org.whispersystems.signalservice.api.backup.MessageBackupKey
@@ -40,11 +42,36 @@ object ArchiveValidator {
} catch (e: IOException) {
ValidationResult.ReadError(e)
} catch (e: ValidationError) {
val sentTimestamp = "\\d{10,}+".toRegex().find(e.message ?: "")?.value?.toLongOrNull()
ValidationResult.ValidationError(
exception = e,
messageDetails = sentTimestamp?.let { fetchMessageDetails(it) } ?: emptyList()
)
if (e.message?.contains("have the same phone number") == true) {
val recipientIds = """RecipientId\((\d+)\)""".toRegex()
.findAll(e.message ?: "")
.map { it.groupValues[1] }
.mapNotNull { it.toLongOrNull() }
.map { RecipientId.from(it) }
.toList()
val recipientIdA = recipientIds.getOrNull(0)
val recipientIdB = recipientIds.getOrNull(1)
val e164A = recipientIdA?.let { Recipient.resolved(it).e164.orElse("UNKNOWN") }.let { "KEEP_E164::$it" }
val e164B = recipientIdB?.let { Recipient.resolved(it).e164.orElse("UNKNOWN") }.let { "KEEP_E164::$it" }
ValidationResult.RecipientDuplicateE164Error(
exception = e,
details = DuplicateRecipientDetails(
recipientIdA = recipientIds.getOrNull(0),
recipientIdB = recipientIds.getOrNull(1),
e164A = e164A,
e164B = e164B
)
)
} else {
val sentTimestamp = "\\d{10,}+".toRegex().find(e.message ?: "")?.value?.toLongOrNull()
ValidationResult.MessageValidationError(
exception = e,
messageDetails = sentTimestamp?.let { fetchMessageDetails(it) } ?: emptyList()
)
}
}
}
@@ -74,10 +101,14 @@ object ArchiveValidator {
sealed interface ValidationResult {
data object Success : ValidationResult
data class ReadError(val exception: IOException) : ValidationResult
data class ValidationError(
val exception: org.signal.libsignal.messagebackup.ValidationError,
data class MessageValidationError(
val exception: ValidationError,
val messageDetails: List<MessageDetails>
) : ValidationResult
data class RecipientDuplicateE164Error(
val exception: ValidationError,
val details: DuplicateRecipientDetails
) : ValidationResult
}
data class MessageDetails(
@@ -97,4 +128,11 @@ object ArchiveValidator {
val originalMessageId: Long,
val isLatestRevision: Boolean
)
data class DuplicateRecipientDetails(
val recipientIdA: RecipientId?,
val recipientIdB: RecipientId?,
val e164A: String?,
val e164B: String?
)
}

View File

@@ -151,10 +151,14 @@ class InternalBackupPlaygroundViewModel : ViewModel() {
val message = when (result) {
is ArchiveValidator.ValidationResult.ReadError -> "Failed to read backup file!"
ArchiveValidator.ValidationResult.Success -> "Validation passed!"
is ArchiveValidator.ValidationResult.ValidationError -> {
is ArchiveValidator.ValidationResult.MessageValidationError -> {
Log.w(TAG, "Validation failed! Details: ${result.messageDetails}", result.exception)
"Validation failed :( Check the logs for details."
}
is ArchiveValidator.ValidationResult.RecipientDuplicateE164Error -> {
Log.w(TAG, "Validation failed with a duplicate recipient! Details: ${result.details}", result.exception)
"Validation failed :( Check the logs for details."
}
}
_state.value = _state.value.copy(statusMessage = message)
}

View File

@@ -226,11 +226,17 @@ class BackupMessagesJob private constructor(
return BackupFileResult.Retry
}
is ArchiveValidator.ValidationResult.ValidationError -> {
is ArchiveValidator.ValidationResult.MessageValidationError -> {
Log.w(TAG, "The backup file fails validation! Message: ${result.exception.message}, Details: ${result.messageDetails}")
ArchiveUploadProgress.onValidationFailure()
return BackupFileResult.Failure
}
is ArchiveValidator.ValidationResult.RecipientDuplicateE164Error -> {
Log.w(TAG, "The backup file fails validation with a duplicate recipient! Message: ${result.exception.message}, Details: ${result.details}")
ArchiveUploadProgress.onValidationFailure()
return BackupFileResult.Failure
}
}
stopwatch.split("validate")

View File

@@ -277,10 +277,14 @@ object LinkDeviceRepository {
Log.w(TAG, "[createAndUploadArchive] Failed to read the file during validation!", result.exception)
return LinkUploadArchiveResult.BackupCreationFailure(result.exception)
}
is ArchiveValidator.ValidationResult.ValidationError -> {
is ArchiveValidator.ValidationResult.MessageValidationError -> {
Log.w(TAG, "[createAndUploadArchive] The backup file fails validation! Details: ${result.messageDetails}", result.exception)
return LinkUploadArchiveResult.BackupCreationFailure(result.exception)
}
is ArchiveValidator.ValidationResult.RecipientDuplicateE164Error -> {
Log.w(TAG, "[createAndUploadArchive] The backup file fails validation with a duplicate recipient! Details: ${result.details}", result.exception)
return LinkUploadArchiveResult.BackupCreationFailure(result.exception)
}
}
stopwatch.split("validate-backup")