Skip to content

Commit 49fc406

Browse files
authored
[andr] Fatal Issue reporter code cleanup (#572)
* Simplify logger to remove the need for two clientAttributes * Make AppExitLoggerTest run in gradle+AS * fmt * version missmatch fix
1 parent fae7673 commit 49fc406

File tree

8 files changed

+26
-129
lines changed

8 files changed

+26
-129
lines changed

platform/jvm/capture/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ dependencies {
3737
testImplementation(libs.assertj.core)
3838
testImplementation(libs.mockito.core)
3939
testImplementation(libs.mockito.kotlin)
40+
testImplementation(libs.mockito.kotlin.inline)
4041
testImplementation(libs.androidx.test.core)
4142
testImplementation(libs.robolectric)
4243
testImplementation(libs.mockwebserver)

platform/jvm/capture/src/main/kotlin/io/bitdrift/capture/Capture.kt

Lines changed: 7 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,8 @@ package io.bitdrift.capture
99

1010
import android.content.Context
1111
import android.util.Log
12-
import androidx.lifecycle.ProcessLifecycleOwner
12+
import io.bitdrift.capture.Capture.Logger.startSpan
1313
import io.bitdrift.capture.LoggerImpl.SdkConfiguredDuration
14-
import io.bitdrift.capture.attributes.ClientAttributes
1514
import io.bitdrift.capture.common.MainThreadHandler
1615
import io.bitdrift.capture.events.span.Span
1716
import io.bitdrift.capture.events.span.SpanResult
@@ -21,8 +20,6 @@ import io.bitdrift.capture.providers.DateProvider
2120
import io.bitdrift.capture.providers.FieldProvider
2221
import io.bitdrift.capture.providers.SystemDateProvider
2322
import io.bitdrift.capture.providers.session.SessionStrategy
24-
import io.bitdrift.capture.reports.FatalIssueReporterFactory
25-
import io.bitdrift.capture.reports.IFatalIssueReporter
2623
import okhttp3.HttpUrl
2724
import java.util.UUID
2825
import java.util.concurrent.atomic.AtomicReference
@@ -108,9 +105,10 @@ object Capture {
108105
* @return the version as a String
109106
*/
110107
@JvmStatic
111-
val sdkVersion: String get() {
112-
return BuildConstants.SDK_VERSION
113-
}
108+
val sdkVersion: String
109+
get() {
110+
return BuildConstants.SDK_VERSION
111+
}
114112

115113
/**
116114
* Initializes the Capture SDK with the specified API key, providers, and configuration.
@@ -152,6 +150,8 @@ object Capture {
152150
)
153151
}
154152

153+
// Note that we need to use @Synchronized to prevent multiple loggers from being initialized,
154+
// while subsequent logger access relies on volatile reads.
155155
@Synchronized
156156
@JvmStatic
157157
@JvmOverloads
@@ -165,9 +165,6 @@ object Capture {
165165
bridge: IBridge,
166166
context: Context? = null,
167167
) {
168-
// Note that we need to use @Synchronized to prevent multiple loggers from being initialized,
169-
// while subsequent logger access relies on volatile reads.
170-
171168
// There's nothing we can do if we don't have yet access to the application context.
172169
if (hasInvalidContext(context)) {
173170
Log.w(
@@ -514,39 +511,27 @@ object Capture {
514511

515512
val appContext = context?.applicationContext ?: ContextHolder.APP_CONTEXT
516513

517-
val clientAttributes =
518-
ClientAttributes(
519-
appContext,
520-
ProcessLifecycleOwner.get(),
521-
)
522-
523514
val nativeLoadDuration =
524515
measureTime {
525516
CaptureJniLibrary.load()
526517
}
527518

528-
val fatalIssueReporter: IFatalIssueReporter? = FatalIssueReporterFactory.create(configuration)
529-
530519
val (loggerImpl, loggerImplBuildDuration) =
531520
measureTimedValue {
532521
LoggerImpl(
533522
apiKey = apiKey,
534523
apiUrl = apiUrl,
535524
context = appContext,
536-
clientAttributes = clientAttributes,
537525
fieldProviders = fieldProviders,
538526
dateProvider = dateProvider ?: SystemDateProvider(),
539527
configuration = configuration,
540528
sessionStrategy = sessionStrategy,
541529
bridge = bridge,
542-
fatalIssueReporter = fatalIssueReporter,
543530
)
544531
}
545532

546533
default.set(LoggerState.Started(loggerImpl))
547534

548-
fatalIssueReporter?.initBuiltInMode(appContext, clientAttributes, loggerImpl)
549-
550535
val sdkConfiguredDuration =
551536
SdkConfiguredDuration(
552537
wholeStartDuration = startSdkTimer.elapsedNow(),

platform/jvm/capture/src/main/kotlin/io/bitdrift/capture/LoggerImpl.kt

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ import io.bitdrift.capture.providers.MetadataProvider
4747
import io.bitdrift.capture.providers.session.SessionStrategy
4848
import io.bitdrift.capture.providers.toFieldValue
4949
import io.bitdrift.capture.providers.toFields
50+
import io.bitdrift.capture.reports.FatalIssueReporter
5051
import io.bitdrift.capture.reports.IFatalIssueReporter
5152
import io.bitdrift.capture.reports.processor.ICompletedReportsProcessor
5253
import io.bitdrift.capture.threading.CaptureDispatchers
@@ -83,7 +84,12 @@ internal class LoggerImpl(
8384
bridge: IBridge = CaptureJniLibrary,
8485
private val eventListenerDispatcher: CaptureDispatchers.CommonBackground = CaptureDispatchers.CommonBackground,
8586
windowManager: IWindowManager = WindowManager(errorHandler),
86-
private val fatalIssueReporter: IFatalIssueReporter?,
87+
private val fatalIssueReporter: IFatalIssueReporter? =
88+
if (configuration.enableFatalIssueReporting) {
89+
FatalIssueReporter(configuration.enableNativeCrashReporting)
90+
} else {
91+
null
92+
},
8793
) : ILogger,
8894
ICompletedReportsProcessor {
8995
private val metadataProvider: MetadataProvider
@@ -249,7 +255,7 @@ internal class LoggerImpl(
249255
runtime,
250256
errorHandler,
251257
memoryMetricsProvider = memoryMetricsProvider,
252-
fatalIssueReporter = fatalIssueReporter,
258+
isFatalIssueReporterEnabled = configuration.enableFatalIssueReporting,
253259
)
254260

255261
// Install the app exit logger before the Capture logger is started to ensure
@@ -258,6 +264,9 @@ internal class LoggerImpl(
258264
appExitLogger.installAppExitLogger()
259265

260266
CaptureJniLibrary.startLogger(this.loggerId)
267+
268+
// fatal issue reporter needs to be initialized after appExitLogger and the jniLogger
269+
fatalIssueReporter?.initBuiltInMode(context, clientAttributes, this)
261270
}
262271

263272
override fun processCrashReports() {

platform/jvm/capture/src/main/kotlin/io/bitdrift/capture/events/lifecycle/AppExitLogger.kt

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,6 @@ import io.bitdrift.capture.common.Runtime
2626
import io.bitdrift.capture.common.RuntimeFeature
2727
import io.bitdrift.capture.events.performance.IMemoryMetricsProvider
2828
import io.bitdrift.capture.providers.toFields
29-
import io.bitdrift.capture.reports.FatalIssueMechanism
30-
import io.bitdrift.capture.reports.IFatalIssueReporter
3129
import io.bitdrift.capture.reports.exitinfo.ILatestAppExitInfoProvider
3230
import io.bitdrift.capture.reports.exitinfo.LatestAppExitInfoProvider
3331
import io.bitdrift.capture.reports.exitinfo.LatestAppExitReasonResult
@@ -49,7 +47,7 @@ internal class AppExitLogger(
4947
private val backgroundThreadHandler: IBackgroundThreadHandler = CaptureDispatchers.CommonBackground,
5048
private val latestAppExitInfoProvider: ILatestAppExitInfoProvider = LatestAppExitInfoProvider,
5149
private val captureUncaughtExceptionHandler: ICaptureUncaughtExceptionHandler = CaptureUncaughtExceptionHandler,
52-
private val fatalIssueReporter: IFatalIssueReporter?,
50+
private val isFatalIssueReporterEnabled: Boolean,
5351
) : IJvmCrashListener {
5452
companion object {
5553
private const val APP_EXIT_EVENT_NAME = "AppExit"
@@ -138,8 +136,7 @@ internal class AppExitLogger(
138136
throwable: Throwable,
139137
) {
140138
// When FatalIssueMechanism.BuiltIn is configured will rely on shared-core to emit the related JVM crash log
141-
if (!runtime.isEnabled(RuntimeFeature.APP_EXIT_EVENTS) ||
142-
fatalIssueReporter?.getReportingMechanism() == FatalIssueMechanism.BuiltIn
139+
if (!runtime.isEnabled(RuntimeFeature.APP_EXIT_EVENTS) || isFatalIssueReporterEnabled
143140
) {
144141
return
145142
}

platform/jvm/capture/src/main/kotlin/io/bitdrift/capture/reports/FatalIssueReporterFactory.kt

Lines changed: 0 additions & 28 deletions
This file was deleted.

platform/jvm/capture/src/test/kotlin/io/bitdrift/capture/events/lifecycle/AppExitLoggerTest.kt

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ import io.bitdrift.capture.LoggerImpl
2525
import io.bitdrift.capture.common.Runtime
2626
import io.bitdrift.capture.common.RuntimeFeature
2727
import io.bitdrift.capture.fakes.FakeBackgroundThreadHandler
28-
import io.bitdrift.capture.fakes.FakeFatalIssueReporter
2928
import io.bitdrift.capture.fakes.FakeLatestAppExitInfoProvider
3029
import io.bitdrift.capture.fakes.FakeLatestAppExitInfoProvider.Companion.FAKE_EXCEPTION
3130
import io.bitdrift.capture.fakes.FakeLatestAppExitInfoProvider.Companion.SESSION_ID
@@ -34,7 +33,6 @@ import io.bitdrift.capture.fakes.FakeMemoryMetricsProvider
3433
import io.bitdrift.capture.fakes.FakeMemoryMetricsProvider.Companion.DEFAULT_MEMORY_ATTRIBUTES_MAP
3534
import io.bitdrift.capture.providers.FieldValue
3635
import io.bitdrift.capture.providers.toFields
37-
import io.bitdrift.capture.reports.FatalIssueMechanism
3836
import io.bitdrift.capture.reports.exitinfo.LatestAppExitInfoProvider.EXIT_REASON_EMPTY_LIST_MESSAGE
3937
import io.bitdrift.capture.reports.exitinfo.LatestAppExitInfoProvider.EXIT_REASON_EXCEPTION_MESSAGE
4038
import io.bitdrift.capture.reports.exitinfo.LatestAppExitInfoProvider.EXIT_REASON_UNMATCHED_PROCESS_NAME_MESSAGE
@@ -283,7 +281,7 @@ class AppExitLoggerTest {
283281

284282
@Test
285283
fun onJvmCrash_whenBuiltInFatalIssueMechanism_shouldNotSendAppExitCrashLog() {
286-
val appExitLogger = buildAppExitLogger(FatalIssueMechanism.BuiltIn)
284+
val appExitLogger = buildAppExitLogger(isFatalIssueReporterEnabled = true)
287285
whenever(runtime.isEnabled(RuntimeFeature.LOGGER_FLUSHING_ON_CRASH)).thenReturn(true)
288286

289287
appExitLogger.onJvmCrash(Thread.currentThread(), IllegalStateException("Simulated Crash"))
@@ -300,7 +298,7 @@ class AppExitLoggerTest {
300298
verify(logger, never()).flush(any())
301299
}
302300

303-
private fun buildAppExitLogger(fatalIssueMechanism: FatalIssueMechanism = FatalIssueMechanism.None) =
301+
private fun buildAppExitLogger(isFatalIssueReporterEnabled: Boolean = false) =
304302
AppExitLogger(
305303
logger,
306304
activityManager,
@@ -311,7 +309,7 @@ class AppExitLoggerTest {
311309
backgroundThreadHandler,
312310
lastExitInfo,
313311
captureUncaughtExceptionHandler,
314-
FakeFatalIssueReporter(fatalIssueMechanism),
312+
isFatalIssueReporterEnabled,
315313
)
316314

317315
private fun buildExpectedAnrFields(): Map<String, FieldValue> =

platform/jvm/capture/src/test/kotlin/io/bitdrift/capture/reports/FatalIssueReporterFactoryTest.kt

Lines changed: 0 additions & 66 deletions
This file was deleted.

platform/jvm/gradle/libs.versions.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ kotlinResultJvm = "1.1.18"
1717
lifecycleCommon = "2.8.7"
1818
material3Android = "1.2.1"
1919
mavenPublishPlugin = "0.28.0"
20-
mockitoCore = "4.9.0"
20+
mockitoCore = "4.11.0"
2121
mockitoKotlin = "2.2.0"
2222
mockitoKotlinVersion = "4.1.0"
2323
okhttp = "4.12.0"
@@ -49,6 +49,7 @@ kotlin-mockito-kotlin = { module = "org.mockito.kotlin:mockito-kotlin", ver
4949
kotlin-result-jvm = { module = "com.michael-bull.kotlin-result:kotlin-result-jvm", version.ref = "kotlinResultJvm" }
5050
mockito-core = { module = "org.mockito:mockito-core", version.ref = "mockitoCore" }
5151
mockito-kotlin = { module = "com.nhaarman.mockitokotlin2:mockito-kotlin", version.ref = "mockitoKotlin" }
52+
mockito-kotlin-inline = { module = "org.mockito:mockito-inline", version.ref = "mockitoCore" }
5253
mockwebserver = { module = "com.squareup.okhttp3:mockwebserver", version.ref = "okhttp" }
5354
okhttp = { module = "com.squareup.okhttp3:okhttp", version.ref = "okhttp" }
5455
performance = { module = "androidx.metrics:metrics-performance", version.ref = "performance" }

0 commit comments

Comments
 (0)