diff --git a/agent-testweb/agentsdk-async-testweb/pom.xml b/agent-testweb/agentsdk-async-testweb/pom.xml index b50cee5fff0d..2dea22e726c3 100644 --- a/agent-testweb/agentsdk-async-testweb/pom.xml +++ b/agent-testweb/agentsdk-async-testweb/pom.xml @@ -19,6 +19,28 @@ + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-logging + + + org.springframework.boot + spring-boot-starter-tomcat + provided + + + org.springframework.boot + spring-boot-starter-actuator + + + org.springdoc + springdoc-openapi-ui + + com.navercorp.pinpoint pinpoint-agent-sdk diff --git a/agent-testweb/bom/pom.xml b/agent-testweb/bom/pom.xml new file mode 100644 index 000000000000..50f98881c978 --- /dev/null +++ b/agent-testweb/bom/pom.xml @@ -0,0 +1,72 @@ + + + + + 4.0.0 + + com.navercorp.pinpoint + pinpoint + ../../pom.xml + 2.4.0-SNAPSHOT + + + pom + pinpoint-agent-testweb-bom + pinpoint-agent-testweb-bom + + + 2.4.2 + 5.1.2.RELEASE + 2.1.7.1 + 2.5.3 + 3.9.0 + 2.7.2 + 2.10.6 + + + + + + org.springframework.boot + spring-boot-starter-web + ${spring.boot.version} + + + org.springframework.boot + spring-boot-starter-logging + ${spring.boot.version} + + + org.springframework.boot + spring-boot-starter-tomcat + ${spring.boot.version} + provided + + + org.springframework.boot + spring-boot-starter-actuator + ${spring.boot.version} + + + org.springdoc + springdoc-openapi-ui + 1.4.4 + + + + \ No newline at end of file diff --git a/agent-testweb/dubbo-plugin-testweb/pom.xml b/agent-testweb/dubbo-plugin-testweb/pom.xml index 7aadc3307577..6ef58efc7e34 100644 --- a/agent-testweb/dubbo-plugin-testweb/pom.xml +++ b/agent-testweb/dubbo-plugin-testweb/pom.xml @@ -36,6 +36,28 @@ + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-logging + + + org.springframework.boot + spring-boot-starter-tomcat + provided + + + org.springframework.boot + spring-boot-starter-actuator + + + org.springdoc + springdoc-openapi-ui + + org.apache.dubbo dubbo diff --git a/agent-testweb/jdk-http-plugin-testweb/pom.xml b/agent-testweb/jdk-http-plugin-testweb/pom.xml index f15232d64fdd..ca245e8d3511 100644 --- a/agent-testweb/jdk-http-plugin-testweb/pom.xml +++ b/agent-testweb/jdk-http-plugin-testweb/pom.xml @@ -21,6 +21,28 @@ + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-logging + + + org.springframework.boot + spring-boot-starter-tomcat + provided + + + org.springframework.boot + spring-boot-starter-actuator + + + org.springdoc + springdoc-openapi-ui + + commons-io commons-io diff --git a/agent-testweb/paho-mqtt-plugin-testweb/pom.xml b/agent-testweb/paho-mqtt-plugin-testweb/pom.xml index e4babb62d4d9..01c6df13e1d0 100644 --- a/agent-testweb/paho-mqtt-plugin-testweb/pom.xml +++ b/agent-testweb/paho-mqtt-plugin-testweb/pom.xml @@ -25,6 +25,28 @@ + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-logging + + + org.springframework.boot + spring-boot-starter-tomcat + provided + + + org.springframework.boot + spring-boot-starter-actuator + + + org.springdoc + springdoc-openapi-ui + + org.eclipse.paho org.eclipse.paho.client.mqttv3 diff --git a/agent-testweb/pom.xml b/agent-testweb/pom.xml index fb131276429e..ae7a2bd23dc1 100644 --- a/agent-testweb/pom.xml +++ b/agent-testweb/pom.xml @@ -34,6 +34,8 @@ ${javax.servlet4.version} ${log4j2-jdk8.version} + + false ${project.artifactId}-boot-${project.version} local @@ -50,79 +52,40 @@ + bom agentsdk-async-testweb thread-plugin-testweb paho-mqtt-plugin-testweb reactor-netty-plugin-testweb rocketmq-plugin-testweb dubbo-plugin-testweb - - + spring-cloud-gateway-plugin-testweb + spring-webflux-plugin-testweb jdk-http-plugin-testweb + vertx-3-plugin-testweb + vertx-4-plugin-testweb - org.springframework.boot - spring-boot-starter-web - ${spring.boot.version} - - - org.springframework.boot - spring-boot-starter-logging - ${spring.boot.version} - - - org.springframework.boot - spring-boot-starter-tomcat - ${spring.boot.version} - provided - - - org.springframework.boot - spring-boot-starter-actuator - ${spring.boot.version} - - - org.springdoc - springdoc-openapi-ui - 1.4.4 + com.navercorp.pinpoint + pinpoint-agent-testweb-bom + ${project.version} + pom + import - - - org.springframework.boot - spring-boot-starter-web - - - org.springframework.boot - spring-boot-starter-logging - - - org.springframework.boot - spring-boot-starter-tomcat - provided - - - org.springframework.boot - spring-boot-starter-actuator - - - org.springdoc - springdoc-openapi-ui - - - org.springframework.boot spring-boot-maven-plugin + ${spring-boot-build-skip} ${project.build.directory}/deploy true false diff --git a/agent-testweb/reactor-netty-plugin-testweb/pom.xml b/agent-testweb/reactor-netty-plugin-testweb/pom.xml index a3f1e66a9f67..c2647465f6cb 100644 --- a/agent-testweb/reactor-netty-plugin-testweb/pom.xml +++ b/agent-testweb/reactor-netty-plugin-testweb/pom.xml @@ -22,6 +22,28 @@ + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-logging + + + org.springframework.boot + spring-boot-starter-tomcat + provided + + + org.springframework.boot + spring-boot-starter-actuator + + + org.springdoc + springdoc-openapi-ui + + io.projectreactor.netty reactor-netty diff --git a/agent-testweb/rocketmq-plugin-testweb/rocketmq-original/pom.xml b/agent-testweb/rocketmq-plugin-testweb/rocketmq-original/pom.xml index 8130f0acfe54..fad7ba79afb0 100644 --- a/agent-testweb/rocketmq-plugin-testweb/rocketmq-original/pom.xml +++ b/agent-testweb/rocketmq-plugin-testweb/rocketmq-original/pom.xml @@ -25,6 +25,28 @@ + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-logging + + + org.springframework.boot + spring-boot-starter-tomcat + provided + + + org.springframework.boot + spring-boot-starter-actuator + + + org.springdoc + springdoc-openapi-ui + + org.apache.rocketmq rocketmq-client diff --git a/agent-testweb/rocketmq-plugin-testweb/rocketmq-springboot/pom.xml b/agent-testweb/rocketmq-plugin-testweb/rocketmq-springboot/pom.xml index f8a829fa50ab..d5eb4f6bb44e 100644 --- a/agent-testweb/rocketmq-plugin-testweb/rocketmq-springboot/pom.xml +++ b/agent-testweb/rocketmq-plugin-testweb/rocketmq-springboot/pom.xml @@ -25,6 +25,28 @@ + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-logging + + + org.springframework.boot + spring-boot-starter-tomcat + provided + + + org.springframework.boot + spring-boot-starter-actuator + + + org.springdoc + springdoc-openapi-ui + + org.apache.rocketmq rocketmq-spring-boot-starter diff --git a/agent-testweb/rocketmq-plugin-testweb/rocketmq-springcloud-stream/pom.xml b/agent-testweb/rocketmq-plugin-testweb/rocketmq-springcloud-stream/pom.xml index baa9be3533f9..21e4a5ace0be 100644 --- a/agent-testweb/rocketmq-plugin-testweb/rocketmq-springcloud-stream/pom.xml +++ b/agent-testweb/rocketmq-plugin-testweb/rocketmq-springcloud-stream/pom.xml @@ -25,6 +25,28 @@ + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-logging + + + org.springframework.boot + spring-boot-starter-tomcat + provided + + + org.springframework.boot + spring-boot-starter-actuator + + + org.springdoc + springdoc-openapi-ui + + com.alibaba.cloud spring-cloud-starter-stream-rocketmq diff --git a/agent-testweb/spring-cloud-gateway-plugin-testweb/pom.xml b/agent-testweb/spring-cloud-gateway-plugin-testweb/pom.xml index b61908b93b2a..e8cc72e91d5d 100644 --- a/agent-testweb/spring-cloud-gateway-plugin-testweb/pom.xml +++ b/agent-testweb/spring-cloud-gateway-plugin-testweb/pom.xml @@ -5,13 +5,12 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - org.springframework.boot - spring-boot-starter-parent - 2.4.1 + com.navercorp.pinpoint + pinpoint-agent-testweb + 2.4.0-SNAPSHOT pinpoint-spring-cloud-gateway-plugin-testweb - jar @@ -20,7 +19,6 @@ - @@ -37,10 +35,12 @@ org.springframework.cloud spring-cloud-starter-gateway + 2.1.2.RELEASE org.springframework.boot spring-boot-autoconfigure + 2.4.1 diff --git a/agent-testweb/spring-webflux-plugin-testweb/pom.xml b/agent-testweb/spring-webflux-plugin-testweb/pom.xml index 840ccc114e85..ae16fc19a76e 100644 --- a/agent-testweb/spring-webflux-plugin-testweb/pom.xml +++ b/agent-testweb/spring-webflux-plugin-testweb/pom.xml @@ -5,9 +5,9 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - org.springframework.boot - spring-boot-starter-parent - 2.4.1 + com.navercorp.pinpoint + pinpoint-agent-testweb + 2.4.0-SNAPSHOT pinpoint-spring-webflux-plugin-testweb @@ -24,10 +24,12 @@ org.springframework.boot spring-boot-starter-webflux + 2.4.1 org.springframework.boot spring-boot-autoconfigure + 2.4.1 diff --git a/agent-testweb/thread-plugin-testweb/pom.xml b/agent-testweb/thread-plugin-testweb/pom.xml index 36ac2b3122cf..60b7c9d03992 100644 --- a/agent-testweb/thread-plugin-testweb/pom.xml +++ b/agent-testweb/thread-plugin-testweb/pom.xml @@ -22,6 +22,27 @@ + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-logging + + + org.springframework.boot + spring-boot-starter-tomcat + provided + + + org.springframework.boot + spring-boot-starter-actuator + + + org.springdoc + springdoc-openapi-ui + diff --git a/agent-testweb/vertx-3-plugin-testweb/pom.xml b/agent-testweb/vertx-3-plugin-testweb/pom.xml index 12b8ed18a818..81d443e37c37 100644 --- a/agent-testweb/vertx-3-plugin-testweb/pom.xml +++ b/agent-testweb/vertx-3-plugin-testweb/pom.xml @@ -1,10 +1,29 @@ + + 4.0.0 - com.navercorp.pinpoint + + com.navercorp.pinpoint + pinpoint-agent-testweb + 2.4.0-SNAPSHOT + pinpoint-vertx-3-plugin-testweb - 2.4.0-SNAPSHOT jar @@ -14,6 +33,7 @@ 3.9.8 + true UTF-8 3.8.1 3.2.4 diff --git a/agent-testweb/vertx-4-plugin-testweb/README.md b/agent-testweb/vertx-4-plugin-testweb/README.md new file mode 100644 index 000000000000..5102c26272fb --- /dev/null +++ b/agent-testweb/vertx-4-plugin-testweb/README.md @@ -0,0 +1,12 @@ + +## Install +``` +$ mvn package +``` + +## Run +``` +$ java -jar target/pinpoint-vertx-4-plugin-testweb-2.4.0-SNAPSHOT-fat.jar +``` +You can then access here: http://localhost:18080/ + diff --git a/agent-testweb/vertx-4-plugin-testweb/pom.xml b/agent-testweb/vertx-4-plugin-testweb/pom.xml new file mode 100644 index 000000000000..274ce8522f16 --- /dev/null +++ b/agent-testweb/vertx-4-plugin-testweb/pom.xml @@ -0,0 +1,119 @@ + + + + + 4.0.0 + + com.navercorp.pinpoint + pinpoint-agent-testweb + 2.4.0-SNAPSHOT + + + pinpoint-vertx-4-plugin-testweb + jar + + + UTF-8 + 1.8 + ${env.JAVA_8_HOME} + + 4.2.2 + + true + UTF-8 + 3.8.1 + 3.2.4 + 2.22.2 + 3.0.0 + com.pinpoint.test.plugin.Vertx4PluginTestStarter + io.vertx.core.Launcher + + + + + + io.vertx + vertx-web + ${vertx.version} + + + + + + + maven-compiler-plugin + ${maven-compiler-plugin.version} + + ${jdk.version} + ${jdk.version} + true + true + true + ${encoding} + true + ${jdk.version} + ${jdk.home}/bin/javac + + + + + maven-shade-plugin + ${maven-shade-plugin.version} + + + package + + shade + + + + + + ${launcher.class} + ${main.verticle} + + + + + ${project.build.directory}/${project.artifactId}-${project.version}-fat.jar + + + + + + + maven-surefire-plugin + ${maven-surefire-plugin.version} + + + org.codehaus.mojo + exec-maven-plugin + ${exec-maven-plugin.version} + + io.vertx.core.Launcher + + run + ${main.verticle} + + + + + + + \ No newline at end of file diff --git a/agent-testweb/vertx-4-plugin-testweb/src/main/java/com/pinpoint/test/plugin/Vertx4PluginTestStarter.java b/agent-testweb/vertx-4-plugin-testweb/src/main/java/com/pinpoint/test/plugin/Vertx4PluginTestStarter.java new file mode 100644 index 000000000000..e88844c41f75 --- /dev/null +++ b/agent-testweb/vertx-4-plugin-testweb/src/main/java/com/pinpoint/test/plugin/Vertx4PluginTestStarter.java @@ -0,0 +1,151 @@ +/* + * Copyright 2021 NAVER Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.pinpoint.test.plugin; + +import io.vertx.core.AbstractVerticle; +import io.vertx.core.AsyncResult; +import io.vertx.core.Handler; +import io.vertx.core.Promise; +import io.vertx.core.http.HttpClient; +import io.vertx.core.http.HttpClientRequest; +import io.vertx.core.http.HttpMethod; +import io.vertx.core.http.HttpServerOptions; +import io.vertx.core.http.HttpServerRequest; +import io.vertx.core.net.SelfSignedCertificate; +import io.vertx.ext.web.Router; + +import java.util.concurrent.TimeUnit; + +public class Vertx4PluginTestStarter extends AbstractVerticle { + + @Override + public void start(Promise startPromise) throws Exception { + HttpServerOptions options = new HttpServerOptions(); + options.setIdleTimeout(1000); + options.setSsl(true); + SelfSignedCertificate selfSignedCertificate = SelfSignedCertificate.create(); + options.setKeyCertOptions(selfSignedCertificate.keyCertOptions()); + options.setTrustOptions(selfSignedCertificate.trustOptions()); + + Router router = Router.router(vertx); + + router.get("/").handler(routingContext -> { + routingContext.response().end("Welcome pinpoint vert.x HTTP server test."); + }); + router.get("/request").handler(routingContext -> { + request(80, "naver.com", "/"); + routingContext.response().end("Request http://naver.com:80/"); + }); + router.get("/request/local").handler(routingContext -> { + request(18080, "localhost", "/"); + routingContext.response().end("Request http://localhost:18080/"); + }); + router.get("/request/https").handler(routingContext -> { + request(443, "naver.com", "/"); + routingContext.response().end("Request http://naver.com:80/"); + }); + router.get("/noresponse").handler(routingContext -> { + }); + router.get("/close").handler(routingContext -> { + routingContext.response().close(); + }); + router.get("/connection/close").handler(routingContext -> { + routingContext.request().connection().close(); + }); + router.get("/executeBlocking").handler(routingContext -> { + executeBlocking(routingContext.request(), 1); + }); + router.get("/executeBlocking/wait10s").handler(routingContext -> { + executeBlocking(routingContext.request(), 10); + }); + router.get("/executeBlocking/request").handler(routingContext -> { + executeBlockingRequest(routingContext.request()); + }); + router.get("/runOnContext").handler(routingContext -> { + runOnContext(routingContext.request(), 1); + }); + router.get("/runOnContext/wait10s").handler(routingContext -> { + runOnContext(routingContext.request(), 10); + }); + router.get("/runOnContext/request").handler(routingContext -> { + runOnContextRequest(routingContext.request()); + }); + + vertx.createHttpServer().requestHandler(router).listen(18080, http -> { + if (http.succeeded()) { + startPromise.complete(); + System.out.println("HTTP server started on port 18080"); + } else { + startPromise.fail(http.cause()); + } + }); + } + + private void executeBlocking(HttpServerRequest request, final int waitSeconds) { + vertx.executeBlocking(new Handler>() { + @Override + public void handle(Promise objectFuture) { + sleep(waitSeconds); + request.response().end("Execute blocking."); + } + }, false, null); + } + + private void executeBlockingRequest(HttpServerRequest request) { + vertx.executeBlocking(new Handler>() { + @Override + public void handle(Promise objectFuture) { + request(80, "naver.com", "/"); + request.response().end("Execute blocking request."); + } + }, false, null); + } + + private void runOnContext(HttpServerRequest request, final int waitSeconds) { + vertx.runOnContext(aVoid -> { + sleep(waitSeconds); + request.response().end("Run on context"); + }); + + } + + private void runOnContextRequest(HttpServerRequest request) { + vertx.runOnContext(aVoid -> { + request(80, "naver.com", "/"); + request.response().end("Run on context request."); + }); + } + + private void sleep(int waiteSeconds) { + try { + Thread.sleep(TimeUnit.SECONDS.toMillis(waiteSeconds)); + } catch (InterruptedException e) { + } + } + + public void request(int port, String host, String uri) { + final HttpClient client = vertx.createHttpClient(); + + client.request(HttpMethod.GET, port, host, uri, new Handler>() { + @Override + public void handle(AsyncResult asyncResult) { + System.out.println("## Result=" + asyncResult.result()); + + } + }); + } +} \ No newline at end of file diff --git a/plugins/vertx/pom.xml b/plugins/vertx/pom.xml index 7e86dcf4198f..bb0ce7c19c38 100644 --- a/plugins/vertx/pom.xml +++ b/plugins/vertx/pom.xml @@ -35,7 +35,7 @@ io.vertx vertx-core - 3.5.0 + 4.2.2 provided diff --git a/plugins/vertx/src/main/java/com/navercorp/pinpoint/plugin/vertx/HttpClientRequestCookieExtractor.java b/plugins/vertx/src/main/java/com/navercorp/pinpoint/plugin/vertx/HttpClientRequestCookieExtractor.java new file mode 100644 index 000000000000..4d8ab05fcf97 --- /dev/null +++ b/plugins/vertx/src/main/java/com/navercorp/pinpoint/plugin/vertx/HttpClientRequestCookieExtractor.java @@ -0,0 +1,36 @@ +/* + * Copyright 2021 NAVER Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.navercorp.pinpoint.plugin.vertx; + +import com.navercorp.pinpoint.bootstrap.plugin.request.util.CookieExtractor; +import com.navercorp.pinpoint.common.util.StringUtils; +import io.vertx.core.MultiMap; +import io.vertx.core.http.HttpClientRequest; + +public class HttpClientRequestCookieExtractor implements CookieExtractor { + @Override + public String getCookie(HttpClientRequest httpRequest) { + final MultiMap headers = httpRequest.headers(); + if (headers != null) { + final String cookie = headers.get("Cookie"); + if (StringUtils.hasLength(cookie)) { + return cookie; + } + } + return null; + } +} diff --git a/plugins/vertx/src/main/java/com/navercorp/pinpoint/plugin/vertx/HttpClientRequestWrapper.java b/plugins/vertx/src/main/java/com/navercorp/pinpoint/plugin/vertx/HttpClientRequestWrapper.java new file mode 100644 index 000000000000..d25a3d6e17ab --- /dev/null +++ b/plugins/vertx/src/main/java/com/navercorp/pinpoint/plugin/vertx/HttpClientRequestWrapper.java @@ -0,0 +1,65 @@ +/* + * Copyright 2021 NAVER Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.navercorp.pinpoint.plugin.vertx; + +import com.navercorp.pinpoint.bootstrap.logging.PLogger; +import com.navercorp.pinpoint.bootstrap.logging.PLoggerFactory; +import com.navercorp.pinpoint.bootstrap.plugin.request.ClientRequestWrapper; +import io.vertx.core.http.HttpClientRequest; + +import java.util.Objects; + +public class HttpClientRequestWrapper implements ClientRequestWrapper { + private final PLogger logger = PLoggerFactory.getLogger(this.getClass()); + private final boolean isDebug = logger.isDebugEnabled(); + + private final HttpClientRequest httpRequest; + private final String host; + + public HttpClientRequestWrapper(final HttpClientRequest httpRequest, final String host) { + this.httpRequest = Objects.requireNonNull(httpRequest, "httpRequest"); + this.host = host; + } + + @Override + public String getDestinationId() { + if (this.host != null) { + return this.host; + } + return "Unknown"; + } + + @Override + public String getUrl() { + return getHttpUrl(httpRequest.getHost(), httpRequest.getPort(), httpRequest.getURI()); + } + + private static String getHttpUrl(final String host, final int port, final String uri) { + if (host == null) { + return null; + } + + final StringBuilder sb = new StringBuilder(); + sb.append(host); + // if port is default port number. + sb.append(':').append(port); + if (uri != null) { + sb.append(uri); + } + return sb.toString(); + } +} diff --git a/plugins/vertx/src/main/java/com/navercorp/pinpoint/plugin/vertx/SamplingRateFlag.java b/plugins/vertx/src/main/java/com/navercorp/pinpoint/plugin/vertx/SamplingRateFlag.java new file mode 100644 index 000000000000..d87f3b5e8601 --- /dev/null +++ b/plugins/vertx/src/main/java/com/navercorp/pinpoint/plugin/vertx/SamplingRateFlag.java @@ -0,0 +1,22 @@ +/* + * Copyright 2021 NAVER Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.navercorp.pinpoint.plugin.vertx; + +public interface SamplingRateFlag { + void _$PINPOINT$_setSamplingRateFlag(Boolean samplingRateFlag); + Boolean _$PINPOINT$_getSamplingRateFlag(); +} diff --git a/plugins/vertx/src/main/java/com/navercorp/pinpoint/plugin/vertx/VertxHttpClientRequestWrapper.java b/plugins/vertx/src/main/java/com/navercorp/pinpoint/plugin/vertx/VertxHttpClientRequestWrapper.java index f9df426a1254..6319a6222436 100644 --- a/plugins/vertx/src/main/java/com/navercorp/pinpoint/plugin/vertx/VertxHttpClientRequestWrapper.java +++ b/plugins/vertx/src/main/java/com/navercorp/pinpoint/plugin/vertx/VertxHttpClientRequestWrapper.java @@ -16,23 +16,19 @@ package com.navercorp.pinpoint.plugin.vertx; -import com.navercorp.pinpoint.bootstrap.logging.PLogger; -import com.navercorp.pinpoint.bootstrap.logging.PLoggerFactory; import com.navercorp.pinpoint.bootstrap.plugin.request.ClientRequestWrapper; + import java.util.Objects; + import io.netty.handler.codec.http.HttpRequest; /** * @author jaehong.kim */ public class VertxHttpClientRequestWrapper implements ClientRequestWrapper { - private final PLogger logger = PLoggerFactory.getLogger(this.getClass()); - private final boolean isDebug = logger.isDebugEnabled(); - private final HttpRequest httpRequest; private final String host; - public VertxHttpClientRequestWrapper(final HttpRequest httpRequest, final String host) { this.httpRequest = Objects.requireNonNull(httpRequest, "httpRequest"); this.host = host; @@ -49,8 +45,19 @@ public String getDestinationId() { @Override public String getUrl() { - return this.httpRequest.uri(); + return getHttpUrl(this.host, this.httpRequest.uri()); } + private static String getHttpUrl(final String host, final String uri) { + if (host == null) { + return null; + } + final StringBuilder sb = new StringBuilder(); + sb.append(host); + if (uri != null) { + sb.append(uri); + } + return sb.toString(); + } } diff --git a/plugins/vertx/src/main/java/com/navercorp/pinpoint/plugin/vertx/VertxPlugin.java b/plugins/vertx/src/main/java/com/navercorp/pinpoint/plugin/vertx/VertxPlugin.java index 610ff6a40a80..e3519b58920b 100644 --- a/plugins/vertx/src/main/java/com/navercorp/pinpoint/plugin/vertx/VertxPlugin.java +++ b/plugins/vertx/src/main/java/com/navercorp/pinpoint/plugin/vertx/VertxPlugin.java @@ -39,13 +39,16 @@ import com.navercorp.pinpoint.plugin.vertx.interceptor.HandlerInterceptor; import com.navercorp.pinpoint.plugin.vertx.interceptor.Http1xClientConnectionCreateRequestInterceptor; import com.navercorp.pinpoint.plugin.vertx.interceptor.HttpClientImplDoRequestInterceptor; +import com.navercorp.pinpoint.plugin.vertx.interceptor.HttpClientImplDoRequestInterceptorV4; import com.navercorp.pinpoint.plugin.vertx.interceptor.HttpClientImplInterceptor; +import com.navercorp.pinpoint.plugin.vertx.interceptor.HttpClientRequestImplConstructorInterceptor; import com.navercorp.pinpoint.plugin.vertx.interceptor.HttpClientRequestImplDoHandleResponseInterceptor; import com.navercorp.pinpoint.plugin.vertx.interceptor.HttpClientRequestImplInterceptor; import com.navercorp.pinpoint.plugin.vertx.interceptor.HttpClientResponseImplInterceptor; import com.navercorp.pinpoint.plugin.vertx.interceptor.HttpClientStreamInterceptor; import com.navercorp.pinpoint.plugin.vertx.interceptor.HttpServerRequestImplHandleEndInterceptor; import com.navercorp.pinpoint.plugin.vertx.interceptor.HttpServerResponseImplInterceptor; +import com.navercorp.pinpoint.plugin.vertx.interceptor.PromiseImplInterceptor; import com.navercorp.pinpoint.plugin.vertx.interceptor.ServerConnectionHandleRequestInterceptor; import java.security.ProtectionDomain; @@ -69,7 +72,7 @@ public void setup(ProfilerPluginSetupContext context) { return; } - // 3.3 <= x <= 3.5 + // 3.3 <= x <= 3.5 logger.info("Enable VertxPlugin. version range=[3.3, 3.5.0]"); logger.info("{} config:{}", this.getClass().getSimpleName(), config); @@ -125,6 +128,7 @@ public void setup(ProfilerPluginSetupContext context) { addHttpClientRequestImpl(); addHttpClientStream(); addHttpClientResponseImpl(); + addPromiseImpl(); } } @@ -241,6 +245,8 @@ public byte[] doInTransform(Instrumentor instrumentor, ClassLoader classLoader, private void addHttpServerRequestImpl() { transformTemplate.transform("io.vertx.core.http.impl.HttpServerRequestImpl", HttpServerRequestImplTransform.class); + // 3.7 + transformTemplate.transform("io.vertx.core.http.impl.Http1xServerRequest", HttpServerRequestImplTransform.class); } public static class HttpServerRequestImplTransform implements TransformCallback { @@ -266,6 +272,8 @@ public byte[] doInTransform(Instrumentor instrumentor, ClassLoader classLoader, private void addHttpServerResponseImpl() { transformTemplate.transform("io.vertx.core.http.impl.HttpServerResponseImpl", HttpServerResponseImplTransform.class); + // 3.7 + transformTemplate.transform("io.vertx.core.http.impl.Http1xServerResponse", HttpServerResponseImplTransform.class); } public static class HttpServerResponseImplTransform implements TransformCallback { @@ -321,42 +329,55 @@ private void addHttpClientImpl() { public static class HttpClientImplTransform implements TransformCallback { - @Override - public byte[] doInTransform(Instrumentor instrumentor, ClassLoader classLoader, String className, Class classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws InstrumentException { - final InstrumentClass target = instrumentor.getInstrumentClass(classLoader, className, classfileBuffer); - for (InstrumentMethod method : target.getDeclaredMethods(MethodFilters.name("requestAbs", "request", "get", "getAbs", "getNow", "post", "postAbs", "head", "headAbs", "headNow", "options", "optionsAbs", "optionsNow", "put", "putAbs", "delete", "deleteAbs"))) { - if (method != null) { - method.addScopedInterceptor(HttpClientImplInterceptor.class, VertxConstants.HTTP_CLIENT_REQUEST_SCOPE); + @Override + public byte[] doInTransform(Instrumentor instrumentor, ClassLoader classLoader, String className, Class classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws InstrumentException { + final InstrumentClass target = instrumentor.getInstrumentClass(classLoader, className, classfileBuffer); + // 4.x + target.addField(AsyncContextAccessor.class); + target.addField(SamplingRateFlag.class); + + for (InstrumentMethod method : target.getDeclaredMethods(MethodFilters.name("requestAbs", "request", "get", "getAbs", "getNow", "post", "postAbs", "head", "headAbs", "headNow", "options", "optionsAbs", "optionsNow", "put", "putAbs", "delete", "deleteAbs"))) { + if (method != null) { + method.addScopedInterceptor(HttpClientImplInterceptor.class, VertxConstants.HTTP_CLIENT_REQUEST_SCOPE); + } } - } - // 3.3.x - final InstrumentMethod doRequestMethod = target.getDeclaredMethod("doRequest", "io.vertx.core.http.HttpMethod", "java.lang.String", "int", "java.lang.String", "io.vertx.core.MultiMap"); - if (doRequestMethod != null) { - doRequestMethod.addInterceptor(HttpClientImplDoRequestInterceptor.class); - } + // 3.3.x + final InstrumentMethod doRequestMethod = target.getDeclaredMethod("doRequest", "io.vertx.core.http.HttpMethod", "java.lang.String", "int", "java.lang.String", "io.vertx.core.MultiMap"); + if (doRequestMethod != null) { + doRequestMethod.addInterceptor(HttpClientImplDoRequestInterceptor.class); + } - // 3.4.0, 3.4.1 - final InstrumentMethod createRequestMethod1 = target.getDeclaredMethod("createRequest", "io.vertx.core.http.HttpMethod", "java.lang.String", "int", "java.lang.Boolean", "java.lang.String", "io.vertx.core.MultiMap"); - if (createRequestMethod1 != null) { - createRequestMethod1.addScopedInterceptor(HttpClientImplDoRequestInterceptor.class, VertxConstants.HTTP_CLIENT_CREATE_REQUEST_SCOPE); - } + // 3.4.0, 3.4.1 + final InstrumentMethod createRequestMethod1 = target.getDeclaredMethod("createRequest", "io.vertx.core.http.HttpMethod", "java.lang.String", "int", "java.lang.Boolean", "java.lang.String", "io.vertx.core.MultiMap"); + if (createRequestMethod1 != null) { + createRequestMethod1.addScopedInterceptor(HttpClientImplDoRequestInterceptor.class, VertxConstants.HTTP_CLIENT_CREATE_REQUEST_SCOPE); + } - // 3.4.2 - final InstrumentMethod createRequestMethod2 = target.getDeclaredMethod("createRequest", "io.vertx.core.http.HttpMethod", "java.lang.String", "java.lang.String", "int", "java.lang.Boolean", "java.lang.String", "io.vertx.core.MultiMap"); - if (createRequestMethod2 != null) { - createRequestMethod2.addScopedInterceptor(HttpClientImplDoRequestInterceptor.class, VertxConstants.HTTP_CLIENT_CREATE_REQUEST_SCOPE); - } + // 3.4.2 + final InstrumentMethod createRequestMethod2 = target.getDeclaredMethod("createRequest", "io.vertx.core.http.HttpMethod", "java.lang.String", "java.lang.String", "int", "java.lang.Boolean", "java.lang.String", "io.vertx.core.MultiMap"); + if (createRequestMethod2 != null) { + createRequestMethod2.addScopedInterceptor(HttpClientImplDoRequestInterceptor.class, VertxConstants.HTTP_CLIENT_CREATE_REQUEST_SCOPE); + } - // 3.7 - final InstrumentMethod createRequestMethod3 = target.getDeclaredMethod("createRequest", "io.vertx.core.http.HttpMethod", "io.vertx.core.net.SocketAddress", "java.lang.String", "java.lang.String", "int", "java.lang.Boolean", "java.lang.String", "io.vertx.core.MultiMap"); - if (createRequestMethod3 != null) { - createRequestMethod3.addScopedInterceptor(HttpClientImplDoRequestInterceptor.class, VertxConstants.HTTP_CLIENT_CREATE_REQUEST_SCOPE); - } + // 3.7 + final InstrumentMethod createRequestMethod3 = target.getDeclaredMethod("createRequest", "io.vertx.core.http.HttpMethod", "io.vertx.core.net.SocketAddress", "java.lang.String", "java.lang.String", "int", "java.lang.Boolean", "java.lang.String", "io.vertx.core.MultiMap"); + if (createRequestMethod3 != null) { + createRequestMethod3.addScopedInterceptor(HttpClientImplDoRequestInterceptor.class, VertxConstants.HTTP_CLIENT_CREATE_REQUEST_SCOPE); + } - return target.toBytecode(); + // 4.x + final InstrumentMethod doRequestMethod2 = target.getDeclaredMethod("doRequest", "io.vertx.core.http.HttpMethod", "io.vertx.core.net.SocketAddress", "io.vertx.core.net.SocketAddress", "java.lang.String", "int", "java.lang.Boolean", "java.lang.String", "io.vertx.core.MultiMap", "long", "java.lang.Boolean", "io.vertx.core.net.ProxyOptions", "io.vertx.core.impl.future.PromiseInternal"); + if (doRequestMethod2 != null) { + doRequestMethod2.addScopedInterceptor(HttpClientImplDoRequestInterceptorV4.class, VertxConstants.HTTP_CLIENT_CREATE_REQUEST_SCOPE); + } + final InstrumentMethod doRequestMethod3 = target.getDeclaredMethod("doRequest", "io.vertx.core.http.HttpMethod", "io.vertx.core.net.SocketAddress", "io.vertx.core.net.SocketAddress", "java.lang.String", "int", "java.lang.Boolean", "java.lang.String", "io.vertx.core.MultiMap", "java.lang.String", "long", "java.lang.Boolean", "io.vertx.core.net.ProxyOptions", "io.vertx.core.impl.future.PromiseInternal"); + if (doRequestMethod3 != null) { + doRequestMethod3.addScopedInterceptor(HttpClientImplDoRequestInterceptorV4.class, VertxConstants.HTTP_CLIENT_CREATE_REQUEST_SCOPE); + } + return target.toBytecode(); + } } -} private void addHttpClientRequestImpl() { transformTemplate.transform("io.vertx.core.http.impl.HttpClientRequestImpl", HttpClientRequestImplTransform.class); @@ -364,72 +385,88 @@ private void addHttpClientRequestImpl() { public static class HttpClientRequestImplTransform implements TransformCallback { - @Override - public byte[] doInTransform(Instrumentor instrumentor, ClassLoader classLoader, String className, Class classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws InstrumentException { - final InstrumentClass target = instrumentor.getInstrumentClass(classLoader, className, classfileBuffer); - target.addField(AsyncContextAccessor.class); + @Override + public byte[] doInTransform(Instrumentor instrumentor, ClassLoader classLoader, String className, Class classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws InstrumentException { + final InstrumentClass target = instrumentor.getInstrumentClass(classLoader, className, classfileBuffer); + target.addField(AsyncContextAccessor.class); + target.addField(SamplingRateFlag.class); - // for HttpClientResponseImpl. - for (InstrumentMethod method : target.getDeclaredMethods(MethodFilters.name("doHandleResponse"))) { - if (method != null) { - method.addInterceptor(HttpClientRequestImplDoHandleResponseInterceptor.class); + // 4.x + InstrumentMethod constructor = target.getConstructor("io.vertx.core.http.impl.HttpClientImpl", "io.vertx.core.http.impl.HttpClientStream", "io.vertx.core.impl.future.PromiseInternal", "boolean", "io.vertx.core.http.HttpMethod", "io.vertx.core.net.SocketAddress", "java.lang.String", "int", "java.lang.String"); + if (constructor != null) { + constructor.addInterceptor(HttpClientRequestImplConstructorInterceptor.class); + } + InstrumentMethod constructor2 = target.getConstructor("io.vertx.core.http.impl.HttpClientImpl", "io.vertx.core.http.impl.HttpClientStream", "io.vertx.core.impl.future.PromiseInternal", "boolean", "io.vertx.core.http.HttpMethod", "io.vertx.core.net.SocketAddress", "java.lang.String", "int", "java.lang.String", "java.lang.String"); + if (constructor2 != null) { + constructor2.addInterceptor(HttpClientRequestImplConstructorInterceptor.class); } - } - // for stream.writeHead(), stream.writeHeadWithContent(), headersCompletionHandler. - final InstrumentMethod connectedMethod = target.getDeclaredMethod("connected", "io.vertx.core.http.impl.HttpClientStream", "io.vertx.core.Handler"); - if (connectedMethod != null) { - connectedMethod.addInterceptor(HttpClientRequestImplInterceptor.class); - } + // for HttpClientResponseImpl. + for (InstrumentMethod method : target.getDeclaredMethods(MethodFilters.name("doHandleResponse"))) { + if (method != null) { + method.addInterceptor(HttpClientRequestImplDoHandleResponseInterceptor.class); + } + } - // for vert.x 3.7 - final InstrumentMethod connectedMethod2 = target.getDeclaredMethod("connected", "io.vertx.core.Handler", "io.vertx.core.http.impl.HttpClientStream"); - if (connectedMethod2 != null) { - connectedMethod2.addInterceptor(HttpClientRequestImplInterceptor.class); - } + // for stream.writeHead(), stream.writeHeadWithContent(), headersCompletionHandler. + final InstrumentMethod connectedMethod = target.getDeclaredMethod("connected", "io.vertx.core.http.impl.HttpClientStream", "io.vertx.core.Handler"); + if (connectedMethod != null) { + connectedMethod.addInterceptor(HttpClientRequestImplInterceptor.class); + } - // handle. - final InstrumentMethod handleDrainedMethod = target.getDeclaredMethod("handleDrained"); - if (handleDrainedMethod != null) { - handleDrainedMethod.addInterceptor(HttpClientRequestImplInterceptor.class); - } + // 3.7 + final InstrumentMethod connectedMethod2 = target.getDeclaredMethod("connected", "io.vertx.core.Handler", "io.vertx.core.http.impl.HttpClientStream"); + if (connectedMethod2 != null) { + connectedMethod2.addInterceptor(HttpClientRequestImplInterceptor.class); + } - final InstrumentMethod handleExceptionMethod = target.getDeclaredMethod("handleException", "java.lang.Throwable"); - if (handleExceptionMethod != null) { - handleExceptionMethod.addInterceptor(HandleExceptionInterceptor.class); - } + // handle. + final InstrumentMethod handleDrainedMethod = target.getDeclaredMethod("handleDrained"); + if (handleDrainedMethod != null) { + handleDrainedMethod.addInterceptor(HttpClientRequestImplInterceptor.class); + } - return target.toBytecode(); + final InstrumentMethod handleExceptionMethod = target.getDeclaredMethod("handleException", "java.lang.Throwable"); + if (handleExceptionMethod != null) { + handleExceptionMethod.addInterceptor(HandleExceptionInterceptor.class); + } + + // 4.x + final InstrumentMethod doWriteMethod = target.getDeclaredMethod("doWrite", "io.netty.buffer.ByteBuf", "boolean", "boolean", "io.vertx.core.Handler"); + if (doWriteMethod != null) { + doWriteMethod.addInterceptor(HttpClientRequestImplInterceptor.class); + } + + return target.toBytecode(); + } } -} private void addHttpClientStream() { transformTemplate.transform("io.vertx.core.http.impl.ClientConnection", ClientConnectionTransform.class); - // for vert.x 3.7 + // 3.7 transformTemplate.transform("io.vertx.core.http.impl.Http1xClientConnection", ClientConnectionTransform.class); } public static class ClientConnectionTransform implements TransformCallback { - @Override - public byte[] doInTransform(Instrumentor instrumentor, ClassLoader classLoader, String className, Class classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws InstrumentException { - final InstrumentClass target = instrumentor.getInstrumentClass(classLoader, className, classfileBuffer); + @Override + public byte[] doInTransform(Instrumentor instrumentor, ClassLoader classLoader, String className, Class classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws InstrumentException { + final InstrumentClass target = instrumentor.getInstrumentClass(classLoader, className, classfileBuffer); - // add pinpoint headers. - final InstrumentMethod prepareHeadersMethod = target.getDeclaredMethod("prepareHeaders", "io.netty.handler.codec.http.HttpRequest", "java.lang.String", "boolean"); - if (prepareHeadersMethod != null) { - prepareHeadersMethod.addInterceptor(HttpClientStreamInterceptor.class); - } + // add pinpoint headers. + final InstrumentMethod prepareHeadersMethod = target.getDeclaredMethod("prepareHeaders", "io.netty.handler.codec.http.HttpRequest", "java.lang.String", "boolean"); + if (prepareHeadersMethod != null) { + prepareHeadersMethod.addInterceptor(HttpClientStreamInterceptor.class); + } - // for vert.x 3.7 - final InstrumentMethod createRequestMethod = target.getDeclaredMethod("createRequest", "io.vertx.core.http.HttpMethod", "java.lang.String", "java.lang.String", "io.vertx.core.MultiMap", "java.lang.String", "boolean"); - if (createRequestMethod != null) { - createRequestMethod.addInterceptor(Http1xClientConnectionCreateRequestInterceptor.class); + // 3.7 + final InstrumentMethod createRequestMethod = target.getDeclaredMethod("createRequest", "io.vertx.core.http.HttpMethod", "java.lang.String", "java.lang.String", "io.vertx.core.MultiMap", "java.lang.String", "boolean"); + if (createRequestMethod != null) { + createRequestMethod.addInterceptor(Http1xClientConnectionCreateRequestInterceptor.class); + } + return target.toBytecode(); } - - return target.toBytecode(); } -} private void addHttpClientResponseImpl() { transformTemplate.transform("io.vertx.core.http.impl.HttpClientResponseImpl", HttpClientResponseImplTransform.class); @@ -437,24 +474,44 @@ private void addHttpClientResponseImpl() { public static class HttpClientResponseImplTransform implements TransformCallback { - @Override - public byte[] doInTransform(Instrumentor instrumentor, ClassLoader classLoader, String className, Class classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws InstrumentException { - final InstrumentClass target = instrumentor.getInstrumentClass(classLoader, className, classfileBuffer); - target.addField(AsyncContextAccessor.class); + @Override + public byte[] doInTransform(Instrumentor instrumentor, ClassLoader classLoader, String className, Class classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws InstrumentException { + final InstrumentClass target = instrumentor.getInstrumentClass(classLoader, className, classfileBuffer); + target.addField(AsyncContextAccessor.class); - final InstrumentMethod handleEndMethod = target.getDeclaredMethod("handleEnd", "io.vertx.core.buffer.Buffer", "io.vertx.core.MultiMap"); - if (handleEndMethod != null) { - handleEndMethod.addInterceptor(HttpClientResponseImplInterceptor.class); - } + final InstrumentMethod handleEndMethod = target.getDeclaredMethod("handleEnd", "io.vertx.core.buffer.Buffer", "io.vertx.core.MultiMap"); + if (handleEndMethod != null) { + handleEndMethod.addInterceptor(HttpClientResponseImplInterceptor.class); + } - final InstrumentMethod handleExceptionMethod = target.getDeclaredMethod("handleException", "java.lang.Throwable"); - if (handleExceptionMethod != null) { - handleExceptionMethod.addInterceptor(HandleExceptionInterceptor.class); + final InstrumentMethod handleExceptionMethod = target.getDeclaredMethod("handleException", "java.lang.Throwable"); + if (handleExceptionMethod != null) { + handleExceptionMethod.addInterceptor(HandleExceptionInterceptor.class); + } + + return target.toBytecode(); } + } - return target.toBytecode(); + private void addPromiseImpl() { + // 4.x + transformTemplate.transform("io.vertx.core.impl.future.PromiseImpl", PromiseImplTransform.class); + } + + public static class PromiseImplTransform implements TransformCallback { + + @Override + public byte[] doInTransform(Instrumentor instrumentor, ClassLoader classLoader, String className, Class classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws InstrumentException { + final InstrumentClass target = instrumentor.getInstrumentClass(classLoader, className, classfileBuffer); + + final InstrumentMethod tryComplete = target.getDeclaredMethod("tryComplete", "java.lang.Object"); + if (tryComplete != null) { + tryComplete.addInterceptor(PromiseImplInterceptor.class); + } + + return target.toBytecode(); + } } -} @Override public void setTransformTemplate(MatchableTransformTemplate transformTemplate) { diff --git a/plugins/vertx/src/main/java/com/navercorp/pinpoint/plugin/vertx/interceptor/HttpClientImplDoRequestInterceptorV4.java b/plugins/vertx/src/main/java/com/navercorp/pinpoint/plugin/vertx/interceptor/HttpClientImplDoRequestInterceptorV4.java new file mode 100644 index 000000000000..a236162ee46c --- /dev/null +++ b/plugins/vertx/src/main/java/com/navercorp/pinpoint/plugin/vertx/interceptor/HttpClientImplDoRequestInterceptorV4.java @@ -0,0 +1,131 @@ +/* + * Copyright 2021 NAVER Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.navercorp.pinpoint.plugin.vertx.interceptor; + +import com.navercorp.pinpoint.bootstrap.async.AsyncContextAccessor; +import com.navercorp.pinpoint.bootstrap.context.AsyncContext; +import com.navercorp.pinpoint.bootstrap.context.MethodDescriptor; +import com.navercorp.pinpoint.bootstrap.context.SpanEventRecorder; +import com.navercorp.pinpoint.bootstrap.context.Trace; +import com.navercorp.pinpoint.bootstrap.context.TraceContext; +import com.navercorp.pinpoint.bootstrap.interceptor.AroundInterceptor; +import com.navercorp.pinpoint.bootstrap.logging.PLogger; +import com.navercorp.pinpoint.bootstrap.logging.PLoggerFactory; +import com.navercorp.pinpoint.bootstrap.plugin.request.ClientHeaderAdaptor; +import com.navercorp.pinpoint.bootstrap.plugin.request.DefaultRequestTraceWriter; +import com.navercorp.pinpoint.bootstrap.plugin.request.RequestTraceWriter; +import com.navercorp.pinpoint.common.plugin.util.HostAndPort; +import com.navercorp.pinpoint.common.trace.AnnotationKey; +import com.navercorp.pinpoint.common.util.ArrayUtils; +import com.navercorp.pinpoint.plugin.vertx.HttpClientRequestClientHeaderAdaptor; +import com.navercorp.pinpoint.plugin.vertx.SamplingRateFlag; +import com.navercorp.pinpoint.plugin.vertx.VertxConstants; +import io.vertx.core.http.HttpClientRequest; + +public class HttpClientImplDoRequestInterceptorV4 implements AroundInterceptor { + private final PLogger logger = PLoggerFactory.getLogger(this.getClass()); + private final boolean isDebug = logger.isDebugEnabled(); + + private final TraceContext traceContext; + private final MethodDescriptor methodDescriptor; + private final RequestTraceWriter requestTraceWriter; + + public HttpClientImplDoRequestInterceptorV4(TraceContext traceContext, MethodDescriptor descriptor) { + this.traceContext = traceContext; + this.methodDescriptor = descriptor; + + ClientHeaderAdaptor clientHeaderAdaptor = new HttpClientRequestClientHeaderAdaptor(); + this.requestTraceWriter = new DefaultRequestTraceWriter<>(clientHeaderAdaptor, traceContext); + } + + @Override + public void before(Object target, Object[] args) { + if (isDebug) { + logger.beforeInterceptor(target, args); + } + + final Trace trace = traceContext.currentRawTraceObject(); + if (trace == null) { + return; + } + + if (!trace.canSampled()) { + if (target instanceof SamplingRateFlag) { + // 4.x + ((SamplingRateFlag) target)._$PINPOINT$_setSamplingRateFlag(Boolean.FALSE); + } + return; + } + + trace.traceBlockBegin(); + } + + @Override + public void after(Object target, Object[] args, Object result, Throwable throwable) { + if (isDebug) { + logger.afterInterceptor(target, args, result, throwable); + } + + final Trace trace = traceContext.currentTraceObject(); + if (trace == null) { + return; + } + + if (!trace.canSampled()) { + return; + } + + try { + final SpanEventRecorder recorder = trace.currentSpanEventRecorder(); + recorder.recordApi(methodDescriptor); + recorder.recordException(throwable); + recorder.recordServiceType(VertxConstants.VERTX_HTTP_CLIENT_INTERNAL); + + final String hostAndPort = toHostAndPort(args); + if (hostAndPort != null) { + recorder.recordAttribute(AnnotationKey.HTTP_INTERNAL_DISPLAY, hostAndPort); + if (isDebug) { + logger.debug("Set hostAndPort {}", hostAndPort); + } + } + + if (target instanceof AsyncContextAccessor) { + // make asynchronous trace-id + final AsyncContext asyncContext = recorder.recordNextAsyncContext(); + ((AsyncContextAccessor) target)._$PINPOINT$_setAsyncContext(asyncContext); + } + } finally { + trace.traceBlockEnd(); + } + } + + private String toHostAndPort(final Object[] args) { + final int length = ArrayUtils.getLength(args); + if (length == 12) { + if (args[3] instanceof String && args[4] instanceof Integer) { + final String host = (String) args[3]; + final int port = (Integer) args[4]; + return HostAndPort.toHostAndPortString(host, port); + } + } + + if (isDebug) { + logger.debug("Invalid args[]. args={}.", args); + } + return null; + } +} \ No newline at end of file diff --git a/plugins/vertx/src/main/java/com/navercorp/pinpoint/plugin/vertx/interceptor/HttpClientRequestImplConnectedInterceptor.java b/plugins/vertx/src/main/java/com/navercorp/pinpoint/plugin/vertx/interceptor/HttpClientRequestImplConnectedInterceptor.java deleted file mode 100644 index 3abb8d28da6c..000000000000 --- a/plugins/vertx/src/main/java/com/navercorp/pinpoint/plugin/vertx/interceptor/HttpClientRequestImplConnectedInterceptor.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright 2016 NAVER Corp. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.navercorp.pinpoint.plugin.vertx.interceptor; - -import com.navercorp.pinpoint.bootstrap.async.AsyncContextAccessor; -import com.navercorp.pinpoint.bootstrap.context.AsyncContext; -import com.navercorp.pinpoint.bootstrap.context.MethodDescriptor; -import com.navercorp.pinpoint.bootstrap.context.SpanEventRecorder; -import com.navercorp.pinpoint.bootstrap.context.TraceContext; -import com.navercorp.pinpoint.bootstrap.interceptor.AsyncContextSpanEventSimpleAroundInterceptor; -import com.navercorp.pinpoint.common.trace.AnnotationKey; -import com.navercorp.pinpoint.common.util.ArrayUtils; -import com.navercorp.pinpoint.plugin.vertx.VertxConstants; -import com.navercorp.pinpoint.plugin.vertx.VertxHttpClientConfig; -import io.vertx.core.http.impl.HttpClientResponseImpl; - -/** - * @author jaehong.kim - */ -public class HttpClientRequestImplConnectedInterceptor extends AsyncContextSpanEventSimpleAroundInterceptor { - - private boolean statusCode; - - public HttpClientRequestImplConnectedInterceptor(TraceContext traceContext, MethodDescriptor methodDescriptor) { - super(traceContext, methodDescriptor); - - final VertxHttpClientConfig config = new VertxHttpClientConfig(traceContext.getProfilerConfig()); - this.statusCode = config.isStatusCode(); - } - - @Override - public void doInBeforeTrace(SpanEventRecorder recorder, AsyncContext asyncContext, Object target, Object[] args) { - if (!validate(args)) { - return; - } - - final HttpClientResponseImpl response = (HttpClientResponseImpl) args[0]; - if (statusCode) { - recorder.recordAttribute(AnnotationKey.HTTP_STATUS_CODE, response.statusCode()); - } - - ((AsyncContextAccessor) response)._$PINPOINT$_setAsyncContext(asyncContext); - } - - private boolean validate(final Object[] args) { - Object httpClientResponseImpl = ArrayUtils.get(args, 0); - if (!(httpClientResponseImpl instanceof HttpClientResponseImpl)) { - if (isDebug) { - logger.debug("Invalid args[0] object. args={}.", args); - } - return false; - } - - if (!(httpClientResponseImpl instanceof AsyncContextAccessor)) { - if (isDebug) { - logger.debug("Invalid args[0] object. Need metadata accessor({}).", AsyncContextAccessor.class.getName()); - } - return false; - } - - return true; - } - - @Override - public void doInAfterTrace(SpanEventRecorder recorder, Object target, Object[] args, Object result, Throwable throwable) { - recorder.recordApi(methodDescriptor); - recorder.recordServiceType(VertxConstants.VERTX_HTTP_CLIENT_INTERNAL); - recorder.recordException(throwable); - } -} \ No newline at end of file diff --git a/plugins/vertx/src/main/java/com/navercorp/pinpoint/plugin/vertx/interceptor/HttpClientRequestImplConstructorInterceptor.java b/plugins/vertx/src/main/java/com/navercorp/pinpoint/plugin/vertx/interceptor/HttpClientRequestImplConstructorInterceptor.java new file mode 100644 index 000000000000..fcf45c22d622 --- /dev/null +++ b/plugins/vertx/src/main/java/com/navercorp/pinpoint/plugin/vertx/interceptor/HttpClientRequestImplConstructorInterceptor.java @@ -0,0 +1,64 @@ +/* + * Copyright 2021 NAVER Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.navercorp.pinpoint.plugin.vertx.interceptor; + +import com.navercorp.pinpoint.bootstrap.async.AsyncContextAccessor; +import com.navercorp.pinpoint.bootstrap.async.AsyncContextAccessorUtils; +import com.navercorp.pinpoint.bootstrap.context.AsyncContext; +import com.navercorp.pinpoint.bootstrap.context.MethodDescriptor; +import com.navercorp.pinpoint.bootstrap.context.TraceContext; +import com.navercorp.pinpoint.bootstrap.interceptor.AroundInterceptor; +import com.navercorp.pinpoint.bootstrap.logging.PLogger; +import com.navercorp.pinpoint.bootstrap.logging.PLoggerFactory; +import com.navercorp.pinpoint.plugin.vertx.SamplingRateFlag; + +public class HttpClientRequestImplConstructorInterceptor implements AroundInterceptor { + private final PLogger logger = PLoggerFactory.getLogger(this.getClass()); + private final boolean isDebug = logger.isDebugEnabled(); + + private final TraceContext traceContext; + private final MethodDescriptor methodDescriptor; + + public HttpClientRequestImplConstructorInterceptor(TraceContext traceContext, MethodDescriptor descriptor) { + this.traceContext = traceContext; + this.methodDescriptor = descriptor; + } + + @Override + public void before(Object target, Object[] args) { + } + + @Override + public void after(Object target, Object[] args, Object result, Throwable throwable) { + if (isDebug) { + logger.afterInterceptor(target, args, result, throwable); + } + + if(args != null && args.length < 1) { + return; + } + + final AsyncContext asyncContext = AsyncContextAccessorUtils.getAsyncContext(args[0]); + if(asyncContext != null) { + ((AsyncContextAccessor)target)._$PINPOINT$_setAsyncContext(asyncContext); + } + if(args[0] instanceof SamplingRateFlag) { + final Boolean samplingRateFlag = ((SamplingRateFlag)(args[0]))._$PINPOINT$_getSamplingRateFlag(); + ((SamplingRateFlag)target)._$PINPOINT$_setSamplingRateFlag(samplingRateFlag); + } + } +} \ No newline at end of file diff --git a/plugins/vertx/src/main/java/com/navercorp/pinpoint/plugin/vertx/interceptor/HttpServerRequestAdaptor.java b/plugins/vertx/src/main/java/com/navercorp/pinpoint/plugin/vertx/interceptor/HttpServerRequestAdaptor.java index 77d0a4f78c0d..a78de5c6b90f 100644 --- a/plugins/vertx/src/main/java/com/navercorp/pinpoint/plugin/vertx/interceptor/HttpServerRequestAdaptor.java +++ b/plugins/vertx/src/main/java/com/navercorp/pinpoint/plugin/vertx/interceptor/HttpServerRequestAdaptor.java @@ -56,8 +56,14 @@ public String getEndPoint(HttpServerRequest request) { final int port = request.localAddress().port(); if (port <= 0) { return request.host(); - } else { - return request.host() + ":" + port; + } + final String host = request.host(); + if (host != null) { + if (host.contains(":")) { + return host; + } else { + return host + ":" + port; + } } } return null; diff --git a/plugins/vertx/src/main/java/com/navercorp/pinpoint/plugin/vertx/interceptor/HttpServerResponseImplInterceptor.java b/plugins/vertx/src/main/java/com/navercorp/pinpoint/plugin/vertx/interceptor/HttpServerResponseImplInterceptor.java index 8feca008c0fb..bcecb5045b74 100644 --- a/plugins/vertx/src/main/java/com/navercorp/pinpoint/plugin/vertx/interceptor/HttpServerResponseImplInterceptor.java +++ b/plugins/vertx/src/main/java/com/navercorp/pinpoint/plugin/vertx/interceptor/HttpServerResponseImplInterceptor.java @@ -23,7 +23,7 @@ import com.navercorp.pinpoint.bootstrap.context.TraceContext; import com.navercorp.pinpoint.bootstrap.plugin.http.HttpStatusCodeRecorder; import com.navercorp.pinpoint.plugin.vertx.VertxConstants; -import io.vertx.core.http.impl.HttpServerResponseImpl; +import io.vertx.core.http.HttpServerResponse; /** * @author jaehong.kim @@ -48,8 +48,8 @@ public void doInAfterTrace(SpanEventRecorder recorder, Object target, Object[] a recorder.recordServiceType(VertxConstants.VERTX_HTTP_SERVER_INTERNAL); recorder.recordException(throwable); - if (target instanceof HttpServerResponseImpl) { - final HttpServerResponseImpl response = (HttpServerResponseImpl) target; + if (target instanceof HttpServerResponse) { + final HttpServerResponse response = (HttpServerResponse) target; // TODO more simple. final AsyncContext asyncContext = getAsyncContext(target); if (asyncContext != null) { diff --git a/plugins/vertx/src/main/java/com/navercorp/pinpoint/plugin/vertx/interceptor/PromiseImplInterceptor.java b/plugins/vertx/src/main/java/com/navercorp/pinpoint/plugin/vertx/interceptor/PromiseImplInterceptor.java new file mode 100644 index 000000000000..6c6408016f40 --- /dev/null +++ b/plugins/vertx/src/main/java/com/navercorp/pinpoint/plugin/vertx/interceptor/PromiseImplInterceptor.java @@ -0,0 +1,161 @@ +/* + * Copyright 2021 NAVER Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.navercorp.pinpoint.plugin.vertx.interceptor; + +import com.navercorp.pinpoint.bootstrap.async.AsyncContextAccessor; +import com.navercorp.pinpoint.bootstrap.async.AsyncContextAccessorUtils; +import com.navercorp.pinpoint.bootstrap.context.AsyncContext; +import com.navercorp.pinpoint.bootstrap.context.MethodDescriptor; +import com.navercorp.pinpoint.bootstrap.context.SpanEventRecorder; +import com.navercorp.pinpoint.bootstrap.context.TraceContext; +import com.navercorp.pinpoint.bootstrap.context.TraceId; +import com.navercorp.pinpoint.bootstrap.interceptor.AsyncContextSpanEventSimpleAroundInterceptor; +import com.navercorp.pinpoint.bootstrap.plugin.request.ClientHeaderAdaptor; +import com.navercorp.pinpoint.bootstrap.plugin.request.ClientRequestAdaptor; +import com.navercorp.pinpoint.bootstrap.plugin.request.ClientRequestRecorder; +import com.navercorp.pinpoint.bootstrap.plugin.request.ClientRequestWrapper; +import com.navercorp.pinpoint.bootstrap.plugin.request.ClientRequestWrapperAdaptor; +import com.navercorp.pinpoint.bootstrap.plugin.request.DefaultRequestTraceWriter; +import com.navercorp.pinpoint.bootstrap.plugin.request.RequestTraceWriter; +import com.navercorp.pinpoint.bootstrap.plugin.request.util.CookieExtractor; +import com.navercorp.pinpoint.bootstrap.plugin.request.util.CookieRecorder; +import com.navercorp.pinpoint.bootstrap.plugin.request.util.CookieRecorderFactory; +import com.navercorp.pinpoint.common.util.ArrayUtils; +import com.navercorp.pinpoint.plugin.vertx.HttpClientRequestClientHeaderAdaptor; +import com.navercorp.pinpoint.plugin.vertx.HttpClientRequestCookieExtractor; +import com.navercorp.pinpoint.plugin.vertx.HttpClientRequestWrapper; +import com.navercorp.pinpoint.plugin.vertx.SamplingRateFlag; +import com.navercorp.pinpoint.plugin.vertx.VertxConstants; +import com.navercorp.pinpoint.plugin.vertx.VertxHttpClientConfig; +import io.vertx.core.http.HttpClientRequest; + +public class PromiseImplInterceptor extends AsyncContextSpanEventSimpleAroundInterceptor { + + private final ClientRequestRecorder clientRequestRecorder; + private final CookieRecorder cookieRecorder; + private final RequestTraceWriter requestTraceWriter; + + public PromiseImplInterceptor(TraceContext traceContext, MethodDescriptor descriptor) { + super(traceContext, descriptor); + + final VertxHttpClientConfig config = new VertxHttpClientConfig(traceContext.getProfilerConfig()); + ClientRequestAdaptor clientRequestAdaptor = ClientRequestWrapperAdaptor.INSTANCE; + this.clientRequestRecorder = new ClientRequestRecorder<>(config.isParam(), clientRequestAdaptor); + + CookieExtractor cookieExtractor = new HttpClientRequestCookieExtractor(); + this.cookieRecorder = CookieRecorderFactory.newCookieRecorder(config.getHttpDumpConfig(), cookieExtractor); + + ClientHeaderAdaptor clientHeaderAdaptor = new HttpClientRequestClientHeaderAdaptor(); + this.requestTraceWriter = new DefaultRequestTraceWriter<>(clientHeaderAdaptor, traceContext); + } + + @Override + public void doInBeforeTrace(SpanEventRecorder recorder, AsyncContext asyncContext, Object target, Object[] args) { + final HttpClientRequest request = (HttpClientRequest) args[0]; + String host = request.getHost(); + if (host == null) { + host = "UNKNOWN"; + } + + // generate next trace id. + final TraceId nextId = asyncContext.currentAsyncTraceObject().getTraceId().getNextTraceId(); + recorder.recordNextSpanId(nextId.getSpanId()); + requestTraceWriter.write(request, nextId, host); + } + + @Override + public AsyncContext getAsyncContext(Object target, Object[] args) { + if (isSamplingRateFalse(args)) { + final HttpClientRequest request = (HttpClientRequest) args[0]; + this.requestTraceWriter.write(request); + return null; + } + + if (validate(args)) { + return AsyncContextAccessorUtils.getAsyncContext(args[0]); + } + return null; + } + + @Override + public void doInAfterTrace(SpanEventRecorder recorder, Object target, Object[] args, Object result, Throwable throwable) { + recorder.recordApi(methodDescriptor); + recorder.recordException(throwable); + recorder.recordServiceType(VertxConstants.VERTX_HTTP_CLIENT); + + final HttpClientRequest request = (HttpClientRequest) args[0]; + String host = request.getHost(); + if (host == null) { + host = "UNKNOWN"; + } + + final ClientRequestWrapper clientRequest = new HttpClientRequestWrapper(request, host); + this.clientRequestRecorder.record(recorder, clientRequest, throwable); + this.cookieRecorder.record(recorder, request, throwable); + } + + @Override + public AsyncContext getAsyncContext(Object target, Object[] args, Object result, Throwable throwable) { + if (isSamplingRateFalse(args)) { + return null; + } + + if (validate(args)) { + return AsyncContextAccessorUtils.getAsyncContext(args[0]); + } + return null; + } + + private boolean isSamplingRateFalse(final Object[] args) { + if (ArrayUtils.getLength(args) < 1) { + return false; + } + + if (Boolean.FALSE == (args[0] instanceof SamplingRateFlag)) { + return false; + } + final Boolean samplingRateFlag = ((SamplingRateFlag) args[0])._$PINPOINT$_getSamplingRateFlag(); + if (samplingRateFlag == null || Boolean.FALSE != samplingRateFlag) { + return false; + } + + if (Boolean.FALSE == (args[0] instanceof HttpClientRequest)) { + return false; + } + + return true; + } + + private boolean validate(final Object[] args) { + if (ArrayUtils.getLength(args) < 1) { + logger.debug("Invalid args object. args={}.", args); + return false; + } + + if (!(args[0] instanceof AsyncContextAccessor)) { + logger.debug("Invalid args[0] object. args[0]={}.", args[0]); + return false; + } + + if (!(args[0] instanceof HttpClientRequest)) { + logger.debug("Invalid args[0] object. {}.", args[0]); + return false; + } + + return true; + } +}