Skip to content

Commit

Permalink
Add metadata to sdk startup trace
Browse files Browse the repository at this point in the history
  • Loading branch information
bidetofevil committed May 13, 2024
1 parent 087ac14 commit 516809c
Show file tree
Hide file tree
Showing 6 changed files with 33 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -373,17 +373,20 @@ private void startImpl(@NonNull Context context,
final long endTimeMs = sdkClock.now();
started.set(true);
Systrace.endSynchronous();
Systrace.startSynchronous("startup-tracking");
dataCaptureServiceModule.getStartupService().setSdkStartupInfo(startTimeMs, endTimeMs);
Systrace.endSynchronous();
boolean inForeground = !essentialServiceModule.getProcessStateService().isInBackground();

// Attempt to send the startup event if the app is already in the foreground. We registered to send this when
// we went to the foreground, but if an activity had already gone to the foreground, we may have missed
// sending this, so to ensure the startup message is sent, we force it to be sent here.
if (!essentialServiceModule.getProcessStateService().isInBackground()) {
if (inForeground) {
dataContainerModule.getEventService().sendStartupMoment();
}

Systrace.startSynchronous("startup-tracking");
dataCaptureServiceModule.getStartupService().setSdkStartupInfo(
startTimeMs, endTimeMs, inForeground, Thread.currentThread().getName());
Systrace.endSynchronous();

// This should return immediately given that EmbraceSpansService initialization should be finished at this point
// Put in emergency timeout just in case something unexpected happens so as to fail the SDK startup.
moduleInitBootstrapper.waitForAsyncInit();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ internal interface StartupService {
/**
* Sets the SDK startup info. This is called when the SDK is initialized.
*/
fun setSdkStartupInfo(startTimeMs: Long, endTimeMs: Long)
fun setSdkStartupInfo(startTimeMs: Long, endTimeMs: Long, endedInForeground: Boolean, threadName: String?)

/**
* Returns the SDK startup duration. This is called when the session ends.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,17 @@ internal class StartupServiceImpl(
@Volatile
private var sdkStartupDurationMs: Long? = null

override fun setSdkStartupInfo(startTimeMs: Long, endTimeMs: Long) {
override fun setSdkStartupInfo(startTimeMs: Long, endTimeMs: Long, endedInForeground: Boolean, threadName: String?) {
if (sdkStartupDurationMs == null) {
spanService.recordCompletedSpan(
name = "sdk-init",
startTimeMs = startTimeMs,
endTimeMs = endTimeMs,
private = true,
attributes = mapOf(
"ended-in-foreground" to endedInForeground.toString(),
"thread-name" to (threadName ?: "unknown"),
),
)
}
sdkInitStartMs = startTimeMs
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ internal class AppStartupTraceEmitterTest {
appStartupTraceEmitter.applicationInitEnd()
val applicationInitEnd = clock.now()
clock.tick(50L)
checkNotNull(startupService).setSdkStartupInfo(sdkInitStart, sdkInitEnd)
checkNotNull(startupService).setSdkStartupInfo(sdkInitStart, sdkInitEnd, false, "main")
appStartupTraceEmitter.startupActivityPreCreated()
val startupActivityPreCreated = clock.now()
clock.tick()
Expand Down Expand Up @@ -256,7 +256,7 @@ internal class AppStartupTraceEmitterTest {
clock.tick(30L)
val sdkInitEnd = clock.now()
clock.tick(400L)
checkNotNull(startupService).setSdkStartupInfo(sdkInitStart, sdkInitEnd)
checkNotNull(startupService).setSdkStartupInfo(sdkInitStart, sdkInitEnd, false, "main")
appStartupTraceEmitter.startupActivityPreCreated()
val startupActivityPreCreated = clock.now()
clock.tick()
Expand Down Expand Up @@ -311,7 +311,7 @@ internal class AppStartupTraceEmitterTest {
appStartupTraceEmitter.applicationInitEnd()
val applicationInitEnd = clock.now()
clock.tick(50L)
checkNotNull(startupService).setSdkStartupInfo(sdkInitStart, sdkInitEnd)
checkNotNull(startupService).setSdkStartupInfo(sdkInitStart, sdkInitEnd, false, "main")
appStartupTraceEmitter.startupActivityInitStart()
val startupActivityStart = clock.now()
clock.tick(180L)
Expand Down Expand Up @@ -356,7 +356,7 @@ internal class AppStartupTraceEmitterTest {
clock.tick(30L)
val sdkInitEnd = clock.now()
clock.tick(400L)
checkNotNull(startupService).setSdkStartupInfo(sdkInitStart, sdkInitEnd)
checkNotNull(startupService).setSdkStartupInfo(sdkInitStart, sdkInitEnd, false, "main")
appStartupTraceEmitter.startupActivityInitStart()
val startupActivityStart = clock.now()
clock.tick(180L)
Expand Down Expand Up @@ -398,7 +398,7 @@ internal class AppStartupTraceEmitterTest {
val sdkInitStart = clock.now()
clock.tick(30L)
val sdkInitEnd = clock.now()
checkNotNull(startupService).setSdkStartupInfo(sdkInitStart, sdkInitEnd)
checkNotNull(startupService).setSdkStartupInfo(sdkInitStart, sdkInitEnd, false, "main")
clock.tick(60001L)
appStartupTraceEmitter.startupActivityPreCreated()
val startupActivityPreCreated = clock.now()
Expand Down Expand Up @@ -446,7 +446,7 @@ internal class AppStartupTraceEmitterTest {
val sdkInitStart = clock.now()
clock.tick(30L)
val sdkInitEnd = clock.now()
checkNotNull(startupService).setSdkStartupInfo(sdkInitStart, sdkInitEnd)
checkNotNull(startupService).setSdkStartupInfo(sdkInitStart, sdkInitEnd, false, "main")
clock.tick(60001L)
appStartupTraceEmitter.startupActivityInitStart()
val startupActivityStart = clock.now()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import io.embrace.android.embracesdk.arch.assertIsTypePerformance
import io.embrace.android.embracesdk.concurrency.BlockableExecutorService
import io.embrace.android.embracesdk.fakes.FakeClock
import io.embrace.android.embracesdk.fakes.injection.FakeInitModule
import io.embrace.android.embracesdk.findSpanAttribute
import io.embrace.android.embracesdk.internal.clock.nanosToMillis
import io.embrace.android.embracesdk.internal.spans.SpanService
import io.embrace.android.embracesdk.internal.spans.SpanSink
Expand Down Expand Up @@ -41,7 +42,7 @@ internal class StartupServiceImplTest {
clock.tick(10L)
val endTimeMillis = clock.now()
spanService.initializeService(startTimeMillis)
startupService.setSdkStartupInfo(startTimeMillis, endTimeMillis)
startupService.setSdkStartupInfo(startTimeMillis, endTimeMillis, false, "main")
val currentSpans = spanSink.completedSpans()
assertEquals(1, currentSpans.size)
with(currentSpans[0]) {
Expand All @@ -52,29 +53,31 @@ internal class StartupServiceImplTest {
assertIsTypePerformance()
assertIsPrivateSpan()
assertEquals(StatusCode.OK, status)
assertEquals("false", findSpanAttribute("ended-in-foreground"))
assertEquals("main", findSpanAttribute("thread-name"))
}
}

@Test
fun `second sdk startup span will not be recorded if you try to set the startup info twice`() {
spanService.initializeService(10)
startupService.setSdkStartupInfo(10, 20)
startupService.setSdkStartupInfo(10, 20, false, "main")
assertEquals(1, spanSink.completedSpans().size)
startupService.setSdkStartupInfo(10, 20)
startupService.setSdkStartupInfo(10, 20)
startupService.setSdkStartupInfo(10, 20, false, "main")
startupService.setSdkStartupInfo(10, 20, false, "main")
assertEquals(1, spanSink.completedSpans().size)
}

@Test
fun `sdk startup span recorded if the startup info is set before span service initializes`() {
startupService.setSdkStartupInfo(10, 20)
startupService.setSdkStartupInfo(10, 20, false, "main")
spanService.initializeService(10)
assertEquals(1, spanSink.completedSpans().size)
}

@Test
fun `startup info available right after setting on the service`() {
startupService.setSdkStartupInfo(1111L, 3222L)
startupService.setSdkStartupInfo(1111L, 3222L, false, "main")
assertEquals(1111L, startupService.getSdkInitStartMs())
assertEquals(3222L, startupService.getSdkInitEndMs())
assertEquals(2111L, startupService.getSdkStartupDuration(true))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,13 @@ import io.embrace.android.embracesdk.capture.startup.StartupService
internal class FakeStartupService : StartupService {

var sdkStartupDuration: Long? = null
var endedInForeground: Boolean? = null
var threadName: String? = null

override fun setSdkStartupInfo(startTimeMs: Long, endTimeMs: Long) {
override fun setSdkStartupInfo(startTimeMs: Long, endTimeMs: Long, endedInForeground: Boolean, threadName: String?) {
sdkStartupDuration = endTimeMs - startTimeMs
this.endedInForeground = endedInForeground
this.threadName = threadName
}

override fun getSdkStartupDuration(coldStart: Boolean): Long? {
Expand Down

0 comments on commit 516809c

Please sign in to comment.