Skip to content

Commit 33e402f

Browse files
authored
Add event attribute extractor (#1104)
* wire up EventAttributesExtractor to ANRs * wire up EventAttributesExtractor to crash instrumentation, fix tests. * fix javadoc
1 parent aebf0e1 commit 33e402f

13 files changed

Lines changed: 70 additions & 47 deletions

File tree

android-agent/src/main/kotlin/io/opentelemetry/android/agent/OpenTelemetryRumInitializer.kt

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import io.opentelemetry.android.instrumentation.AndroidInstrumentation
1818
import io.opentelemetry.android.instrumentation.AndroidInstrumentationLoader
1919
import io.opentelemetry.android.instrumentation.activity.ActivityLifecycleInstrumentation
2020
import io.opentelemetry.android.instrumentation.anr.AnrInstrumentation
21+
import io.opentelemetry.android.instrumentation.common.EventAttributesExtractor
2122
import io.opentelemetry.android.instrumentation.common.ScreenNameExtractor
2223
import io.opentelemetry.android.instrumentation.crash.CrashDetails
2324
import io.opentelemetry.android.instrumentation.crash.CrashReporterInstrumentation
@@ -31,7 +32,6 @@ import io.opentelemetry.api.trace.Tracer
3132
import io.opentelemetry.exporter.otlp.http.logs.OtlpHttpLogRecordExporter
3233
import io.opentelemetry.exporter.otlp.http.metrics.OtlpHttpMetricExporter
3334
import io.opentelemetry.exporter.otlp.http.trace.OtlpHttpSpanExporter
34-
import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor
3535
import java.time.Duration
3636

3737
object OpenTelemetryRumInitializer {
@@ -81,8 +81,8 @@ object OpenTelemetryRumInitializer {
8181
activityNameExtractor: ScreenNameExtractor? = null,
8282
fragmentTracerCustomizer: ((Tracer) -> Tracer)? = null,
8383
fragmentNameExtractor: ScreenNameExtractor? = null,
84-
anrAttributesExtractors: List<AttributesExtractor<Array<StackTraceElement>, Void>> = emptyList(),
85-
crashAttributesExtractors: List<AttributesExtractor<CrashDetails, Void>> = emptyList(),
84+
anrAttributesExtractors: List<EventAttributesExtractor<Array<StackTraceElement>>> = emptyList(),
85+
crashAttributesExtractors: List<EventAttributesExtractor<CrashDetails>> = emptyList(),
8686
networkChangeAttributesExtractors: List<NetworkAttributesExtractor> = emptyList(),
8787
slowRenderingDetectionPollInterval: Duration? = null,
8888
): OpenTelemetryRum {
@@ -135,8 +135,8 @@ object OpenTelemetryRumInitializer {
135135
activityNameExtractor: ScreenNameExtractor?,
136136
fragmentTracerCustomizer: ((Tracer) -> Tracer)?,
137137
fragmentNameExtractor: ScreenNameExtractor?,
138-
anrAttributesExtractors: List<AttributesExtractor<Array<StackTraceElement>, Void>>,
139-
crashAttributesExtractors: List<AttributesExtractor<CrashDetails, Void>>,
138+
anrAttributesExtractors: List<EventAttributesExtractor<Array<StackTraceElement>>>,
139+
crashAttributesExtractors: List<EventAttributesExtractor<CrashDetails>>,
140140
networkChangeAttributesExtractors: List<NetworkAttributesExtractor>,
141141
slowRenderingDetectionPollInterval: Duration?,
142142
) {

instrumentation/anr/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ android {
2020
dependencies {
2121
api(project(":instrumentation:android-instrumentation"))
2222
implementation(project(":services"))
23+
implementation(project(":instrumentation:common-api"))
2324
api(platform(libs.opentelemetry.platform.alpha))
2425
api(libs.opentelemetry.api)
2526
implementation(libs.androidx.core)

instrumentation/anr/src/main/java/io/opentelemetry/android/instrumentation/anr/AnrDetector.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,23 +7,23 @@
77

88
import android.os.Handler;
99
import android.os.Looper;
10+
import io.opentelemetry.android.instrumentation.common.EventAttributesExtractor;
1011
import io.opentelemetry.android.internal.services.applifecycle.AppLifecycle;
1112
import io.opentelemetry.api.OpenTelemetry;
1213
import io.opentelemetry.api.logs.Logger;
13-
import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor;
1414
import java.util.List;
1515
import java.util.concurrent.ScheduledExecutorService;
1616

1717
/** Entrypoint for installing the ANR (application not responding) detection instrumentation. */
1818
public final class AnrDetector {
19-
private final List<AttributesExtractor<StackTraceElement[], Void>> additionalExtractors;
19+
private final List<EventAttributesExtractor<StackTraceElement[]>> additionalExtractors;
2020
private final Looper mainLooper;
2121
private final ScheduledExecutorService scheduler;
2222
private final AppLifecycle appLifecycle;
2323
private final OpenTelemetry openTelemetry;
2424

2525
AnrDetector(
26-
List<AttributesExtractor<StackTraceElement[], Void>> additionalExtractors,
26+
List<EventAttributesExtractor<StackTraceElement[]>> additionalExtractors,
2727
Looper mainLooper,
2828
ScheduledExecutorService scheduler,
2929
AppLifecycle appLifecycle,

instrumentation/anr/src/main/java/io/opentelemetry/android/instrumentation/anr/AnrInstrumentation.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@
1010
import com.google.auto.service.AutoService;
1111
import io.opentelemetry.android.instrumentation.AndroidInstrumentation;
1212
import io.opentelemetry.android.instrumentation.InstallationContext;
13+
import io.opentelemetry.android.instrumentation.common.EventAttributesExtractor;
1314
import io.opentelemetry.android.internal.services.Services;
14-
import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor;
1515
import java.util.ArrayList;
1616
import java.util.List;
1717
import java.util.concurrent.Executors;
@@ -22,14 +22,14 @@
2222
public final class AnrInstrumentation implements AndroidInstrumentation {
2323

2424
public static final String INSTRUMENTATION_NAME = "anr";
25-
final List<AttributesExtractor<StackTraceElement[], Void>> additionalExtractors =
25+
final List<EventAttributesExtractor<StackTraceElement[]>> additionalExtractors =
2626
new ArrayList<>();
2727
Looper mainLooper = Looper.getMainLooper();
2828
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
2929

30-
/** Adds an {@link AttributesExtractor} that will extract additional attributes. */
30+
/** Adds an {@link EventAttributesExtractor} that will extract additional attributes. */
3131
public AnrInstrumentation addAttributesExtractor(
32-
AttributesExtractor<StackTraceElement[], Void> extractor) {
32+
EventAttributesExtractor<StackTraceElement[]> extractor) {
3333
additionalExtractors.add(extractor);
3434
return this;
3535
}

instrumentation/anr/src/main/java/io/opentelemetry/android/instrumentation/anr/AnrWatcher.kt

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@
66
package io.opentelemetry.android.instrumentation.anr
77

88
import android.os.Handler
9+
import io.opentelemetry.android.instrumentation.common.EventAttributesExtractor
910
import io.opentelemetry.api.common.Attributes
1011
import io.opentelemetry.api.incubator.logs.ExtendedLogRecordBuilder
1112
import io.opentelemetry.api.logs.Logger
1213
import io.opentelemetry.context.Context
13-
import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor
1414
import io.opentelemetry.semconv.ExceptionAttributes.EXCEPTION_STACKTRACE
1515
import io.opentelemetry.semconv.incubating.ThreadIncubatingAttributes.THREAD_ID
1616
import io.opentelemetry.semconv.incubating.ThreadIncubatingAttributes.THREAD_NAME
@@ -32,7 +32,7 @@ internal class AnrWatcher(
3232
private val uiHandler: Handler,
3333
private val mainThread: Thread,
3434
private val anrLogger: Logger,
35-
private val additionalExtractors: List<AttributesExtractor<Array<StackTraceElement>, Void>>,
35+
private val additionalExtractors: List<EventAttributesExtractor<Array<StackTraceElement>>>,
3636
private val pollDurationNs: Long = DEFAULT_POLL_DURATION_NS,
3737
) : Runnable {
3838
private val anrCounter = AtomicInteger()
@@ -45,7 +45,7 @@ internal class AnrWatcher(
4545
uiHandler: Handler,
4646
mainThread: Thread,
4747
anrLogger: Logger,
48-
additionalExtractors: List<AttributesExtractor<Array<StackTraceElement>, Void>>,
48+
additionalExtractors: List<EventAttributesExtractor<Array<StackTraceElement>>>,
4949
) :
5050
this(uiHandler, mainThread, anrLogger, additionalExtractors, DEFAULT_POLL_DURATION_NS)
5151

@@ -82,7 +82,8 @@ internal class AnrWatcher(
8282
.put(EXCEPTION_STACKTRACE, stackTraceToString(stackTrace))
8383

8484
for (extractor in additionalExtractors) {
85-
extractor.onStart(attributesBuilder, Context.current(), stackTrace)
85+
val extractedAttributes = extractor.extract(Context.current(), stackTrace)
86+
attributesBuilder.putAll(extractedAttributes)
8687
}
8788

8889
val eventBuilder = anrLogger.logRecordBuilder() as ExtendedLogRecordBuilder

instrumentation/anr/src/test/java/io/opentelemetry/android/instrumentation/anr/AnrDetectorTest.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,16 @@
66
package io.opentelemetry.android.instrumentation.anr;
77

88
import static io.opentelemetry.api.common.AttributeKey.stringKey;
9-
import static io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor.constant;
109
import static org.mockito.ArgumentMatchers.eq;
1110
import static org.mockito.ArgumentMatchers.isA;
1211
import static org.mockito.Mockito.verify;
1312
import static org.mockito.Mockito.when;
1413

1514
import android.os.Looper;
15+
import io.opentelemetry.android.instrumentation.common.EventAttributesExtractor;
1616
import io.opentelemetry.android.internal.services.applifecycle.AppLifecycle;
1717
import io.opentelemetry.api.OpenTelemetry;
18+
import io.opentelemetry.api.common.Attributes;
1819
import io.opentelemetry.sdk.OpenTelemetrySdk;
1920
import java.util.Collections;
2021
import java.util.concurrent.ScheduledExecutorService;
@@ -36,9 +37,11 @@ void shouldInstallInstrumentation() {
3637
when(mainLooper.getThread()).thenReturn(new Thread());
3738
OpenTelemetry openTelemetry = OpenTelemetrySdk.builder().build();
3839

40+
EventAttributesExtractor<StackTraceElement[]> extractor =
41+
(parentContext, o) -> Attributes.of(stringKey("test.key"), "abc");
3942
AnrDetector anrDetector =
4043
new AnrDetector(
41-
Collections.singletonList(constant(stringKey("test.key"), "abc")),
44+
Collections.singletonList(extractor),
4245
mainLooper,
4346
scheduler,
4447
appLifecycle,
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.android.instrumentation.common
7+
8+
import io.opentelemetry.api.common.Attributes
9+
import io.opentelemetry.context.Context
10+
11+
/**
12+
* Extractor of point-in-time attributes. Whereas the AttributesExtractor in the
13+
* upstream instrumentation api is targeted at tracing/spans (onStart, onEnd),
14+
* this extractor operates purely on the parentContext and a generic SUBJECT
15+
* at a point in time. The resulting Attributes will all be added to the event
16+
* that is being generated.
17+
*/
18+
interface EventAttributesExtractor<SUBJECT> {
19+
fun extract(
20+
parentContext: Context,
21+
subject: SUBJECT,
22+
): Attributes
23+
}

instrumentation/crash/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ dependencies {
1818
implementation(project(":common"))
1919
implementation(project(":services"))
2020
implementation(project(":session"))
21+
implementation(project(":instrumentation:common-api"))
2122
api(platform(libs.opentelemetry.platform.alpha))
2223
api(libs.opentelemetry.api)
2324
implementation(libs.androidx.core)

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

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,23 +11,23 @@
1111
import static io.opentelemetry.semconv.incubating.ThreadIncubatingAttributes.THREAD_ID;
1212
import static io.opentelemetry.semconv.incubating.ThreadIncubatingAttributes.THREAD_NAME;
1313

14+
import io.opentelemetry.android.instrumentation.common.EventAttributesExtractor;
1415
import io.opentelemetry.api.common.Attributes;
1516
import io.opentelemetry.api.common.AttributesBuilder;
1617
import io.opentelemetry.api.incubator.logs.ExtendedLogRecordBuilder;
1718
import io.opentelemetry.api.logs.Logger;
1819
import io.opentelemetry.api.logs.LoggerProvider;
1920
import io.opentelemetry.context.Context;
20-
import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor;
2121
import io.opentelemetry.sdk.OpenTelemetrySdk;
2222
import java.io.PrintWriter;
2323
import java.io.StringWriter;
2424
import java.util.List;
2525
import java.util.function.Consumer;
2626

2727
public final class CrashReporter {
28-
private final List<AttributesExtractor<CrashDetails, Void>> additionalExtractors;
28+
private final List<EventAttributesExtractor<CrashDetails>> additionalExtractors;
2929

30-
public CrashReporter(List<AttributesExtractor<CrashDetails, Void>> additionalExtractors) {
30+
public CrashReporter(List<EventAttributesExtractor<CrashDetails>> additionalExtractors) {
3131
this.additionalExtractors = additionalExtractors;
3232
}
3333

@@ -55,8 +55,9 @@ private void emitCrashEvent(Logger crashReporter, CrashDetails crashDetails) {
5555
.put(EXCEPTION_STACKTRACE, stackTraceToString(throwable))
5656
.put(EXCEPTION_TYPE, throwable.getClass().getName());
5757

58-
for (AttributesExtractor<CrashDetails, Void> extractor : additionalExtractors) {
59-
extractor.onStart(attributesBuilder, Context.current(), crashDetails);
58+
for (EventAttributesExtractor<CrashDetails> extractor : additionalExtractors) {
59+
Attributes extractedAttributes = extractor.extract(Context.current(), crashDetails);
60+
attributesBuilder.putAll(extractedAttributes);
6061
}
6162

6263
ExtendedLogRecordBuilder eventBuilder =

instrumentation/crash/src/main/java/io/opentelemetry/android/instrumentation/crash/CrashReporterInstrumentation.java

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,9 @@
77

88
import androidx.annotation.NonNull;
99
import com.google.auto.service.AutoService;
10-
import io.opentelemetry.android.common.RuntimeDetailsExtractor;
1110
import io.opentelemetry.android.instrumentation.AndroidInstrumentation;
1211
import io.opentelemetry.android.instrumentation.InstallationContext;
13-
import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor;
12+
import io.opentelemetry.android.instrumentation.common.EventAttributesExtractor;
1413
import io.opentelemetry.sdk.OpenTelemetrySdk;
1514
import java.util.ArrayList;
1615
import java.util.List;
@@ -19,11 +18,11 @@
1918
@AutoService(AndroidInstrumentation.class)
2019
public final class CrashReporterInstrumentation implements AndroidInstrumentation {
2120
private static final String INSTRUMENTATION_NAME = "crash";
22-
private final List<AttributesExtractor<CrashDetails, Void>> additionalExtractors =
21+
private final List<EventAttributesExtractor<CrashDetails>> additionalExtractors =
2322
new ArrayList<>();
2423

25-
/** Adds an {@link AttributesExtractor} that will extract additional attributes. */
26-
public void addAttributesExtractor(AttributesExtractor<CrashDetails, Void> extractor) {
24+
/** Adds an {@link EventAttributesExtractor} that will extract additional attributes. */
25+
public void addAttributesExtractor(EventAttributesExtractor<CrashDetails> extractor) {
2726
additionalExtractors.add(extractor);
2827
}
2928

0 commit comments

Comments
 (0)