Skip to content

Commit 75a3429

Browse files
authored
make elasticsearch indy-ready (#14672)
1 parent 626c296 commit 75a3429

File tree

17 files changed

+423
-219
lines changed

17 files changed

+423
-219
lines changed

instrumentation/elasticsearch/elasticsearch-api-client-7.16/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/apiclient/ElasticsearchApiClientInstrumentationModule.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,4 +42,9 @@ public List<TypeInstrumentation> typeInstrumentations() {
4242
return asList(
4343
new RestClientTransportInstrumentation(), new RestClientHttpClientInstrumentation());
4444
}
45+
46+
@Override
47+
public boolean isIndyReady() {
48+
return true;
49+
}
4550
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.javaagent.instrumentation.elasticsearch.apiclient;
7+
8+
import io.opentelemetry.instrumentation.api.util.VirtualField;
9+
import io.opentelemetry.instrumentation.elasticsearch.rest.common.v5_0.internal.ElasticsearchEndpointDefinition;
10+
import org.elasticsearch.client.Request;
11+
12+
public class ElasticsearchApiClientSingletons {
13+
14+
public static final VirtualField<Request, ElasticsearchEndpointDefinition> ENDPOINT_DEFINITION =
15+
VirtualField.find(Request.class, ElasticsearchEndpointDefinition.class);
16+
17+
private ElasticsearchApiClientSingletons() {}
18+
}

instrumentation/elasticsearch/elasticsearch-api-client-7.16/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/apiclient/RestClientHttpClientInstrumentation.java

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
package io.opentelemetry.javaagent.instrumentation.elasticsearch.apiclient;
77

8+
import static io.opentelemetry.javaagent.instrumentation.elasticsearch.apiclient.ElasticsearchApiClientSingletons.ENDPOINT_DEFINITION;
89
import static net.bytebuddy.matcher.ElementMatchers.isMethod;
910
import static net.bytebuddy.matcher.ElementMatchers.named;
1011
import static net.bytebuddy.matcher.ElementMatchers.namedOneOf;
@@ -13,8 +14,6 @@
1314

1415
import io.opentelemetry.context.Context;
1516
import io.opentelemetry.context.Scope;
16-
import io.opentelemetry.instrumentation.api.util.VirtualField;
17-
import io.opentelemetry.instrumentation.elasticsearch.rest.common.v5_0.internal.ElasticsearchEndpointDefinition;
1817
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
1918
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
2019
import net.bytebuddy.asm.Advice;
@@ -72,8 +71,7 @@ public static void onExit(@Advice.Return Request request) {
7271
if (endpointId.startsWith("es/") && endpointId.length() > 3) {
7372
endpointId = endpointId.substring(3);
7473
}
75-
VirtualField.find(Request.class, ElasticsearchEndpointDefinition.class)
76-
.set(request, ElasticsearchEndpointMap.get(endpointId));
74+
ENDPOINT_DEFINITION.set(request, ElasticsearchEndpointMap.get(endpointId));
7775
}
7876
}
7977
}

instrumentation/elasticsearch/elasticsearch-api-client-7.16/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/apiclient/RestClientTransportInstrumentation.java

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,13 @@
55

66
package io.opentelemetry.javaagent.instrumentation.elasticsearch.apiclient;
77

8+
import static io.opentelemetry.javaagent.instrumentation.elasticsearch.apiclient.ElasticsearchApiClientSingletons.ENDPOINT_DEFINITION;
89
import static net.bytebuddy.matcher.ElementMatchers.isMethod;
910
import static net.bytebuddy.matcher.ElementMatchers.named;
1011
import static net.bytebuddy.matcher.ElementMatchers.returns;
1112
import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
1213

1314
import co.elastic.clients.transport.Endpoint;
14-
import io.opentelemetry.instrumentation.api.util.VirtualField;
15-
import io.opentelemetry.instrumentation.elasticsearch.rest.common.v5_0.internal.ElasticsearchEndpointDefinition;
1615
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
1716
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
1817
import net.bytebuddy.asm.Advice;
@@ -44,13 +43,11 @@ public static class RestClientTransportAdvice {
4443
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
4544
public static void onPrepareLowLevelRequest(
4645
@Advice.Argument(1) Endpoint<?, ?, ?> endpoint, @Advice.Return Request request) {
47-
VirtualField<Request, ElasticsearchEndpointDefinition> virtualField =
48-
VirtualField.find(Request.class, ElasticsearchEndpointDefinition.class);
4946
String endpointId = endpoint.id();
5047
if (endpointId.startsWith("es/") && endpointId.length() > 3) {
5148
endpointId = endpointId.substring(3);
5249
}
53-
virtualField.set(request, ElasticsearchEndpointMap.get(endpointId));
50+
ENDPOINT_DEFINITION.set(request, ElasticsearchEndpointMap.get(endpointId));
5451
}
5552
}
5653
}

instrumentation/elasticsearch/elasticsearch-rest-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/rest/v5_0/ElasticsearchRest5InstrumentationModule.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,12 @@
1010
import com.google.auto.service.AutoService;
1111
import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule;
1212
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
13+
import io.opentelemetry.javaagent.extension.instrumentation.internal.ExperimentalInstrumentationModule;
1314
import java.util.List;
1415

1516
@AutoService(InstrumentationModule.class)
16-
public class ElasticsearchRest5InstrumentationModule extends InstrumentationModule {
17+
public class ElasticsearchRest5InstrumentationModule extends InstrumentationModule
18+
implements ExperimentalInstrumentationModule {
1719
public ElasticsearchRest5InstrumentationModule() {
1820
super("elasticsearch-rest", "elasticsearch-rest-5.0", "elasticsearch");
1921
}
@@ -22,4 +24,9 @@ public ElasticsearchRest5InstrumentationModule() {
2224
public List<TypeInstrumentation> typeInstrumentations() {
2325
return singletonList(new RestClientInstrumentation());
2426
}
27+
28+
@Override
29+
public boolean isIndyReady() {
30+
return true;
31+
}
2532
}

instrumentation/elasticsearch/elasticsearch-rest-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/rest/v5_0/RestClientInstrumentation.java

Lines changed: 54 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,10 @@
1919
import io.opentelemetry.instrumentation.elasticsearch.rest.common.v5_0.internal.RestResponseListener;
2020
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
2121
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
22+
import javax.annotation.Nullable;
2223
import net.bytebuddy.asm.Advice;
24+
import net.bytebuddy.asm.Advice.AssignReturned;
25+
import net.bytebuddy.asm.Advice.AssignReturned.ToArguments.ToArgument;
2326
import net.bytebuddy.description.type.TypeDescription;
2427
import net.bytebuddy.matcher.ElementMatcher;
2528
import org.elasticsearch.client.ResponseListener;
@@ -45,45 +48,67 @@ public void transform(TypeTransformer transformer) {
4548
@SuppressWarnings("unused")
4649
public static class PerformRequestAsyncAdvice {
4750

48-
@Advice.OnMethodEnter(suppress = Throwable.class)
49-
public static void onEnter(
50-
@Advice.Argument(0) String method,
51-
@Advice.Argument(1) String endpoint,
52-
@Advice.Local("otelRequest") ElasticsearchRestRequest request,
53-
@Advice.Local("otelContext") Context context,
54-
@Advice.Local("otelScope") Scope scope,
55-
@Advice.Argument(value = 5, readOnly = false) ResponseListener responseListener) {
51+
public static class AdviceScope {
52+
private final ElasticsearchRestRequest request;
53+
private final Context parentContext;
54+
private final Context context;
55+
private final Scope scope;
56+
57+
private AdviceScope(
58+
ElasticsearchRestRequest request, Context parentContext, Context context, Scope scope) {
59+
this.request = request;
60+
this.parentContext = parentContext;
61+
this.context = context;
62+
this.scope = scope;
63+
}
5664

57-
Context parentContext = currentContext();
58-
request = ElasticsearchRestRequest.create(method, endpoint);
59-
if (!instrumenter().shouldStart(parentContext, request)) {
60-
return;
65+
@Nullable
66+
public static AdviceScope start(ElasticsearchRestRequest request) {
67+
Context parentContext = currentContext();
68+
if (!instrumenter().shouldStart(parentContext, request)) {
69+
return null;
70+
}
71+
Context context = instrumenter().start(parentContext, request);
72+
return new AdviceScope(request, parentContext, context, context.makeCurrent());
6173
}
6274

63-
context = instrumenter().start(parentContext, request);
64-
scope = context.makeCurrent();
75+
public RestResponseListener wrapListener(ResponseListener listener) {
76+
return new RestResponseListener(listener, parentContext, instrumenter(), context, request);
77+
}
6578

66-
responseListener =
67-
new RestResponseListener(
68-
responseListener, parentContext, instrumenter(), context, request);
79+
public void end(@Nullable Throwable throwable) {
80+
scope.close();
81+
if (throwable != null) {
82+
instrumenter().end(context, request, null, throwable);
83+
}
84+
// span ended in RestResponseListener
85+
}
6986
}
7087

71-
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
72-
public static void stopSpan(
73-
@Advice.Thrown Throwable throwable,
74-
@Advice.Local("otelRequest") ElasticsearchRestRequest request,
75-
@Advice.Local("otelContext") Context context,
76-
@Advice.Local("otelScope") Scope scope) {
88+
@AssignReturned.ToArguments(@ToArgument(value = 5, index = 1))
89+
@Advice.OnMethodEnter(suppress = Throwable.class)
90+
public static Object[] onEnter(
91+
@Advice.Argument(0) String method,
92+
@Advice.Argument(1) String endpoint,
93+
@Advice.Argument(5) ResponseListener originalResponseListener) {
94+
ResponseListener responseListener = originalResponseListener;
7795

78-
if (scope == null) {
79-
return;
96+
ElasticsearchRestRequest request = ElasticsearchRestRequest.create(method, endpoint);
97+
AdviceScope adviceScope = AdviceScope.start(request);
98+
if (adviceScope == null) {
99+
return new Object[] {null, responseListener};
80100
}
81-
scope.close();
101+
responseListener = adviceScope.wrapListener(responseListener);
102+
return new Object[] {adviceScope, responseListener};
103+
}
82104

83-
if (throwable != null) {
84-
instrumenter().end(context, request, null, throwable);
105+
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
106+
public static void stopSpan(
107+
@Advice.Thrown Throwable throwable, @Advice.Enter Object[] enterResult) {
108+
AdviceScope adviceScope = (AdviceScope) enterResult[0];
109+
if (adviceScope != null) {
110+
adviceScope.end(throwable);
85111
}
86-
// span ended in RestResponseListener
87112
}
88113
}
89114
}

instrumentation/elasticsearch/elasticsearch-rest-6.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/rest/v6_4/ElasticsearchRest6InstrumentationModule.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,13 @@
1212
import com.google.auto.service.AutoService;
1313
import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule;
1414
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
15+
import io.opentelemetry.javaagent.extension.instrumentation.internal.ExperimentalInstrumentationModule;
1516
import java.util.List;
1617
import net.bytebuddy.matcher.ElementMatcher;
1718

1819
@AutoService(InstrumentationModule.class)
19-
public class ElasticsearchRest6InstrumentationModule extends InstrumentationModule {
20+
public class ElasticsearchRest6InstrumentationModule extends InstrumentationModule
21+
implements ExperimentalInstrumentationModule {
2022
public ElasticsearchRest6InstrumentationModule() {
2123
super("elasticsearch-rest", "elasticsearch-rest-6.4", "elasticsearch");
2224
}
@@ -31,4 +33,9 @@ public ElementMatcher.Junction<ClassLoader> classLoaderMatcher() {
3133
public List<TypeInstrumentation> typeInstrumentations() {
3234
return singletonList(new RestClientInstrumentation());
3335
}
36+
37+
@Override
38+
public boolean isIndyReady() {
39+
return true;
40+
}
3441
}

instrumentation/elasticsearch/elasticsearch-rest-6.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/rest/v6_4/RestClientInstrumentation.java

Lines changed: 54 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,10 @@
1818
import io.opentelemetry.instrumentation.elasticsearch.rest.common.v5_0.internal.RestResponseListener;
1919
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
2020
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
21+
import javax.annotation.Nullable;
2122
import net.bytebuddy.asm.Advice;
23+
import net.bytebuddy.asm.Advice.AssignReturned;
24+
import net.bytebuddy.asm.Advice.AssignReturned.ToArguments.ToArgument;
2225
import net.bytebuddy.description.type.TypeDescription;
2326
import net.bytebuddy.matcher.ElementMatcher;
2427
import org.elasticsearch.client.Request;
@@ -44,44 +47,67 @@ public void transform(TypeTransformer transformer) {
4447
@SuppressWarnings("unused")
4548
public static class PerformRequestAsyncAdvice {
4649

47-
@Advice.OnMethodEnter(suppress = Throwable.class)
48-
public static void onEnter(
49-
@Advice.Argument(0) Request request,
50-
@Advice.Argument(value = 1, readOnly = false) ResponseListener responseListener,
51-
@Advice.Local("otelRequest") ElasticsearchRestRequest otelRequest,
52-
@Advice.Local("otelContext") Context context,
53-
@Advice.Local("otelScope") Scope scope) {
50+
public static class AdviceScope {
51+
private final ElasticsearchRestRequest request;
52+
private final Context parentContext;
53+
private final Context context;
54+
private final Scope scope;
5455

55-
Context parentContext = currentContext();
56-
otelRequest = ElasticsearchRestRequest.create(request.getMethod(), request.getEndpoint());
57-
if (!instrumenter().shouldStart(parentContext, otelRequest)) {
58-
return;
56+
private AdviceScope(
57+
ElasticsearchRestRequest request, Context parentContext, Context context, Scope scope) {
58+
this.request = request;
59+
this.parentContext = parentContext;
60+
this.context = context;
61+
this.scope = scope;
5962
}
6063

61-
context = instrumenter().start(parentContext, otelRequest);
62-
scope = context.makeCurrent();
64+
@Nullable
65+
public static AdviceScope start(ElasticsearchRestRequest request) {
66+
Context parentContext = currentContext();
67+
if (!instrumenter().shouldStart(parentContext, request)) {
68+
return null;
69+
}
70+
Context context = instrumenter().start(parentContext, request);
71+
return new AdviceScope(request, parentContext, context, context.makeCurrent());
72+
}
6373

64-
responseListener =
65-
new RestResponseListener(
66-
responseListener, parentContext, instrumenter(), context, otelRequest);
74+
public RestResponseListener wrapListener(ResponseListener listener) {
75+
return new RestResponseListener(listener, parentContext, instrumenter(), context, request);
76+
}
77+
78+
public void end(@Nullable Throwable throwable) {
79+
scope.close();
80+
if (throwable != null) {
81+
instrumenter().end(context, request, null, throwable);
82+
}
83+
// span ended in RestResponseListener
84+
}
6785
}
6886

69-
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
70-
public static void stopSpan(
71-
@Advice.Thrown Throwable throwable,
72-
@Advice.Local("otelRequest") ElasticsearchRestRequest otelRequest,
73-
@Advice.Local("otelContext") Context context,
74-
@Advice.Local("otelScope") Scope scope) {
87+
@AssignReturned.ToArguments(@ToArgument(value = 1, index = 1))
88+
@Advice.OnMethodEnter(suppress = Throwable.class)
89+
public static Object[] onEnter(
90+
@Advice.Argument(0) Request request,
91+
@Advice.Argument(1) ResponseListener originalResponseListener) {
92+
ResponseListener responseListener = originalResponseListener;
7593

76-
if (scope == null) {
77-
return;
94+
ElasticsearchRestRequest otelRequest =
95+
ElasticsearchRestRequest.create(request.getMethod(), request.getEndpoint());
96+
AdviceScope adviceScope = AdviceScope.start(otelRequest);
97+
if (adviceScope == null) {
98+
return new Object[] {null, responseListener};
7899
}
79-
scope.close();
100+
responseListener = adviceScope.wrapListener(responseListener);
101+
return new Object[] {adviceScope, responseListener};
102+
}
80103

81-
if (throwable != null) {
82-
instrumenter().end(context, otelRequest, null, throwable);
104+
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
105+
public static void stopSpan(
106+
@Advice.Thrown @Nullable Throwable throwable, @Advice.Enter Object[] enterResult) {
107+
AdviceScope adviceScope = (AdviceScope) enterResult[0];
108+
if (adviceScope != null) {
109+
adviceScope.end(throwable);
83110
}
84-
// span ended in RestResponseListener
85111
}
86112
}
87113
}

instrumentation/elasticsearch/elasticsearch-rest-7.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/rest/v7_0/ElasticsearchRest7InstrumentationModule.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,4 +43,9 @@ public String getModuleGroup() {
4343
public List<TypeInstrumentation> typeInstrumentations() {
4444
return singletonList(new RestClientInstrumentation());
4545
}
46+
47+
@Override
48+
public boolean isIndyReady() {
49+
return true;
50+
}
4651
}

instrumentation/elasticsearch/elasticsearch-rest-7.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/rest/v7_0/ElasticsearchRest7Singletons.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,11 @@
66
package io.opentelemetry.javaagent.instrumentation.elasticsearch.rest.v7_0;
77

88
import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter;
9+
import io.opentelemetry.instrumentation.api.util.VirtualField;
10+
import io.opentelemetry.instrumentation.elasticsearch.rest.common.v5_0.internal.ElasticsearchEndpointDefinition;
911
import io.opentelemetry.instrumentation.elasticsearch.rest.common.v5_0.internal.ElasticsearchRestRequest;
1012
import io.opentelemetry.javaagent.instrumentation.elasticsearch.rest.ElasticsearchRestJavaagentInstrumenterFactory;
13+
import org.elasticsearch.client.Request;
1114
import org.elasticsearch.client.Response;
1215

1316
public final class ElasticsearchRest7Singletons {
@@ -20,5 +23,8 @@ public static Instrumenter<ElasticsearchRestRequest, Response> instrumenter() {
2023
return INSTRUMENTER;
2124
}
2225

26+
public static final VirtualField<Request, ElasticsearchEndpointDefinition> ENDPOINT_DEFINITION =
27+
VirtualField.find(Request.class, ElasticsearchEndpointDefinition.class);
28+
2329
private ElasticsearchRest7Singletons() {}
2430
}

0 commit comments

Comments
 (0)