mirror of
https://github.com/ProtonMail/android-mail.git
synced 2026-05-15 09:50:40 +00:00
feat: Attach Rust logs file if app has crashed.
This commit is contained in:
committed by
MargeBot
parent
926045c683
commit
afe4d4e025
@@ -21,6 +21,7 @@ package ch.protonmail.android.initializer
|
||||
import android.content.Context
|
||||
import androidx.startup.Initializer
|
||||
import ch.protonmail.android.BuildConfig
|
||||
import ch.protonmail.android.logging.RustLogsAttachmentProcessor
|
||||
import ch.protonmail.android.logging.SentryUserObserver
|
||||
import dagger.hilt.EntryPoint
|
||||
import dagger.hilt.InstallIn
|
||||
@@ -35,6 +36,11 @@ import me.proton.core.configuration.EnvironmentConfigurationDefaults
|
||||
class SentryInitializer : Initializer<Unit> {
|
||||
|
||||
override fun create(context: Context) {
|
||||
val entryPoint = EntryPointAccessors.fromApplication(
|
||||
context.applicationContext,
|
||||
SentryInitializerEntryPoint::class.java
|
||||
)
|
||||
|
||||
SentryAndroid.init(context.applicationContext) { options: SentryOptions ->
|
||||
options.dsn = BuildConfig.SENTRY_DSN
|
||||
options.release = BuildConfig.VERSION_NAME
|
||||
@@ -45,14 +51,10 @@ class SentryInitializer : Initializer<Unit> {
|
||||
minBreadcrumbLevel = SentryLevel.INFO
|
||||
)
|
||||
)
|
||||
options.addEventProcessor(entryPoint.rustLogsAttachmentProcessor())
|
||||
}
|
||||
|
||||
val entryPoint = EntryPointAccessors.fromApplication(
|
||||
context.applicationContext,
|
||||
SentryInitializerEntryPoint::class.java
|
||||
)
|
||||
entryPoint.observer().start()
|
||||
|
||||
}
|
||||
|
||||
override fun dependencies(): List<Class<out Initializer<*>>> = emptyList()
|
||||
@@ -60,6 +62,8 @@ class SentryInitializer : Initializer<Unit> {
|
||||
@EntryPoint
|
||||
@InstallIn(SingletonComponent::class)
|
||||
interface SentryInitializerEntryPoint {
|
||||
|
||||
fun observer(): SentryUserObserver
|
||||
fun rustLogsAttachmentProcessor(): RustLogsAttachmentProcessor
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Proton Technologies AG
|
||||
* This file is part of Proton Technologies AG and Proton Mail.
|
||||
*
|
||||
* Proton Mail is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Proton Mail is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Proton Mail. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package ch.protonmail.android.logging
|
||||
|
||||
import java.io.File
|
||||
import java.io.RandomAccessFile
|
||||
import ch.protonmail.android.mailbugreport.domain.LogsFileHandler
|
||||
import ch.protonmail.android.mailbugreport.domain.annotations.RustLogsFileHandler
|
||||
import io.sentry.Attachment
|
||||
import io.sentry.EventProcessor
|
||||
import io.sentry.Hint
|
||||
import io.sentry.SentryEvent
|
||||
import javax.inject.Inject
|
||||
|
||||
private const val MAX_BYTES = 16 * 1024
|
||||
|
||||
class RustLogsAttachmentProcessor @Inject constructor(
|
||||
@RustLogsFileHandler
|
||||
private val logsFileHandler: LogsFileHandler
|
||||
) : EventProcessor {
|
||||
|
||||
override fun process(event: SentryEvent, hint: Hint): SentryEvent {
|
||||
if (event.isCrashed) {
|
||||
getRustLogsAttachment()?.let { logs ->
|
||||
hint.addAttachment(logs)
|
||||
}
|
||||
}
|
||||
return event
|
||||
}
|
||||
|
||||
private fun getRustLogsAttachment(maxBytes: Int = MAX_BYTES): Attachment? = runCatching {
|
||||
logsFileHandler.getLastLogFile()?.let { file ->
|
||||
val bytes = readFileTail(file, maxBytes)
|
||||
Attachment(bytes, file.name)
|
||||
}
|
||||
}.getOrNull()
|
||||
|
||||
private fun readFileTail(file: File, maxBytes: Int): ByteArray = RandomAccessFile(file, "r").use { raf ->
|
||||
val fileLen = raf.length()
|
||||
val bytesToRead = minOf(fileLen, maxBytes.toLong())
|
||||
raf.seek(maxOf(fileLen - bytesToRead, 0))
|
||||
|
||||
val bytes = ByteArray(bytesToRead.toInt())
|
||||
raf.readFully(bytes)
|
||||
bytes
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user