Skip to content

Commit

Permalink
Make RxJava2 instrumentation Android-friendly (#7895)
Browse files Browse the repository at this point in the history
Resolves #7894

Replace `MethodHandle` with older `java.lang.reflect.Field`, which is
supported on older Java versions.

Also enables animal sniffer for the RxJava2 instrumentation to prevent
regression.

---------

Co-authored-by: opentelemetrybot <107717825+opentelemetrybot@users.noreply.github.com>
  • Loading branch information
bherbst and opentelemetrybot authored Feb 24, 2023
1 parent cb095e6 commit ba9df3f
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 14 deletions.
1 change: 1 addition & 0 deletions instrumentation/rxjava/rxjava-2.0/library/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
plugins {
id("otel.library-instrumentation")
id("otel.animalsniffer-conventions")
}

dependencies {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,10 @@
import io.reactivex.Observer;
import io.reactivex.internal.fuseable.QueueDisposable;
import io.reactivex.internal.observers.BasicFuseableObserver;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.reflect.Field;

class TracingObserver<T> extends BasicFuseableObserver<T, T> {
private static final MethodHandle queueDisposableGetter = getQueueDisposableGetter();
private static final Field queueDisposableField = getQueueDisposableField();

// BasicFuseableObserver#actual has been renamed to downstream in newer versions, we can't use it
// in this class
Expand Down Expand Up @@ -81,34 +80,35 @@ public T poll() throws Exception {
return getQueueDisposable().poll();
}

@SuppressWarnings("unchecked")
private QueueDisposable<T> getQueueDisposable() {
try {
return (QueueDisposable<T>) queueDisposableGetter.invoke(this);
return (QueueDisposable<T>) queueDisposableField.get(this);
} catch (Throwable throwable) {
throw new IllegalStateException(throwable);
}
}

private static MethodHandle getGetterHandle(String fieldName) {
private static Field getField(String fieldName) {

try {
return MethodHandles.lookup()
.findGetter(BasicFuseableObserver.class, fieldName, QueueDisposable.class);
} catch (NoSuchFieldException | IllegalAccessException ignored) {
return BasicFuseableObserver.class.getDeclaredField(fieldName);
} catch (NoSuchFieldException ignored) {
// Ignore
}
return null;
}

private static MethodHandle getQueueDisposableGetter() {
MethodHandle getter = getGetterHandle("qd");
if (getter == null) {
private static Field getQueueDisposableField() {
Field queueDisposableField = getField("qd");
if (queueDisposableField == null) {
// in versions before 2.2.1 field was named "qs"
getter = getGetterHandle("qs");
queueDisposableField = getField("qs");
}
return getter;
return queueDisposableField;
}

public static boolean canEnable() {
return queueDisposableGetter != null;
return queueDisposableField != null;
}
}

0 comments on commit ba9df3f

Please sign in to comment.