Skip to content

Commit

Permalink
Record internal error when startup trace fails to be recorded
Browse files Browse the repository at this point in the history
  • Loading branch information
bidetofevil committed Sep 11, 2024
1 parent c6fbca9 commit 541c146
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ package io.embrace.android.embracesdk.internal.logging
enum class InternalErrorType {
UNCAUGHT_EXC_HANDLER,
ANR_DATA_FETCH,
UNBALANCED_CALL,
DISABLE_DATA_CAPTURE,
ENABLE_DATA_CAPTURE,
NETWORK_STATUS_CAPTURE_FAIL,
Expand All @@ -17,7 +16,6 @@ enum class InternalErrorType {
FG_SESSION_CACHE_FAIL,
ACTIVITY_LISTENER_FAIL,
PROCESS_STATE_CALLBACK_FAIL,
TIME_TRAVEL,
ANR_HEARTBEAT_CHECK_FAIL,
CFG_CHANGE_DATA_CAPTURE_FAIL,
SESSION_CHANGE_DATA_CAPTURE_FAIL,
Expand All @@ -31,12 +29,10 @@ enum class InternalErrorType {
NATIVE_CRASH_LOAD_FAIL,
INVALID_NATIVE_SYMBOLS,
NATIVE_HANDLER_INSTALL_FAIL,
INVALID_JS_EXCEPTION,
SAFE_DATA_CAPTURE_FAIL,
PROCESS_STATE_SUMMARY_FAIL,
UNBALANCED_FG_CALL,
UNBALANCED_BG_CALL,
ANR_HEARTBEAT_STOP_FAIL,
SDK_START_FAIL,
CONFIG_DESERIALIZATION_FAIL,
APP_STARTUP_TRACE_NOT_RECORDED,
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import android.os.Build.VERSION_CODES
import android.os.Process
import io.embrace.android.embracesdk.internal.clock.nanosToMillis
import io.embrace.android.embracesdk.internal.logging.EmbLogger
import io.embrace.android.embracesdk.internal.logging.InternalErrorType
import io.embrace.android.embracesdk.internal.spans.PersistableEmbraceSpan
import io.embrace.android.embracesdk.internal.spans.SpanService
import io.embrace.android.embracesdk.internal.utils.Provider
Expand Down Expand Up @@ -97,6 +98,7 @@ internal class AppStartupTraceEmitter(
private var sdkInitEndedInForeground: Boolean? = null

private val startupRecorded = AtomicBoolean(false)
private val dataCollectionComplete = AtomicBoolean(false)
private val endWithFrameDraw: Boolean = versionChecker.isAtLeast(VERSION_CODES.Q)

override fun applicationInitStart(timestampMs: Long?) {
Expand Down Expand Up @@ -161,16 +163,20 @@ internal class AppStartupTraceEmitter(
* Called when app startup is considered complete, i.e. the data can be used and any additional updates can be ignored
*/
private fun dataCollectionComplete(callback: () -> Unit) {
if (!startupRecorded.get()) {
synchronized(startupRecorded) {
if (!startupRecorded.get()) {
if (!dataCollectionComplete.get()) {
synchronized(dataCollectionComplete) {
if (!dataCollectionComplete.get()) {
backgroundWorker.submit {
recordStartup()
if (!startupRecorded.get()) {
logger.logWarning("App startup trace recording attempted but did not succeed")
logger.trackInternalError(
type = InternalErrorType.APP_STARTUP_TRACE_NOT_RECORDED,
throwable = IllegalStateException("App startup trace not recorded after terminal app startup event")
)
}
}
callback()
dataCollectionComplete.set(true)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ class StartupTracker(
private var isFirstDraw = false
private var nullWindowCallbackErrorLogged = false
private var startupActivityId: Int? = null
private var startupDataCollectionComplete = false

override fun onActivityPreCreated(activity: Activity, savedInstanceState: Bundle?) {
if (activity.useAsStartupActivity()) {
Expand All @@ -53,6 +54,7 @@ class StartupTracker(
override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {
if (activity.useAsStartupActivity()) {
val activityName = activity.localClassName
val application = activity.application
appStartupDataCollector.startupActivityInitStart()
if (versionChecker.isAtLeast(Build.VERSION_CODES.Q)) {
if (!isFirstDraw) {
Expand All @@ -66,7 +68,7 @@ class StartupTracker(
val callback = {
appStartupDataCollector.firstFrameRendered(
activityName = activityName,
collectionCompleteCallback = {}
collectionCompleteCallback = { startupComplete(application) }
)
}
decorView.viewTreeObserver.registerFrameCommitCallback(callback)
Expand Down Expand Up @@ -96,9 +98,10 @@ class StartupTracker(

override fun onActivityResumed(activity: Activity) {
if (activity.observeForStartup()) {
val application = activity.application
appStartupDataCollector.startupActivityResumed(
activityName = activity.localClassName,
collectionCompleteCallback = { }
collectionCompleteCallback = { startupComplete(application) }
)
}
}
Expand All @@ -111,6 +114,13 @@ class StartupTracker(

override fun onActivityDestroyed(activity: Activity) {}

private fun startupComplete(application: Application) {
if (!startupDataCollectionComplete) {
application.unregisterActivityLifecycleCallbacks(this)
startupDataCollectionComplete = true
}
}

/**
* Returns true if the Activity instance is being used as the startup Activity. It will return false if [useAsStartupActivity] has
* not been called previously to setup the Activity instance to be used as the startup Activity.
Expand Down

0 comments on commit 541c146

Please sign in to comment.