Skip to content

Commit 9578eab

Browse files
authored
Fix add missing thread name/id to app start spans (#3226)
* Fix add missing thread name/id to app start spans * Update Changelog
1 parent aa91b8f commit 9578eab

File tree

3 files changed

+67
-1
lines changed

3 files changed

+67
-1
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
- Fix old profiles deletion on SDK init ([#3216](https://github.com/getsentry/sentry-java/pull/3216))
1414
- Fix hub restore point in wrappers: SentryWrapper, SentryTaskDecorator and SentryScheduleHook ([#3225](https://github.com/getsentry/sentry-java/pull/3225))
1515
- We now reset the hub to its previous value on the thread where the `Runnable`/`Callable`/`Supplier` is executed instead of setting it to the hub that was used on the thread where the `Runnable`/`Callable`/`Supplier` was created.
16+
- Fix add missing thread name/id to app start spans ([#3226](https://github.com/getsentry/sentry-java/pull/3226))
1617

1718
## 7.4.0
1819

sentry-android-core/src/main/java/io/sentry/android/core/PerformanceAndroidEventProcessor.java

+8-1
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,13 @@
44
import static io.sentry.android.core.ActivityLifecycleIntegration.APP_START_WARM;
55
import static io.sentry.android.core.ActivityLifecycleIntegration.UI_LOAD_OP;
66

7+
import android.os.Looper;
78
import io.sentry.EventProcessor;
89
import io.sentry.Hint;
910
import io.sentry.MeasurementUnit;
1011
import io.sentry.SentryEvent;
1112
import io.sentry.SpanContext;
13+
import io.sentry.SpanDataConvention;
1214
import io.sentry.SpanId;
1315
import io.sentry.SpanStatus;
1416
import io.sentry.android.core.performance.ActivityLifecycleTimeSpan;
@@ -231,6 +233,11 @@ private static SentrySpan timeSpanToSentrySpan(
231233
final @Nullable SpanId parentSpanId,
232234
final @NotNull SentryId traceId,
233235
final @NotNull String operation) {
236+
237+
final Map<String, Object> defaultSpanData = new HashMap<>(2);
238+
defaultSpanData.put(SpanDataConvention.THREAD_ID, Looper.getMainLooper().getThread().getId());
239+
defaultSpanData.put(SpanDataConvention.THREAD_NAME, "main");
240+
234241
return new SentrySpan(
235242
span.getStartTimestampSecs(),
236243
span.getProjectedStopTimestampSecs(),
@@ -242,6 +249,6 @@ private static SentrySpan timeSpanToSentrySpan(
242249
SpanStatus.OK,
243250
APP_METRICS_ORIGIN,
244251
new HashMap<>(),
245-
null);
252+
defaultSpanData);
246253
}
247254
}

sentry-android-core/src/test/java/io/sentry/android/core/PerformanceAndroidEventProcessorTest.kt

+58
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package io.sentry.android.core
22

33
import android.content.ContentProvider
4+
import androidx.test.ext.junit.runners.AndroidJUnit4
45
import io.sentry.Hint
56
import io.sentry.IHub
67
import io.sentry.MeasurementUnit
@@ -18,6 +19,7 @@ import io.sentry.android.core.performance.AppStartMetrics.AppStartType
1819
import io.sentry.protocol.MeasurementValue
1920
import io.sentry.protocol.SentrySpan
2021
import io.sentry.protocol.SentryTransaction
22+
import org.junit.runner.RunWith
2123
import org.mockito.kotlin.any
2224
import org.mockito.kotlin.mock
2325
import org.mockito.kotlin.whenever
@@ -27,6 +29,7 @@ import kotlin.test.assertEquals
2729
import kotlin.test.assertFalse
2830
import kotlin.test.assertTrue
2931

32+
@RunWith(AndroidJUnit4::class)
3033
class PerformanceAndroidEventProcessorTest {
3134

3235
private class Fixture {
@@ -398,6 +401,61 @@ class PerformanceAndroidEventProcessorTest {
398401
)
399402
}
400403

404+
@Test
405+
fun `adds main thread name and id to app start spans`() {
406+
// given some cold app start metrics
407+
// where class loaded happened way before app start
408+
val appStartMetrics = AppStartMetrics.getInstance()
409+
appStartMetrics.appStartType = AppStartType.COLD
410+
appStartMetrics.appStartTimeSpan.setStartedAt(1)
411+
appStartMetrics.appStartTimeSpan.setStoppedAt(3000)
412+
413+
AppStartMetrics.getInstance().applicationOnCreateTimeSpan.apply {
414+
setStartedAt(1000)
415+
description = "com.example.App.onCreate"
416+
setStoppedAt(2000)
417+
}
418+
419+
val sut = fixture.getSut(enablePerformanceV2 = true)
420+
val context = TransactionContext("Activity", UI_LOAD_OP)
421+
val tracer = SentryTracer(context, fixture.hub)
422+
var tr = SentryTransaction(tracer)
423+
val appStartSpan = SentrySpan(
424+
0.0,
425+
1.0,
426+
tr.contexts.trace!!.traceId,
427+
SpanId(),
428+
null,
429+
APP_START_COLD,
430+
"App Start",
431+
SpanStatus.OK,
432+
null,
433+
emptyMap(),
434+
null
435+
)
436+
tr.spans.add(appStartSpan)
437+
438+
// when the processor attaches the app start spans
439+
tr = sut.process(tr, Hint())
440+
441+
// thread name and id should be set
442+
assertTrue {
443+
tr.spans.any {
444+
it.op == "process.load" &&
445+
it.data!!["thread.name"] == "main" &&
446+
it.data!!.containsKey("thread.id")
447+
}
448+
}
449+
450+
assertTrue {
451+
tr.spans.any {
452+
it.op == "application.load" &&
453+
it.data!!["thread.name"] == "main" &&
454+
it.data!!.containsKey("thread.id")
455+
}
456+
}
457+
}
458+
401459
private fun setAppStart(options: SentryAndroidOptions, coldStart: Boolean = true) {
402460
AppStartMetrics.getInstance().apply {
403461
appStartType = when (coldStart) {

0 commit comments

Comments
 (0)