Skip to content

Commit b8e63cf

Browse files
authored
Instrument vertx client directly (#311)
* Instrument vertx client directly Signed-off-by: Pavol Loffay <[email protected]> * Fix muzzle Signed-off-by: Pavol Loffay <[email protected]> * Add format Signed-off-by: Pavol Loffay <[email protected]> * info Signed-off-by: Pavol Loffay <[email protected]> * use %d Signed-off-by: Pavol Loffay <[email protected]> * Disable Signed-off-by: Pavol Loffay <[email protected]> * Clear context Signed-off-by: Pavol Loffay <[email protected]> * Make no static Signed-off-by: Pavol Loffay <[email protected]>
1 parent 33183a3 commit b8e63cf

File tree

9 files changed

+678
-8
lines changed

9 files changed

+678
-8
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ List of supported frameworks with additional capabilities:
2424
| [Servlet](https://javaee.github.io/javaee-spec/javadocs/javax/servlet/package-summary.html) | 2.3+ |
2525
| [Spark Web Framework](https://github.com/perwendel/spark) | 2.3+ |
2626
| [Spring Webflux](https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/reactive/package-summary.html) | 5.0+ |
27-
| [Vert.x](https://vertx.io) | 3.0+ |
27+
| [Vert.x](https://vertx.io) | 3.0+ (4 not supported yet) |
2828
| [Struts](https://struts.apache.org/) | 2.3+ |
2929

3030
### Adding custom filter implementation

instrumentation/vertx-web-3.0/build.gradle.kts

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ plugins {
22
`java-library`
33
id("net.bytebuddy.byte-buddy")
44
id("io.opentelemetry.instrumentation.auto-instrumentation")
5+
muzzle
56
}
67

78
afterEvaluate{
@@ -12,17 +13,25 @@ afterEvaluate{
1213
).configure()
1314
}
1415

16+
muzzle {
17+
pass {
18+
group = "io.vertx"
19+
module = "vertx-web"
20+
versions = "[3.0.0,4.0.0)"
21+
}
22+
}
23+
1524
val versions: Map<String, String> by extra
1625
// version used by io.vertx:vertx-web:3.0.0
1726
val nettyVersion = "4.0.28.Final"
1827

1928
dependencies {
29+
implementation("io.opentelemetry.javaagent.instrumentation:opentelemetry-javaagent-vertx-web-3.0:${versions["opentelemetry_java_agent"]}")
30+
implementation("io.vertx:vertx-web:3.0.0")
31+
2032
testImplementation(project(":testing-common"))
2133
testImplementation(project(":instrumentation:netty:netty-4.0"))
2234
testImplementation("io.opentelemetry.javaagent.instrumentation:opentelemetry-javaagent-netty-4.0:${versions["opentelemetry_java_agent"]}")
23-
testImplementation("io.opentelemetry.javaagent.instrumentation:opentelemetry-javaagent-vertx-web-3.0:${versions["opentelemetry_java_agent"]}")
24-
testImplementation("io.vertx:vertx-web:3.0.0")
25-
2635

2736
testImplementation("io.netty:netty-codec-http:${nettyVersion}") {
2837
version {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
/*
2+
* Copyright The Hypertrace Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package io.opentelemetry.javaagent.instrumentation.hypertrace.vertx;
18+
19+
import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.implementsInterface;
20+
import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.ClassLoaderMatcher.hasClassesNamed;
21+
import static net.bytebuddy.matcher.ElementMatchers.isMethod;
22+
import static net.bytebuddy.matcher.ElementMatchers.named;
23+
24+
import io.opentelemetry.api.trace.Span;
25+
import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext;
26+
import io.opentelemetry.javaagent.instrumentation.vertx.client.Contexts;
27+
import io.opentelemetry.javaagent.tooling.TypeInstrumentation;
28+
import io.vertx.core.http.HttpClientRequest;
29+
import io.vertx.core.http.HttpClientResponse;
30+
import java.util.HashMap;
31+
import java.util.Map;
32+
import net.bytebuddy.asm.Advice;
33+
import net.bytebuddy.description.method.MethodDescription;
34+
import net.bytebuddy.description.type.TypeDescription;
35+
import net.bytebuddy.matcher.ElementMatcher;
36+
import org.hypertrace.agent.core.config.HypertraceConfig;
37+
import org.hypertrace.agent.core.instrumentation.HypertraceSemanticAttributes;
38+
import org.hypertrace.agent.core.instrumentation.utils.ContentTypeUtils;
39+
40+
public class HttpRequestHandleInstrumentation implements TypeInstrumentation {
41+
42+
@Override
43+
public ElementMatcher<ClassLoader> classLoaderOptimization() {
44+
return hasClassesNamed("io.vertx.core.http.HttpClientRequest");
45+
}
46+
47+
@Override
48+
public ElementMatcher<TypeDescription> typeMatcher() {
49+
return implementsInterface(named("io.vertx.core.http.HttpClientRequest"));
50+
}
51+
52+
@Override
53+
public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() {
54+
Map<ElementMatcher<? super MethodDescription>, String> transformers = new HashMap<>();
55+
56+
// capture response data
57+
transformers.put(
58+
isMethod().and(named("handleResponse")),
59+
HttpRequestHandleInstrumentation.class.getName() + "$HandleResponseAdvice");
60+
return transformers;
61+
}
62+
63+
public static class HandleResponseAdvice {
64+
@Advice.OnMethodEnter(suppress = Throwable.class)
65+
public static void handleResponseEnter(
66+
@Advice.This HttpClientRequest request, @Advice.Argument(0) HttpClientResponse response) {
67+
68+
Contexts contexts =
69+
InstrumentationContext.get(HttpClientRequest.class, Contexts.class).get(request);
70+
if (contexts == null) {
71+
return;
72+
}
73+
Span span = Span.fromContext(contexts.context);
74+
75+
if (HypertraceConfig.get().getDataCapture().getHttpHeaders().getRequest().getValue()) {
76+
for (Map.Entry<String, String> entry : request.headers()) {
77+
span.setAttribute(
78+
HypertraceSemanticAttributes.httpRequestHeader(entry.getKey()), entry.getValue());
79+
}
80+
}
81+
82+
if (HypertraceConfig.get().getDataCapture().getHttpHeaders().getResponse().getValue()) {
83+
for (Map.Entry<String, String> entry : response.headers()) {
84+
span.setAttribute(
85+
HypertraceSemanticAttributes.httpResponseHeader(entry.getKey()), entry.getValue());
86+
}
87+
}
88+
89+
String contentType = response.getHeader("Content-Type");
90+
if (HypertraceConfig.get().getDataCapture().getHttpBody().getResponse().getValue()
91+
&& ContentTypeUtils.shouldCapture(contentType)) {
92+
InstrumentationContext.get(HttpClientResponse.class, Span.class).put(response, span);
93+
}
94+
}
95+
}
96+
}

0 commit comments

Comments
 (0)