Skip to content

Commit

Permalink
[pinpoint-apm#10656] Add java 11 httpclient plugin
Browse files Browse the repository at this point in the history
  • Loading branch information
jaehong-kim committed Jan 31, 2024
1 parent 591a7c5 commit 37e0927
Show file tree
Hide file tree
Showing 29 changed files with 1,219 additions and 2 deletions.
16 changes: 16 additions & 0 deletions agent-testweb/jdk-httpclient-plugin-testweb/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@

## Install
```
$ mvnw -P pinpoint-jdk-httpclient-plugin-testweb install -Dmaven.test.skip=true
```

## Run
```
$ mvnw -P pinpoint-jdk-httpclient-plugin-testweb spring-boot:start
```
You can then access here: https://localhost:18443/

## Stop
```
$ mvnw -P pinpoint-jdk-httpclient-plugin-testweb spring-boot:stop
```
46 changes: 46 additions & 0 deletions agent-testweb/jdk-httpclient-plugin-testweb/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.navercorp.pinpoint</groupId>
<artifactId>pinpoint-agent-testweb</artifactId>
<version>3.0.0-SNAPSHOT</version>
</parent>

<artifactId>pinpoint-jdk-httpclient-plugin-testweb</artifactId>

<packaging>jar</packaging>

<properties>
<pinpoint.agent.jvmargument>
${pinpoint.agent.default.jvmargument}
</pinpoint.agent.jvmargument>
<jdk.version>11</jdk.version>
<jdk.home>${env.JAVA_11_HOME}</jdk.home>
</properties>

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<dependency>
<groupId>com.navercorp.pinpoint</groupId>
<artifactId>pinpoint-agent-testweb-commons</artifactId>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
/*
* Copyright 2024 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 com.pinpoint.test.common.view.ApiLinkPage;
import com.pinpoint.test.common.view.HrefTag;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.reactive.result.method.RequestMappingInfo;
import org.springframework.web.reactive.result.method.annotation.RequestMappingHandlerMapping;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

@RestController
public class JdkHttpClientPluginController {
private final Logger logger = LogManager.getLogger(this.getClass());

private final RequestMappingHandlerMapping handlerMapping;

@Autowired
public JdkHttpClientPluginController(RequestMappingHandlerMapping handlerMapping) {
this.handlerMapping = handlerMapping;
}

@GetMapping("/")
String welcome() {
Map<RequestMappingInfo, HandlerMethod> handlerMethods = this.handlerMapping.getHandlerMethods();
List<HrefTag> list = new ArrayList<>();
for (RequestMappingInfo info : handlerMethods.keySet()) {
for (String path : info.getDirectPaths()) {
list.add(HrefTag.of(path));
}
}
list.sort(Comparator.comparing(HrefTag::getPath));
return new ApiLinkPage("spring-webflux-plugin-testweb")
.addHrefTag(list)
.build();
}

@GetMapping("/client/get")
public Mono<String> clientGet(ServerWebExchange exchange) throws IOException, InterruptedException {
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.version(HttpClient.Version.HTTP_2)
.uri(URI.create("http://httpbin.org"))
.headers("Accept-Enconding", "gzip, deflate")
.headers("Cookie", "foo-bar")
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());

String responseBody = response.body();
int responseStatusCode = response.statusCode();

return Mono.just(responseStatusCode + " " + responseBody);
}

@GetMapping("/client/retry")
public Mono<String> clientRetry(ServerWebExchange exchange) throws IOException, InterruptedException {
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.version(HttpClient.Version.HTTP_2)
.uri(URI.create("http://naver.com"))
.headers("Accept-Enconding", "gzip, deflate")
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());

String responseBody = response.body();
int responseStatusCode = response.statusCode();

return Mono.just(responseStatusCode + " " + responseBody);
}

@GetMapping("/client/unknown")
public Mono<String> clientUnknown(ServerWebExchange exchange) throws IOException, InterruptedException {
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.version(HttpClient.Version.HTTP_2)
.uri(URI.create("http://fjaklfjkladjfklajlf"))
.headers("Accept-Enconding", "gzip, deflate")
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());

String responseBody = response.body();
int responseStatusCode = response.statusCode();

return Mono.just(responseStatusCode + " " + responseBody);
}

@GetMapping("/client/post")
public Mono<String> clientPost(ServerWebExchange exchange) throws IOException, InterruptedException, URISyntaxException {
HttpClient client = HttpClient.newBuilder()
.version(HttpClient.Version.HTTP_2)
.build();
HttpRequest request = HttpRequest.newBuilder(new URI("http://httpbin.org"))
.version(HttpClient.Version.HTTP_2)
.POST(HttpRequest.BodyPublishers.ofString("Sample Post Request"))
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
String responseBody = response.body();

return Mono.just(responseBody);
}

@GetMapping("/client/async")
public Mono<String> clientAsync(ServerWebExchange exchange) throws IOException, InterruptedException, URISyntaxException {
HttpClient client = HttpClient.newHttpClient();
URI httpURI = new URI("http://httpbin.org");
HttpRequest request = HttpRequest.newBuilder(httpURI)
.version(HttpClient.Version.HTTP_2)
.build();
CompletableFuture<Void> futureResponse = client.sendAsync(request, HttpResponse.BodyHandlers.ofString())
.thenAccept(resp -> {
System.out.println("Got pushed response " + resp.uri());
System.out.println("Response statuscode: " + resp.statusCode());
System.out.println("Response body: " + resp.body());
});
System.out.println("futureResponse" + futureResponse);
return Mono.just(futureResponse.toString());
}

@GetMapping("/client/multi")
public Mono<String> clientMulti(ServerWebExchange exchange) throws IOException, InterruptedException, URISyntaxException {
HttpClient client = HttpClient.newHttpClient();
List<URI> uris = Arrays.asList(new URI("http://httpbin.org"), new URI("http://google.com"));
List<HttpRequest> requests = uris.stream()
.map(HttpRequest::newBuilder)
.map(reqBuilder -> reqBuilder.build())
.collect(Collectors.toList());
System.out.println("Got pushed response1 " + requests);
CompletableFuture.allOf(requests.stream()
.map(request -> client.sendAsync(request, HttpResponse.BodyHandlers.ofString()))
.toArray(CompletableFuture<?>[]::new))
.thenAccept(System.out::println)
.join();
return Mono.just("OK");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* Copyright 2024 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 org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class JdkHttpClientPluginTestStarter {

public static void main(String[] args) {
SpringApplication.run(JdkHttpClientPluginTestStarter.class, args);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Defined in commandlineArgument of agent-test pom.xml

server:
port: 18080

logging:
level:
root: info

springdoc:
swagger-ui:
path: /
1 change: 1 addition & 0 deletions agent-testweb/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
<module>spring-cloud-gateway-plugin-testweb</module>
<module>spring-webflux-plugin-testweb</module>
<module>jdk-http-plugin-testweb</module>
<module>jdk-httpclient-plugin-testweb</module>
<module>vertx-3-plugin-testweb</module>
<module>vertx-4-plugin-testweb</module>
<module>mongodb-plugin-testweb</module>
Expand Down
23 changes: 23 additions & 0 deletions agent/src/main/resources/profiles/local/pinpoint.config
Original file line number Diff line number Diff line change
Expand Up @@ -908,6 +908,29 @@ profiler.apache.httpclient5.entity.statuscode=true
profiler.jdk.http=true
profiler.jdk.http.param=true

# Java 11 version or later
profiler.jdk.httpclient.enable=true
profiler.jdk.httpclient.param=true

# Record cookies.
profiler.jdk.httpclient.cookie=true
# When to dump cookies. Either ALWAYS or EXCEPTION.
profiler.jdk.httpclient.cookie.dumptype=ALWAYS
# 1 out of n cookies will be sampled where n is the rate. (1: 100%)
profiler.jdk.httpclient.cookie.sampling.rate=1
# Cookie dump size.
profiler.jdk.httpclient.cookie.dumpsize=1024

# Record Entities.
profiler.jdk.httpclient.entity=true
# When to dump entities. Either ALWAYS or EXCEPTION.
profiler.jdk.httpclient.entity.dumptype=ALWAYS
# 1 out of n cookies will be sampled where n is the rate. (1: 100%)
profiler.jdk.httpclient.entity.sampling.rate=1
# Entity dump size.
profiler.jdk.httpclient.entity.dumpsize=1024


###########################################################
# Ning Async HTTP Client #
###########################################################
Expand Down
22 changes: 22 additions & 0 deletions agent/src/main/resources/profiles/release/pinpoint.config
Original file line number Diff line number Diff line change
Expand Up @@ -905,6 +905,28 @@ profiler.apache.httpclient5.entity.statuscode=true
profiler.jdk.http=true
profiler.jdk.http.param=true

# Java 11 version or later
profiler.jdk.httpclient.enable=true
profiler.jdk.httpclient.param=true

# Record cookies.
profiler.jdk.httpclient.cookie=false
# When to dump cookies. Either ALWAYS or EXCEPTION.
profiler.jdk.httpclient.cookie.dumptype=EXCEPTION
# 1 out of n cookies will be sampled where n is the rate. (1: 100%)
profiler.jdk.httpclient.cookie.sampling.rate=1
# Cookie dump size.
profiler.jdk.httpclient.cookie.dumpsize=1024

# Record Entities.
profiler.jdk.httpclient.entity=false
# When to dump entities. Either ALWAYS or EXCEPTION.
profiler.jdk.httpclient.entity.dumptype=EXCEPTION
# 1 out of n cookies will be sampled where n is the rate. (1: 100%)
profiler.jdk.httpclient.entity.sampling.rate=1
# Entity dump size.
profiler.jdk.httpclient.entity.dumpsize=1024

###########################################################
# Ning Async HTTP Client #
###########################################################
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,8 @@
* <tr><td>9060</td><td><i>RESERVED</i></td></tr>
* <tr><td>9062</td><td><i>HTTP_CLIENT_5</i></td></tr>
* <tr><td>9063</td><td><i>HTTP_CLIENT_5_INTERNAL</i></td></tr>
* <tr><td>9065</td><td><i>JDK_HTTP_CLIENT</i></td></tr>
* <tr><td>9066</td><td><i>JDK_HTTP_CLIENT_INTERNAL</i></td></tr>
* <tr><td>9070</td><td><i>RESERVED</i></td></tr>
* <tr><td><s>9080</s></td><td><s>APACHE_CXF_CLIENT</s></td></tr>
* <tr><td>9081</td><td>APACHE_CXF_SERVICE_INVOKER</td></tr>
Expand Down
5 changes: 5 additions & 0 deletions plugins/assembly/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,11 @@
<artifactId>pinpoint-jdk-http-plugin</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.navercorp.pinpoint</groupId>
<artifactId>pinpoint-jdk-httpclient-plugin</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.navercorp.pinpoint</groupId>
<artifactId>pinpoint-redis-plugin</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,6 @@ public static class CompletableFutureTransform implements TransformCallback {
public byte[] doInTransform(Instrumentor instrumentor, ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws InstrumentException {
final InstrumentClass target = instrumentor.getInstrumentClass(loader, className, classfileBuffer);
target.addField(AsyncContextAccessor.class);


for (InstrumentMethod method : target.getDeclaredMethods(MethodFilters.name("complete", "join", "cancel", "get"))) {
method.addInterceptor(CompletableFutureMethodInterceptor.class);
}
Expand Down
21 changes: 21 additions & 0 deletions plugins/jdk-httpclient/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
## JDK HttpClient
* Since: Pinpoint 3.0.0
* Range: java [11,]

### Pinpoint Configuration
pinpoint.config

#### HttpClient options.
~~~
# Profile parameter.
profiler.jdk.httpclient.enable=true
profiler.jdk.httpclient.param=true
profiler.jdk.httpclient.cookie=false
profiler.jdk.httpclient.cookie.dumptype=DumpType.EXCEPTION
profiler.jdk.httpclient.cookie.sampling.rate=1
profiler.jdk.httpclient.cookie.dumpsize=1024
profiler.jdk.httpclient.entity=false
profiler.jdk.httpclient.entity.dumptype=DumpType.EXCEPTION
profiler.jdk.httpclient.entity.sampling.rate=1
profiler.jdk.httpclient.entity.dumpsize=1024
~~~
Loading

0 comments on commit 37e0927

Please sign in to comment.