Skip to content

Commit d2af2a5

Browse files
committed
use opentelemetry-kotlin to capture span and log
1 parent b51e374 commit d2af2a5

File tree

10 files changed

+80
-38
lines changed

10 files changed

+80
-38
lines changed

gradle/libs.versions.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ detekt = "1.23.8"
2121
binaryCompatValidator = "0.18.1"
2222
fragment = "1.8.9"
2323
koverGradlePlugin = "0.9.2"
24+
opentelemetryKotlin = "0.5.1"
2425

2526
[libraries]
2627
opentelemetry-platform-alpha = { module = "io.opentelemetry.instrumentation:opentelemetry-instrumentation-bom-alpha", version.ref = "opentelemetry-instrumentation-alpha" }
@@ -56,6 +57,8 @@ auto-service-processor = { module = "dev.zacsweers.autoservice:auto-service-ksp"
5657
compose = { group = "androidx.compose.ui", name = "ui", version.ref = "compose" }
5758
detekt-plugin = { module = "io.gitlab.arturbosch.detekt:detekt-gradle-plugin", version.ref = "detekt" }
5859
binary-compat-validator = { module = "org.jetbrains.kotlinx:binary-compatibility-validator", version.ref = "binaryCompatValidator" }
60+
opentelemetry-kotlin = { group = "io.embrace.opentelemetry.kotlin", name = "opentelemetry-kotlin", version.ref = "opentelemetryKotlin" }
61+
opentelemetry-kotlin-compat = { group = "io.embrace.opentelemetry.kotlin", name = "opentelemetry-kotlin-compat", version.ref = "opentelemetryKotlin" }
5962

6063
#Test tools
6164
opentelemetry-sdk-testing = { module = "io.opentelemetry:opentelemetry-sdk-testing" }
@@ -75,6 +78,7 @@ assertj-core = "org.assertj:assertj-core:3.27.4"
7578
awaitility = "org.awaitility:awaitility:4.3.0"
7679
mockwebserver = "com.google.mockwebserver:mockwebserver:20130706"
7780
okhttp-mockwebserver = { module = "com.squareup.okhttp3:mockwebserver", version.ref = "okhttp" }
81+
opentelemetry-kotlin-testing = { group = "io.embrace.opentelemetry.kotlin", name = "opentelemetry-kotlin-testing", version.ref = "opentelemetryKotlin" }
7882

7983
#Compilation tools
8084
desugarJdkLibs = "com.android.tools:desugar_jdk_libs:2.1.5"

instrumentation/crash/build.gradle.kts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,7 @@ dependencies {
2828
implementation(libs.opentelemetry.instrumentation.api)
2929
testImplementation(libs.awaitility)
3030
testImplementation(libs.robolectric)
31+
32+
implementation(libs.opentelemetry.kotlin)
33+
implementation(libs.opentelemetry.kotlin.compat)
3134
}

instrumentation/crash/src/main/java/io/opentelemetry/android/instrumentation/crash/CrashReporter.kt

Lines changed: 29 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,13 @@
55

66
package io.opentelemetry.android.instrumentation.crash
77

8+
import io.embrace.opentelemetry.kotlin.ExperimentalApi
9+
import io.embrace.opentelemetry.kotlin.attributes.setAttributes
10+
import io.embrace.opentelemetry.kotlin.getLogger
11+
import io.embrace.opentelemetry.kotlin.toOtelKotlinApi
812
import io.opentelemetry.android.instrumentation.common.EventAttributesExtractor
913
import io.opentelemetry.api.common.Attributes
10-
import io.opentelemetry.api.incubator.logs.ExtendedLogRecordBuilder
14+
import io.opentelemetry.api.common.AttributesBuilder
1115
import io.opentelemetry.context.Context
1216
import io.opentelemetry.sdk.OpenTelemetrySdk
1317
import io.opentelemetry.semconv.ExceptionAttributes.EXCEPTION_MESSAGE
@@ -37,35 +41,42 @@ internal class CrashReporter(
3741
Thread.setDefaultUncaughtExceptionHandler(handler)
3842
}
3943

44+
@OptIn(ExperimentalApi::class)
4045
private fun processCrash(
4146
openTelemetry: OpenTelemetrySdk,
4247
crashDetails: CrashDetails,
4348
) {
44-
val logger = openTelemetry.sdkLoggerProvider.loggerBuilder("io.opentelemetry.crash").build()
49+
val otel = openTelemetry.toOtelKotlinApi()
50+
val logger = otel.getLogger("io.opentelemetry.crash")
4551
val throwable = crashDetails.cause
4652
val thread = crashDetails.thread
47-
val attributesBuilder =
48-
Attributes
49-
.builder()
50-
.put(THREAD_ID, thread.id)
51-
.put(THREAD_NAME, thread.name)
52-
.put(EXCEPTION_MESSAGE, throwable.message)
53-
.put(
54-
EXCEPTION_STACKTRACE,
55-
throwable.stackTraceToString(),
56-
).put(EXCEPTION_TYPE, throwable.javaClass.name)
53+
54+
val attributesBuilder = Attributes.builder()
5755
for (extractor in extractors) {
5856
val extractedAttributes = extractor.extract(Context.current(), crashDetails)
5957
attributesBuilder.putAll(extractedAttributes)
6058
}
61-
val eventBuilder =
62-
logger.logRecordBuilder() as ExtendedLogRecordBuilder
63-
eventBuilder
64-
.setEventName("device.crash")
65-
.setAllAttributes(attributesBuilder.build())
66-
.emit()
59+
60+
logger.log(body = "device.crash") {
61+
// event name not supported yet. Use body as an example instead.
62+
setAttributes(
63+
mapOf<String, Any>(
64+
THREAD_ID.key to thread.id,
65+
THREAD_NAME.key to thread.name,
66+
EXCEPTION_STACKTRACE.key to throwable.stackTraceToString(),
67+
EXCEPTION_TYPE.key to throwable.javaClass.name,
68+
),
69+
)
70+
setAttributes(attributesBuilder.toMap())
71+
72+
throwable.message?.let {
73+
setStringAttribute(EXCEPTION_MESSAGE.key, it)
74+
}
75+
}
6776
}
6877

78+
private fun AttributesBuilder.toMap(): Map<String, Any> = build().asMap().mapKeys { (k, _) -> k.key }
79+
6980
private fun waitForCrashFlush(openTelemetry: OpenTelemetrySdk) {
7081
val flushResult = openTelemetry.sdkLoggerProvider.forceFlush()
7182
flushResult.join(10, TimeUnit.SECONDS)

instrumentation/crash/src/test/java/io/opentelemetry/android/instrumentation/crash/CrashReportIntegrationTest.kt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,6 @@ internal class CrashReportIntegrationTest {
187187
expectedExcType: String,
188188
expectedExcMessage: String? = null,
189189
) {
190-
assertEquals("device.crash", eventName)
191190
assertEquals(Severity.UNDEFINED_SEVERITY_NUMBER, severity)
192191

193192
val attrs = attributes.asMap().mapKeys { it.key.key }

instrumentation/slowrendering/build.gradle.kts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ dependencies {
2727
implementation(libs.androidx.core)
2828
implementation(libs.opentelemetry.semconv)
2929
implementation(libs.opentelemetry.sdk)
30+
implementation(libs.opentelemetry.kotlin)
31+
implementation(libs.opentelemetry.kotlin.compat)
3032
implementation(libs.opentelemetry.instrumentation.api)
3133
implementation(libs.opentelemetry.sdk.extension.incubator)
3234
testImplementation(libs.robolectric)

instrumentation/slowrendering/src/main/java/io/opentelemetry/android/instrumentation/slowrendering/SlowRenderingInstrumentation.kt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ package io.opentelemetry.android.instrumentation.slowrendering
88
import android.os.Build
99
import android.util.Log
1010
import com.google.auto.service.AutoService
11+
import io.embrace.opentelemetry.kotlin.ExperimentalApi
12+
import io.embrace.opentelemetry.kotlin.getTracer
13+
import io.embrace.opentelemetry.kotlin.toOtelKotlinApi
1114
import io.opentelemetry.android.common.RumConstants
1215
import io.opentelemetry.android.instrumentation.AndroidInstrumentation
1316
import io.opentelemetry.android.instrumentation.InstallationContext
@@ -64,6 +67,7 @@ class SlowRenderingInstrumentation : AndroidInstrumentation {
6467
return this
6568
}
6669

70+
@OptIn(ExperimentalApi::class)
6771
override fun install(ctx: InstallationContext) {
6872
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
6973
Log.w(
@@ -85,7 +89,8 @@ class SlowRenderingInstrumentation : AndroidInstrumentation {
8589
jankReporter = jankReporter.combine(EventJankReporter(logger, FROZEN_THRESHOLD_MS / 1000.0, debugVerbose))
8690

8791
if (useDeprecatedSpan) {
88-
val tracer = ctx.openTelemetry.getTracer("io.opentelemetry.slow-rendering")
92+
val otel = ctx.openTelemetry.toOtelKotlinApi()
93+
val tracer = otel.getTracer("io.opentelemetry.slow-rendering")
8994
jankReporter = jankReporter.combine(SpanBasedJankReporter(tracer))
9095
}
9196

instrumentation/slowrendering/src/main/java/io/opentelemetry/android/instrumentation/slowrendering/SpanBasedJankReporter.kt

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,16 @@
66
package io.opentelemetry.android.instrumentation.slowrendering
77

88
import android.util.Log
9+
import io.embrace.opentelemetry.kotlin.ExperimentalApi
10+
import io.embrace.opentelemetry.kotlin.tracing.Tracer
911
import io.opentelemetry.android.common.RumConstants
10-
import io.opentelemetry.api.trace.Span
11-
import io.opentelemetry.api.trace.Tracer
1212
import java.time.Instant
13+
import java.util.concurrent.TimeUnit
1314

1415
internal const val SLOW_THRESHOLD_MS = 16
1516
internal const val FROZEN_THRESHOLD_MS = 700
1617

18+
@OptIn(ExperimentalApi::class)
1719
internal class SpanBasedJankReporter(
1820
private val tracer: Tracer,
1921
) : JankReporter {
@@ -57,13 +59,13 @@ internal class SpanBasedJankReporter(
5759
slowCount: Int,
5860
now: Instant,
5961
) {
60-
val span: Span =
61-
tracer
62-
.spanBuilder(spanName)
63-
.setAttribute("count", slowCount.toLong())
64-
.setAttribute("activity.name", activityName)
65-
.setStartTimestamp(now)
66-
.startSpan()
67-
span.end(now)
62+
val span =
63+
tracer.createSpan(spanName, startTimestamp = now.toNanoSeconds()) {
64+
setLongAttribute("count", slowCount.toLong())
65+
setStringAttribute("activity.name", activityName)
66+
}
67+
span.end(now.toNanoSeconds())
6868
}
69+
70+
private fun Instant.toNanoSeconds(): Long = TimeUnit.MILLISECONDS.convert(toEpochMilli(), TimeUnit.NANOSECONDS)
6971
}

instrumentation/slowrendering/src/test/java/io/opentelemetry/android/instrumentation/slowrendering/SlowRenderListenerTest.java

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,11 @@
2525
import android.os.Handler;
2626
import android.view.FrameMetrics;
2727
import androidx.test.ext.junit.runners.AndroidJUnit4;
28+
import io.embrace.opentelemetry.kotlin.OpenTelemetryExtKt;
29+
import io.embrace.opentelemetry.kotlin.OtelJavaOpenTelemetryExtKt;
30+
import io.embrace.opentelemetry.kotlin.tracing.Tracer;
31+
import io.opentelemetry.api.OpenTelemetry;
2832
import io.opentelemetry.api.common.AttributeKey;
29-
import io.opentelemetry.api.trace.Tracer;
3033
import io.opentelemetry.sdk.testing.junit4.OpenTelemetryRule;
3134
import io.opentelemetry.sdk.trace.data.SpanData;
3235
import java.time.Duration;
@@ -122,7 +125,10 @@ public void addAndRemove() {
122125

123126
@Test
124127
public void removeWithMetrics() {
125-
Tracer tracer = otelTesting.getOpenTelemetry().getTracer("testTracer");
128+
OpenTelemetry openTelemetry = otelTesting.getOpenTelemetry();
129+
io.embrace.opentelemetry.kotlin.OpenTelemetry otelKotlin =
130+
OtelJavaOpenTelemetryExtKt.toOtelKotlinApi(openTelemetry);
131+
Tracer tracer = OpenTelemetryExtKt.getTracer(otelKotlin, "testTracer");
126132
jankReporter = new SpanBasedJankReporter(tracer);
127133
SlowRenderListener testInstance =
128134
new SlowRenderListener(
@@ -157,7 +163,10 @@ public void start() {
157163
.when(exec)
158164
.scheduleWithFixedDelay(any(), eq(1001L), eq(1001L), eq(TimeUnit.MILLISECONDS));
159165

160-
Tracer tracer = otelTesting.getOpenTelemetry().getTracer("testTracer");
166+
OpenTelemetry openTelemetry = otelTesting.getOpenTelemetry();
167+
io.embrace.opentelemetry.kotlin.OpenTelemetry otelKotlin =
168+
OtelJavaOpenTelemetryExtKt.toOtelKotlinApi(openTelemetry);
169+
Tracer tracer = OpenTelemetryExtKt.getTracer(otelKotlin, "testTracer");
161170
jankReporter = new SpanBasedJankReporter(tracer);
162171
SlowRenderListener testInstance =
163172
new SlowRenderListener(

instrumentation/slowrendering/src/test/java/io/opentelemetry/android/instrumentation/slowrendering/SlowRenderingInstrumentationTest.kt

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ package io.opentelemetry.android.instrumentation.slowrendering
77

88
import android.app.Application
99
import androidx.test.ext.junit.runners.AndroidJUnit4
10+
import io.embrace.opentelemetry.kotlin.ExperimentalApi
11+
import io.embrace.opentelemetry.kotlin.createCompatOpenTelemetry
12+
import io.embrace.opentelemetry.kotlin.toOtelJavaApi
1013
import io.mockk.Called
1114
import io.mockk.MockKAnnotations
1215
import io.mockk.Runs
@@ -100,16 +103,16 @@ class SlowRenderingInstrumentationTest {
100103
verify { application.registerActivityLifecycleCallbacks(capture(capturedListener)) }
101104
}
102105

106+
@OptIn(ExperimentalApi::class)
103107
@Config(sdk = [24, 25])
104108
@Test
105109
fun `can use legacy span`() {
106110
val capturedListener = slot<SlowRenderListener>()
107-
every { openTelemetry.getTracer(any()) }.returns(mockk())
111+
val otel = createCompatOpenTelemetry().toOtelJavaApi()
108112
every { application.registerActivityLifecycleCallbacks(any()) } just Runs
109-
val ctx = InstallationContext(application, openTelemetry, mockk())
113+
val ctx = InstallationContext(application, otel, mockk())
110114
slowRenderingInstrumentation.enableDeprecatedZeroDurationSpan().install(ctx)
111115

112-
verify { openTelemetry.getTracer("io.opentelemetry.slow-rendering") }
113116
verify { application.registerActivityLifecycleCallbacks(capture(capturedListener)) }
114117
}
115118
}

instrumentation/slowrendering/src/test/java/io/opentelemetry/android/instrumentation/slowrendering/SpanBasedJankReporterTest.kt

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,13 @@
66
package io.opentelemetry.android.instrumentation.slowrendering
77

88
import android.util.Log
9+
import io.embrace.opentelemetry.kotlin.ExperimentalApi
10+
import io.embrace.opentelemetry.kotlin.getTracer
11+
import io.embrace.opentelemetry.kotlin.toOtelKotlinApi
12+
import io.embrace.opentelemetry.kotlin.tracing.Tracer
913
import io.mockk.every
1014
import io.mockk.mockkStatic
1115
import io.opentelemetry.api.common.AttributeKey
12-
import io.opentelemetry.api.trace.Tracer
1316
import io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions
1417
import io.opentelemetry.sdk.testing.junit4.OpenTelemetryRule
1518
import io.opentelemetry.sdk.trace.data.SpanData
@@ -21,6 +24,7 @@ import org.junit.jupiter.api.Test
2124

2225
private val COUNT_KEY = AttributeKey.longKey("count")
2326

27+
@OptIn(ExperimentalApi::class)
2428
class SpanBasedJankReporterTest {
2529
private lateinit var tracer: Tracer
2630

@@ -29,7 +33,7 @@ class SpanBasedJankReporterTest {
2933

3034
@BeforeEach
3135
fun setup() {
32-
tracer = otelTesting.openTelemetry.getTracer("testTracer")
36+
tracer = otelTesting.openTelemetry.toOtelKotlinApi().getTracer("testTracer")
3337
}
3438

3539
@Test

0 commit comments

Comments
 (0)