From e83f49116862530f62c2fbecd5d504880a3c30c5 Mon Sep 17 00:00:00 2001 From: enoch Date: Thu, 7 Sep 2023 12:22:15 +0800 Subject: [PATCH 1/4] feat: add httpclient: java.net.HttpURLConnection support --- plugins/httpclient/pom.xml | 5 + ...ttpURLConnectionGetResponseCodeAdvice.java | 43 +++++ ...LConnectionGetResponseCodeInterceptor.java | 162 ++++++++++++++++++ ...nectionGetResponseCodeInterceptorTest.java | 151 ++++++++++++++++ 4 files changed, 361 insertions(+) create mode 100644 plugins/httpclient/src/main/java/com/megaease/easeagent/plugin/httpclient/advice/HttpURLConnectionGetResponseCodeAdvice.java create mode 100644 plugins/httpclient/src/main/java/com/megaease/easeagent/plugin/httpclient/interceptor/HttpURLConnectionGetResponseCodeInterceptor.java create mode 100644 plugins/httpclient/src/test/java/com/megaease/easeagent/plugin/httpclient/interceptor/HttpURLConnectionGetResponseCodeInterceptorTest.java diff --git a/plugins/httpclient/pom.xml b/plugins/httpclient/pom.xml index 9d8332e2c..65de7b9f0 100644 --- a/plugins/httpclient/pom.xml +++ b/plugins/httpclient/pom.xml @@ -35,6 +35,11 @@ plugin-api provided + + com.google.guava + guava + provided + org.apache.httpcomponents httpclient diff --git a/plugins/httpclient/src/main/java/com/megaease/easeagent/plugin/httpclient/advice/HttpURLConnectionGetResponseCodeAdvice.java b/plugins/httpclient/src/main/java/com/megaease/easeagent/plugin/httpclient/advice/HttpURLConnectionGetResponseCodeAdvice.java new file mode 100644 index 000000000..a4a180b02 --- /dev/null +++ b/plugins/httpclient/src/main/java/com/megaease/easeagent/plugin/httpclient/advice/HttpURLConnectionGetResponseCodeAdvice.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2023, MegaEase + * All rights reserved. + * + * 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.megaease.easeagent.plugin.httpclient.advice; + +import com.megaease.easeagent.plugin.Points; +import com.megaease.easeagent.plugin.matcher.ClassMatcher; +import com.megaease.easeagent.plugin.matcher.IClassMatcher; +import com.megaease.easeagent.plugin.matcher.IMethodMatcher; +import com.megaease.easeagent.plugin.matcher.MethodMatcher; + +import java.util.Set; + +public class HttpURLConnectionGetResponseCodeAdvice implements Points { + + @Override + public IClassMatcher getClassMatcher() { + return ClassMatcher.builder() + .hasSuperClass("java.net.HttpURLConnection") + .build(); + } + + @Override + public Set getMethodMatcher() { + return MethodMatcher.multiBuilder() + .match(MethodMatcher.builder().isPublic().named("getResponseCode").build()) + .build(); + } +} diff --git a/plugins/httpclient/src/main/java/com/megaease/easeagent/plugin/httpclient/interceptor/HttpURLConnectionGetResponseCodeInterceptor.java b/plugins/httpclient/src/main/java/com/megaease/easeagent/plugin/httpclient/interceptor/HttpURLConnectionGetResponseCodeInterceptor.java new file mode 100644 index 000000000..68d7c7fdf --- /dev/null +++ b/plugins/httpclient/src/main/java/com/megaease/easeagent/plugin/httpclient/interceptor/HttpURLConnectionGetResponseCodeInterceptor.java @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2023, MegaEase + * All rights reserved. + * + * 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.megaease.easeagent.plugin.httpclient.interceptor; + +import com.google.common.collect.ArrayListMultimap; +import com.google.common.collect.Multimap; +import com.megaease.easeagent.plugin.annotation.AdviceTo; +import com.megaease.easeagent.plugin.api.Context; +import com.megaease.easeagent.plugin.api.trace.Span; +import com.megaease.easeagent.plugin.httpclient.HttpClientPlugin; +import com.megaease.easeagent.plugin.httpclient.advice.HttpURLConnectionGetResponseCodeAdvice; +import com.megaease.easeagent.plugin.interceptor.MethodInfo; +import com.megaease.easeagent.plugin.tools.trace.BaseHttpClientTracingInterceptor; +import com.megaease.easeagent.plugin.tools.trace.HttpRequest; +import com.megaease.easeagent.plugin.tools.trace.HttpResponse; +import lombok.SneakyThrows; + +import java.net.HttpURLConnection; +import java.util.List; +import java.util.Map; + + +@AdviceTo(value = HttpURLConnectionGetResponseCodeAdvice.class, qualifier = "default", plugin = HttpClientPlugin.class) +public class HttpURLConnectionGetResponseCodeInterceptor extends BaseHttpClientTracingInterceptor { + @Override + public Object getProgressKey() { + return HttpURLConnectionGetResponseCodeInterceptor.class; + } + + @Override + protected HttpRequest getRequest(MethodInfo methodInfo, Context context) { + return new InternalRequest((HttpURLConnection) methodInfo.getInvoker()); + } + + + @Override + protected HttpResponse getResponse(MethodInfo methodInfo, Context context) { + return new InternalResponse(methodInfo.getThrowable(), (HttpURLConnection) methodInfo.getInvoker()); + } + + + final static class InternalRequest implements HttpRequest { + + private final HttpURLConnection httpURLConn; + + public InternalRequest(HttpURLConnection httpURLConn) { + this.httpURLConn = httpURLConn; + } + + + @Override + public String method() { + return httpURLConn.getRequestMethod(); + } + + @Override + public String path() { + return httpURLConn.getURL().toString(); + } + + @Override + public String route() { + return null; + } + + @Override + public String getRemoteAddr() { + return null; + } + + @Override + public int getRemotePort() { + return 0; + } + + @Override + public Span.Kind kind() { + return Span.Kind.CLIENT; + } + + @Override + public String header(String name) { + return httpURLConn.getRequestProperty(name); + } + + @Override + public boolean cacheScope() { + return false; + } + + @Override + public void setHeader(String name, String value) { + httpURLConn.setRequestProperty(name, value); + } + + } + + final static class InternalResponse implements HttpResponse { + private final Throwable caught; + private final HttpURLConnection httpURLConn; + private final Multimap headers; + + public InternalResponse(Throwable caught, HttpURLConnection httpURLConn) { + this.caught = caught; + this.httpURLConn = httpURLConn; + this.headers = getResponseHeaders(httpURLConn); + } + + @Override + public String method() { + return httpURLConn.getRequestMethod(); + } + + @Override + public String route() { + return null; + } + + @SneakyThrows + @Override + public int statusCode() { + return this.httpURLConn.getResponseCode(); + } + + @Override + public Throwable maybeError() { + return caught; + } + + + @Override + public String header(String name) { + return this.headers.get(name).stream().findFirst().orElse(null); + + } + + private Multimap getResponseHeaders(HttpURLConnection uc) { + Multimap headers = ArrayListMultimap.create(); + for (Map.Entry> e : uc.getHeaderFields().entrySet()) { + if (e.getKey() != null) { + headers.putAll(e.getKey(), e.getValue()); + } + } + return headers; + } + } +} diff --git a/plugins/httpclient/src/test/java/com/megaease/easeagent/plugin/httpclient/interceptor/HttpURLConnectionGetResponseCodeInterceptorTest.java b/plugins/httpclient/src/test/java/com/megaease/easeagent/plugin/httpclient/interceptor/HttpURLConnectionGetResponseCodeInterceptorTest.java new file mode 100644 index 000000000..6cafe0148 --- /dev/null +++ b/plugins/httpclient/src/test/java/com/megaease/easeagent/plugin/httpclient/interceptor/HttpURLConnectionGetResponseCodeInterceptorTest.java @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2023, Inspireso and/or its affiliates. All rights reserved. + */ + +package com.megaease.easeagent.plugin.httpclient.interceptor; + +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Lists; +import com.google.common.net.HttpHeaders; +import com.megaease.easeagent.mock.plugin.api.MockEaseAgent; +import com.megaease.easeagent.mock.plugin.api.junit.EaseAgentJunit4ClassRunner; +import com.megaease.easeagent.plugin.api.Context; +import com.megaease.easeagent.plugin.api.trace.Scope; +import com.megaease.easeagent.plugin.api.trace.Span; +import com.megaease.easeagent.plugin.bridge.EaseAgent; +import com.megaease.easeagent.plugin.interceptor.MethodInfo; +import com.megaease.easeagent.plugin.report.tracing.ReportSpan; +import com.megaease.easeagent.plugin.tools.trace.HttpRequest; +import com.megaease.easeagent.plugin.tools.trace.HttpResponse; +import lombok.SneakyThrows; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.io.IOException; +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static org.junit.Assert.*; + +@RunWith(EaseAgentJunit4ClassRunner.class) +public class HttpURLConnectionGetResponseCodeInterceptorTest { + + @SneakyThrows + @Test + public void before() { + Context context = EaseAgent.getContext(); + MethodInfo methodInfo = mockMethodInfo(); + + HttpURLConnectionGetResponseCodeInterceptor httpURLConnectionWriteRequestsInterceptor = new HttpURLConnectionGetResponseCodeInterceptor(); + MockEaseAgent.cleanLastSpan(); + httpURLConnectionWriteRequestsInterceptor.before(methodInfo, context); + httpURLConnectionWriteRequestsInterceptor.after(methodInfo, context); + ReportSpan mockSpan = MockEaseAgent.getLastSpan(); + assertNotNull(mockSpan); + assertEquals(Span.Kind.CLIENT.name(), mockSpan.kind()); + assertEquals(TestConst.RESPONSE_TAG_VALUE, mockSpan.tag(TestConst.RESPONSE_TAG_NAME)); + assertNull(mockSpan.parentId()); + + Span span = context.nextSpan(); + try (Scope ignored = span.maybeScope()) { + httpURLConnectionWriteRequestsInterceptor.doBefore(methodInfo, context); + httpURLConnectionWriteRequestsInterceptor.doAfter(methodInfo, context); + mockSpan = MockEaseAgent.getLastSpan(); + assertEquals(span.traceIdString(), mockSpan.traceId()); + assertEquals(span.spanIdString(), mockSpan.parentId()); + assertNotNull(mockSpan.id()); + } + span.abandon(); + } + + @Test + public void after() { + before(); + } + + + @SneakyThrows + @Test + public void getRequest() { + Context context = EaseAgent.getContext(); + MethodInfo methodInfo = mockMethodInfo(); + + HttpURLConnectionGetResponseCodeInterceptor httpClientDoExecuteInterceptor = new HttpURLConnectionGetResponseCodeInterceptor(); + HttpRequest request = httpClientDoExecuteInterceptor.getRequest(methodInfo, context); + assertEquals(Span.Kind.CLIENT, request.kind()); + assertEquals("GET", request.method()); + } + + @SneakyThrows + @Test + public void getResponse() { + Context context = EaseAgent.getContext(); + MethodInfo methodInfo = mockMethodInfo(); + + HttpURLConnectionGetResponseCodeInterceptor httpClientDoExecuteInterceptor = new HttpURLConnectionGetResponseCodeInterceptor(); + + HttpResponse httpResponse = httpClientDoExecuteInterceptor.getResponse(methodInfo, context); + assertEquals(200, httpResponse.statusCode()); + } + + @SneakyThrows + private MethodInfo mockMethodInfo() { + URL url = new URL("http://127.0.0.1:8080"); + Map responseHeader = ImmutableMap.of(TestConst.RESPONSE_TAG_NAME, TestConst.RESPONSE_TAG_VALUE); + HttpURLConnection httpURLConnection = getConnection(url, "GET", null, responseHeader); + MethodInfo methodInfo = MethodInfo.builder() + .invoker(httpURLConnection).retValue(httpURLConnection) + .build(); + return methodInfo; + } + + private static HttpURLConnection getConnection( + URL url, String method, Map requestHeaders, Map responseHeader) throws IOException { + + HttpURLConnection conn = new HttpURLConnection(url) { + + @Override + public void connect() throws IOException { + + } + + @Override + public void disconnect() { + + } + + @Override + public boolean usingProxy() { + return false; + } + + @Override + public int getResponseCode() throws IOException { + return 200; + } + + @Override + public Map> getHeaderFields() { + Map> fields = new HashMap<>(); + for (String key : responseHeader.keySet()) { + fields.put(key, Lists.newArrayList(responseHeader.get(key))); + } + return fields; + } + }; + conn.setRequestMethod(method); + conn.setDoInput(true); + conn.setDoOutput(true); + conn.setRequestProperty(HttpHeaders.HOST, url.getHost()); + if (requestHeaders != null) { + for (String key : requestHeaders.keySet()) { + conn.setRequestProperty(key, requestHeaders.get(key)); + } + } + + return conn; + } +} From 04e82e959cbd87eac927eb5910b95145ff01fb76 Mon Sep 17 00:00:00 2001 From: enoch Date: Mon, 25 Sep 2023 09:49:23 +0800 Subject: [PATCH 2/4] fix: HttpURLConnectionPlugin moved to package com.megaease.easeagent.plugin.httpurlconnection; --- .../plugin/api/config/ConfigConst.java | 1 + plugins/httpclient/pom.xml | 5 -- plugins/httpurlconnection/pom.xml | 50 +++++++++++++++++++ .../httpurlconnection/ForwardedPlugin.java | 33 ++++++++++++ .../HttpURLConnectionPlugin.java | 33 ++++++++++++ ...ttpURLConnectionGetResponseCodeAdvice.java | 2 +- ...LConnectionGetResponseCodeInterceptor.java | 8 +-- ...nectionGetResponseCodeInterceptorTest.java | 17 ++++++- .../interceptor/TestConst.java | 23 +++++++++ .../src/test/resources/mock_agent.properties | 19 +++++++ plugins/pom.xml | 1 + 11 files changed, 180 insertions(+), 12 deletions(-) create mode 100644 plugins/httpurlconnection/pom.xml create mode 100644 plugins/httpurlconnection/src/main/java/com/megaease/easeagent/plugin/httpurlconnection/ForwardedPlugin.java create mode 100644 plugins/httpurlconnection/src/main/java/com/megaease/easeagent/plugin/httpurlconnection/HttpURLConnectionPlugin.java rename plugins/{httpclient/src/main/java/com/megaease/easeagent/plugin/httpclient => httpurlconnection/src/main/java/com/megaease/easeagent/plugin/httpurlconnection}/advice/HttpURLConnectionGetResponseCodeAdvice.java (95%) rename plugins/{httpclient/src/main/java/com/megaease/easeagent/plugin/httpclient => httpurlconnection/src/main/java/com/megaease/easeagent/plugin/httpurlconnection}/interceptor/HttpURLConnectionGetResponseCodeInterceptor.java (93%) rename plugins/{httpclient/src/test/java/com/megaease/easeagent/plugin/httpclient => httpurlconnection/src/test/java/com/megaease/easeagent/plugin/httpurlconnection}/interceptor/HttpURLConnectionGetResponseCodeInterceptorTest.java (88%) create mode 100644 plugins/httpurlconnection/src/test/java/com/megaease/easeagent/plugin/httpurlconnection/interceptor/TestConst.java create mode 100644 plugins/httpurlconnection/src/test/resources/mock_agent.properties diff --git a/plugin-api/src/main/java/com/megaease/easeagent/plugin/api/config/ConfigConst.java b/plugin-api/src/main/java/com/megaease/easeagent/plugin/api/config/ConfigConst.java index 7addef69c..b741cd73e 100644 --- a/plugin-api/src/main/java/com/megaease/easeagent/plugin/api/config/ConfigConst.java +++ b/plugin-api/src/main/java/com/megaease/easeagent/plugin/api/config/ConfigConst.java @@ -159,6 +159,7 @@ interface Namespace { String WEB_CLIENT = "webclient"; String FEIGN_CLIENT = "feignClient"; String REST_TEMPLATE = "resTemplate"; + String HTTPURLCONNECTION = "httpURLConnection"; String FORWARDED = "forwarded"; } diff --git a/plugins/httpclient/pom.xml b/plugins/httpclient/pom.xml index 65de7b9f0..9d8332e2c 100644 --- a/plugins/httpclient/pom.xml +++ b/plugins/httpclient/pom.xml @@ -35,11 +35,6 @@ plugin-api provided - - com.google.guava - guava - provided - org.apache.httpcomponents httpclient diff --git a/plugins/httpurlconnection/pom.xml b/plugins/httpurlconnection/pom.xml new file mode 100644 index 000000000..0a85893e5 --- /dev/null +++ b/plugins/httpurlconnection/pom.xml @@ -0,0 +1,50 @@ + + + + + + plugins + com.megaease.easeagent + 2.2.7 + + 4.0.0 + + httpurlconnection + + + + + com.megaease.easeagent + plugin-api + provided + + + com.google.guava + guava + provided + + + com.megaease.easeagent + plugin-api-mock + ${project.version} + test + + + diff --git a/plugins/httpurlconnection/src/main/java/com/megaease/easeagent/plugin/httpurlconnection/ForwardedPlugin.java b/plugins/httpurlconnection/src/main/java/com/megaease/easeagent/plugin/httpurlconnection/ForwardedPlugin.java new file mode 100644 index 000000000..6bcf4cf20 --- /dev/null +++ b/plugins/httpurlconnection/src/main/java/com/megaease/easeagent/plugin/httpurlconnection/ForwardedPlugin.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2023, MegaEase + * All rights reserved. + * + * 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.megaease.easeagent.plugin.httpurlconnection; + +import com.megaease.easeagent.plugin.AgentPlugin; +import com.megaease.easeagent.plugin.api.config.ConfigConst; + +public class ForwardedPlugin implements AgentPlugin { + @Override + public String getNamespace() { + return ConfigConst.Namespace.FORWARDED; + } + + @Override + public String getDomain() { + return ConfigConst.INTEGRABILITY; + } +} diff --git a/plugins/httpurlconnection/src/main/java/com/megaease/easeagent/plugin/httpurlconnection/HttpURLConnectionPlugin.java b/plugins/httpurlconnection/src/main/java/com/megaease/easeagent/plugin/httpurlconnection/HttpURLConnectionPlugin.java new file mode 100644 index 000000000..efcc97dd2 --- /dev/null +++ b/plugins/httpurlconnection/src/main/java/com/megaease/easeagent/plugin/httpurlconnection/HttpURLConnectionPlugin.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2023, MegaEase + * All rights reserved. + * + * 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.megaease.easeagent.plugin.httpurlconnection; + +import com.megaease.easeagent.plugin.AgentPlugin; +import com.megaease.easeagent.plugin.api.config.ConfigConst; + +public class HttpURLConnectionPlugin implements AgentPlugin { + @Override + public String getNamespace() { + return ConfigConst.Namespace.HTTPURLCONNECTION; + } + + @Override + public String getDomain() { + return ConfigConst.OBSERVABILITY; + } +} diff --git a/plugins/httpclient/src/main/java/com/megaease/easeagent/plugin/httpclient/advice/HttpURLConnectionGetResponseCodeAdvice.java b/plugins/httpurlconnection/src/main/java/com/megaease/easeagent/plugin/httpurlconnection/advice/HttpURLConnectionGetResponseCodeAdvice.java similarity index 95% rename from plugins/httpclient/src/main/java/com/megaease/easeagent/plugin/httpclient/advice/HttpURLConnectionGetResponseCodeAdvice.java rename to plugins/httpurlconnection/src/main/java/com/megaease/easeagent/plugin/httpurlconnection/advice/HttpURLConnectionGetResponseCodeAdvice.java index a4a180b02..1a1156117 100644 --- a/plugins/httpclient/src/main/java/com/megaease/easeagent/plugin/httpclient/advice/HttpURLConnectionGetResponseCodeAdvice.java +++ b/plugins/httpurlconnection/src/main/java/com/megaease/easeagent/plugin/httpurlconnection/advice/HttpURLConnectionGetResponseCodeAdvice.java @@ -15,7 +15,7 @@ * limitations under the License. */ -package com.megaease.easeagent.plugin.httpclient.advice; +package com.megaease.easeagent.plugin.httpurlconnection.advice; import com.megaease.easeagent.plugin.Points; import com.megaease.easeagent.plugin.matcher.ClassMatcher; diff --git a/plugins/httpclient/src/main/java/com/megaease/easeagent/plugin/httpclient/interceptor/HttpURLConnectionGetResponseCodeInterceptor.java b/plugins/httpurlconnection/src/main/java/com/megaease/easeagent/plugin/httpurlconnection/interceptor/HttpURLConnectionGetResponseCodeInterceptor.java similarity index 93% rename from plugins/httpclient/src/main/java/com/megaease/easeagent/plugin/httpclient/interceptor/HttpURLConnectionGetResponseCodeInterceptor.java rename to plugins/httpurlconnection/src/main/java/com/megaease/easeagent/plugin/httpurlconnection/interceptor/HttpURLConnectionGetResponseCodeInterceptor.java index 68d7c7fdf..a4f99d0a0 100644 --- a/plugins/httpclient/src/main/java/com/megaease/easeagent/plugin/httpclient/interceptor/HttpURLConnectionGetResponseCodeInterceptor.java +++ b/plugins/httpurlconnection/src/main/java/com/megaease/easeagent/plugin/httpurlconnection/interceptor/HttpURLConnectionGetResponseCodeInterceptor.java @@ -15,15 +15,15 @@ * limitations under the License. */ -package com.megaease.easeagent.plugin.httpclient.interceptor; +package com.megaease.easeagent.plugin.httpurlconnection.interceptor; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.Multimap; import com.megaease.easeagent.plugin.annotation.AdviceTo; import com.megaease.easeagent.plugin.api.Context; import com.megaease.easeagent.plugin.api.trace.Span; -import com.megaease.easeagent.plugin.httpclient.HttpClientPlugin; -import com.megaease.easeagent.plugin.httpclient.advice.HttpURLConnectionGetResponseCodeAdvice; +import com.megaease.easeagent.plugin.httpurlconnection.HttpURLConnectionPlugin; +import com.megaease.easeagent.plugin.httpurlconnection.advice.HttpURLConnectionGetResponseCodeAdvice; import com.megaease.easeagent.plugin.interceptor.MethodInfo; import com.megaease.easeagent.plugin.tools.trace.BaseHttpClientTracingInterceptor; import com.megaease.easeagent.plugin.tools.trace.HttpRequest; @@ -35,7 +35,7 @@ import java.util.Map; -@AdviceTo(value = HttpURLConnectionGetResponseCodeAdvice.class, qualifier = "default", plugin = HttpClientPlugin.class) +@AdviceTo(value = HttpURLConnectionGetResponseCodeAdvice.class, qualifier = "default", plugin = HttpURLConnectionPlugin.class) public class HttpURLConnectionGetResponseCodeInterceptor extends BaseHttpClientTracingInterceptor { @Override public Object getProgressKey() { diff --git a/plugins/httpclient/src/test/java/com/megaease/easeagent/plugin/httpclient/interceptor/HttpURLConnectionGetResponseCodeInterceptorTest.java b/plugins/httpurlconnection/src/test/java/com/megaease/easeagent/plugin/httpurlconnection/interceptor/HttpURLConnectionGetResponseCodeInterceptorTest.java similarity index 88% rename from plugins/httpclient/src/test/java/com/megaease/easeagent/plugin/httpclient/interceptor/HttpURLConnectionGetResponseCodeInterceptorTest.java rename to plugins/httpurlconnection/src/test/java/com/megaease/easeagent/plugin/httpurlconnection/interceptor/HttpURLConnectionGetResponseCodeInterceptorTest.java index 6cafe0148..84119d2f3 100644 --- a/plugins/httpclient/src/test/java/com/megaease/easeagent/plugin/httpclient/interceptor/HttpURLConnectionGetResponseCodeInterceptorTest.java +++ b/plugins/httpurlconnection/src/test/java/com/megaease/easeagent/plugin/httpurlconnection/interceptor/HttpURLConnectionGetResponseCodeInterceptorTest.java @@ -1,8 +1,21 @@ /* - * Copyright (c) 2023, Inspireso and/or its affiliates. All rights reserved. + * Copyright (c) 2023, MegaEase + * All rights reserved. + * + * 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.megaease.easeagent.plugin.httpclient.interceptor; +package com.megaease.easeagent.plugin.httpurlconnection.interceptor; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Lists; diff --git a/plugins/httpurlconnection/src/test/java/com/megaease/easeagent/plugin/httpurlconnection/interceptor/TestConst.java b/plugins/httpurlconnection/src/test/java/com/megaease/easeagent/plugin/httpurlconnection/interceptor/TestConst.java new file mode 100644 index 000000000..89c4fee04 --- /dev/null +++ b/plugins/httpurlconnection/src/test/java/com/megaease/easeagent/plugin/httpurlconnection/interceptor/TestConst.java @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2021, MegaEase + * All rights reserved. + * + * 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.megaease.easeagent.plugin.httpurlconnection.interceptor; + +public class TestConst { + public static final String RESPONSE_TAG_NAME = "X-EG-Test"; + public static final String RESPONSE_TAG_VALUE = "X-EG-Test-Value"; +} diff --git a/plugins/httpurlconnection/src/test/resources/mock_agent.properties b/plugins/httpurlconnection/src/test/resources/mock_agent.properties new file mode 100644 index 000000000..8fb0c2983 --- /dev/null +++ b/plugins/httpurlconnection/src/test/resources/mock_agent.properties @@ -0,0 +1,19 @@ +# +# Copyright (c) 2023, MegaEase +# All rights reserved. +# +# 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. +# + +easeagent.progress.forwarded.headers=X-Forwarded-For +observability.tracings.tag.response.headers.eg.0=X-EG-Test diff --git a/plugins/pom.xml b/plugins/pom.xml index d81a14cca..85caab04b 100644 --- a/plugins/pom.xml +++ b/plugins/pom.xml @@ -52,6 +52,7 @@ dubbo motan sofarpc + httpurlconnection From b131bcca124339a87b12226f6f3272ac5b5e407d Mon Sep 17 00:00:00 2001 From: enoch Date: Mon, 25 Sep 2023 10:55:35 +0800 Subject: [PATCH 3/4] feat: add httpURLConnection plugin config --- build/src/main/resources/agent.properties | 2 ++ 1 file changed, 2 insertions(+) diff --git a/build/src/main/resources/agent.properties b/build/src/main/resources/agent.properties index d25ae84ec..5e65afe82 100644 --- a/build/src/main/resources/agent.properties +++ b/build/src/main/resources/agent.properties @@ -214,6 +214,8 @@ plugin.observability.redis.metric.url=/platform-metrics # plugin.observability.feignClient.tracing.enabled=true ## restTemplate tracing # plugin.observability.restTemplate.tracing.enabled=true +## httpURLConnection tracing +# plugin.observability.httpURLConnection.tracing.enabled=true # -------------------- service name --------------------- ## add service name to header by name for easemesh. default name: X-Mesh-RPC-Service From f2cb5b7d45e20c1849c1b5f7039e5fa9f2b2e1e9 Mon Sep 17 00:00:00 2001 From: enoch Date: Mon, 25 Sep 2023 10:57:02 +0800 Subject: [PATCH 4/4] feat: add forwarded plugin for independent from Trace --- ...onGetResponseCodeForwardedInterceptor.java | 50 +++++++++ ...tResponseCodeForwardedInterceptorTest.java | 56 ++++++++++ ...nectionGetResponseCodeInterceptorTest.java | 76 +------------ .../interceptor/TestConst.java | 23 ---- .../interceptor/TestUtils.java | 105 ++++++++++++++++++ 5 files changed, 215 insertions(+), 95 deletions(-) create mode 100644 plugins/httpurlconnection/src/main/java/com/megaease/easeagent/plugin/httpurlconnection/interceptor/HttpURLConnectionGetResponseCodeForwardedInterceptor.java create mode 100644 plugins/httpurlconnection/src/test/java/com/megaease/easeagent/plugin/httpurlconnection/interceptor/HttpURLConnectionGetResponseCodeForwardedInterceptorTest.java delete mode 100644 plugins/httpurlconnection/src/test/java/com/megaease/easeagent/plugin/httpurlconnection/interceptor/TestConst.java create mode 100644 plugins/httpurlconnection/src/test/java/com/megaease/easeagent/plugin/httpurlconnection/interceptor/TestUtils.java diff --git a/plugins/httpurlconnection/src/main/java/com/megaease/easeagent/plugin/httpurlconnection/interceptor/HttpURLConnectionGetResponseCodeForwardedInterceptor.java b/plugins/httpurlconnection/src/main/java/com/megaease/easeagent/plugin/httpurlconnection/interceptor/HttpURLConnectionGetResponseCodeForwardedInterceptor.java new file mode 100644 index 000000000..24ea16a36 --- /dev/null +++ b/plugins/httpurlconnection/src/main/java/com/megaease/easeagent/plugin/httpurlconnection/interceptor/HttpURLConnectionGetResponseCodeForwardedInterceptor.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2023, MegaEase + * All rights reserved. + * + * 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.megaease.easeagent.plugin.httpurlconnection.interceptor; + +import com.megaease.easeagent.plugin.annotation.AdviceTo; +import com.megaease.easeagent.plugin.api.Context; +import com.megaease.easeagent.plugin.api.config.ConfigConst; +import com.megaease.easeagent.plugin.enums.Order; +import com.megaease.easeagent.plugin.httpurlconnection.ForwardedPlugin; +import com.megaease.easeagent.plugin.httpurlconnection.HttpURLConnectionPlugin; +import com.megaease.easeagent.plugin.httpurlconnection.advice.HttpURLConnectionGetResponseCodeAdvice; +import com.megaease.easeagent.plugin.interceptor.Interceptor; +import com.megaease.easeagent.plugin.interceptor.MethodInfo; + +import java.net.HttpURLConnection; + +@AdviceTo(value = HttpURLConnectionGetResponseCodeAdvice.class, qualifier = "default", plugin = ForwardedPlugin.class) +public class HttpURLConnectionGetResponseCodeForwardedInterceptor implements Interceptor { + + @Override + public void before(MethodInfo methodInfo, Context context) { + HttpURLConnection httpURLConnection = (HttpURLConnection) methodInfo.getInvoker(); + context.injectForwardedHeaders(httpURLConnection::setRequestProperty); + } + + @Override + public String getType() { + return ConfigConst.PluginID.FORWARDED; + } + + @Override + public int order() { + return Order.FORWARDED.getOrder(); + } +} diff --git a/plugins/httpurlconnection/src/test/java/com/megaease/easeagent/plugin/httpurlconnection/interceptor/HttpURLConnectionGetResponseCodeForwardedInterceptorTest.java b/plugins/httpurlconnection/src/test/java/com/megaease/easeagent/plugin/httpurlconnection/interceptor/HttpURLConnectionGetResponseCodeForwardedInterceptorTest.java new file mode 100644 index 000000000..fb39ec55d --- /dev/null +++ b/plugins/httpurlconnection/src/test/java/com/megaease/easeagent/plugin/httpurlconnection/interceptor/HttpURLConnectionGetResponseCodeForwardedInterceptorTest.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2023, MegaEase + * All rights reserved. + * + * 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.megaease.easeagent.plugin.httpurlconnection.interceptor; + +import com.megaease.easeagent.mock.plugin.api.junit.EaseAgentJunit4ClassRunner; +import com.megaease.easeagent.plugin.api.Context; +import com.megaease.easeagent.plugin.api.config.ConfigConst; +import com.megaease.easeagent.plugin.bridge.EaseAgent; +import com.megaease.easeagent.plugin.interceptor.MethodInfo; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.net.HttpURLConnection; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +@RunWith(EaseAgentJunit4ClassRunner.class) +public class HttpURLConnectionGetResponseCodeForwardedInterceptorTest { + + @Test + public void before() { + Context context = EaseAgent.getContext(); + HttpURLConnection conn = TestUtils.mockHttpURLConnection(); + MethodInfo methodInfo = TestUtils.mockMethodInfo(conn); + HttpURLConnectionGetResponseCodeForwardedInterceptor httpClientDoExecuteForwardedInterceptor = new HttpURLConnectionGetResponseCodeForwardedInterceptor(); + + httpClientDoExecuteForwardedInterceptor.before(methodInfo, context); + assertNull(conn.getRequestProperty(TestUtils.FORWARDED_NAME)); + context.put(TestUtils.FORWARDED_NAME, TestUtils.FORWARDED_VALUE); + httpClientDoExecuteForwardedInterceptor.before(methodInfo, context); + assertEquals(TestUtils.FORWARDED_VALUE, conn.getRequestProperty(TestUtils.FORWARDED_NAME)); + context.remove(TestUtils.FORWARDED_NAME); + } + + @Test + public void getType() { + HttpURLConnectionGetResponseCodeForwardedInterceptor httpClientDoExecuteForwardedInterceptor = new HttpURLConnectionGetResponseCodeForwardedInterceptor(); + assertEquals(ConfigConst.PluginID.FORWARDED, httpClientDoExecuteForwardedInterceptor.getType()); + } +} diff --git a/plugins/httpurlconnection/src/test/java/com/megaease/easeagent/plugin/httpurlconnection/interceptor/HttpURLConnectionGetResponseCodeInterceptorTest.java b/plugins/httpurlconnection/src/test/java/com/megaease/easeagent/plugin/httpurlconnection/interceptor/HttpURLConnectionGetResponseCodeInterceptorTest.java index 84119d2f3..54d6d0aa0 100644 --- a/plugins/httpurlconnection/src/test/java/com/megaease/easeagent/plugin/httpurlconnection/interceptor/HttpURLConnectionGetResponseCodeInterceptorTest.java +++ b/plugins/httpurlconnection/src/test/java/com/megaease/easeagent/plugin/httpurlconnection/interceptor/HttpURLConnectionGetResponseCodeInterceptorTest.java @@ -17,9 +17,6 @@ package com.megaease.easeagent.plugin.httpurlconnection.interceptor; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.Lists; -import com.google.common.net.HttpHeaders; import com.megaease.easeagent.mock.plugin.api.MockEaseAgent; import com.megaease.easeagent.mock.plugin.api.junit.EaseAgentJunit4ClassRunner; import com.megaease.easeagent.plugin.api.Context; @@ -34,13 +31,6 @@ import org.junit.Test; import org.junit.runner.RunWith; -import java.io.IOException; -import java.net.HttpURLConnection; -import java.net.URL; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - import static org.junit.Assert.*; @RunWith(EaseAgentJunit4ClassRunner.class) @@ -50,7 +40,7 @@ public class HttpURLConnectionGetResponseCodeInterceptorTest { @Test public void before() { Context context = EaseAgent.getContext(); - MethodInfo methodInfo = mockMethodInfo(); + MethodInfo methodInfo = TestUtils.mockMethodInfo(); HttpURLConnectionGetResponseCodeInterceptor httpURLConnectionWriteRequestsInterceptor = new HttpURLConnectionGetResponseCodeInterceptor(); MockEaseAgent.cleanLastSpan(); @@ -59,7 +49,7 @@ public void before() { ReportSpan mockSpan = MockEaseAgent.getLastSpan(); assertNotNull(mockSpan); assertEquals(Span.Kind.CLIENT.name(), mockSpan.kind()); - assertEquals(TestConst.RESPONSE_TAG_VALUE, mockSpan.tag(TestConst.RESPONSE_TAG_NAME)); + assertEquals(TestUtils.RESPONSE_TAG_VALUE, mockSpan.tag(TestUtils.RESPONSE_TAG_NAME)); assertNull(mockSpan.parentId()); Span span = context.nextSpan(); @@ -84,7 +74,7 @@ public void after() { @Test public void getRequest() { Context context = EaseAgent.getContext(); - MethodInfo methodInfo = mockMethodInfo(); + MethodInfo methodInfo = TestUtils.mockMethodInfo(); HttpURLConnectionGetResponseCodeInterceptor httpClientDoExecuteInterceptor = new HttpURLConnectionGetResponseCodeInterceptor(); HttpRequest request = httpClientDoExecuteInterceptor.getRequest(methodInfo, context); @@ -96,69 +86,11 @@ public void getRequest() { @Test public void getResponse() { Context context = EaseAgent.getContext(); - MethodInfo methodInfo = mockMethodInfo(); + MethodInfo methodInfo = TestUtils.mockMethodInfo(); HttpURLConnectionGetResponseCodeInterceptor httpClientDoExecuteInterceptor = new HttpURLConnectionGetResponseCodeInterceptor(); HttpResponse httpResponse = httpClientDoExecuteInterceptor.getResponse(methodInfo, context); assertEquals(200, httpResponse.statusCode()); } - - @SneakyThrows - private MethodInfo mockMethodInfo() { - URL url = new URL("http://127.0.0.1:8080"); - Map responseHeader = ImmutableMap.of(TestConst.RESPONSE_TAG_NAME, TestConst.RESPONSE_TAG_VALUE); - HttpURLConnection httpURLConnection = getConnection(url, "GET", null, responseHeader); - MethodInfo methodInfo = MethodInfo.builder() - .invoker(httpURLConnection).retValue(httpURLConnection) - .build(); - return methodInfo; - } - - private static HttpURLConnection getConnection( - URL url, String method, Map requestHeaders, Map responseHeader) throws IOException { - - HttpURLConnection conn = new HttpURLConnection(url) { - - @Override - public void connect() throws IOException { - - } - - @Override - public void disconnect() { - - } - - @Override - public boolean usingProxy() { - return false; - } - - @Override - public int getResponseCode() throws IOException { - return 200; - } - - @Override - public Map> getHeaderFields() { - Map> fields = new HashMap<>(); - for (String key : responseHeader.keySet()) { - fields.put(key, Lists.newArrayList(responseHeader.get(key))); - } - return fields; - } - }; - conn.setRequestMethod(method); - conn.setDoInput(true); - conn.setDoOutput(true); - conn.setRequestProperty(HttpHeaders.HOST, url.getHost()); - if (requestHeaders != null) { - for (String key : requestHeaders.keySet()) { - conn.setRequestProperty(key, requestHeaders.get(key)); - } - } - - return conn; - } } diff --git a/plugins/httpurlconnection/src/test/java/com/megaease/easeagent/plugin/httpurlconnection/interceptor/TestConst.java b/plugins/httpurlconnection/src/test/java/com/megaease/easeagent/plugin/httpurlconnection/interceptor/TestConst.java deleted file mode 100644 index 89c4fee04..000000000 --- a/plugins/httpurlconnection/src/test/java/com/megaease/easeagent/plugin/httpurlconnection/interceptor/TestConst.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (c) 2021, MegaEase - * All rights reserved. - * - * 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.megaease.easeagent.plugin.httpurlconnection.interceptor; - -public class TestConst { - public static final String RESPONSE_TAG_NAME = "X-EG-Test"; - public static final String RESPONSE_TAG_VALUE = "X-EG-Test-Value"; -} diff --git a/plugins/httpurlconnection/src/test/java/com/megaease/easeagent/plugin/httpurlconnection/interceptor/TestUtils.java b/plugins/httpurlconnection/src/test/java/com/megaease/easeagent/plugin/httpurlconnection/interceptor/TestUtils.java new file mode 100644 index 000000000..4f7fa4f04 --- /dev/null +++ b/plugins/httpurlconnection/src/test/java/com/megaease/easeagent/plugin/httpurlconnection/interceptor/TestUtils.java @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2023, MegaEase + * All rights reserved. + * + * 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.megaease.easeagent.plugin.httpurlconnection.interceptor; + +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Lists; +import com.google.common.net.HttpHeaders; +import com.megaease.easeagent.plugin.interceptor.MethodInfo; +import lombok.SneakyThrows; + +import java.io.IOException; +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +final class TestUtils { + public static final String FORWARDED_NAME = "X-Forwarded-For"; + public static final String FORWARDED_VALUE = "testForwarded"; + public static final String RESPONSE_TAG_NAME = "X-EG-Test"; + public static final String RESPONSE_TAG_VALUE = "X-EG-Test-Value"; + + @SneakyThrows + static MethodInfo mockMethodInfo() { + HttpURLConnection httpURLConnection = mockHttpURLConnection(); + return mockMethodInfo(httpURLConnection); + } + + static MethodInfo mockMethodInfo(HttpURLConnection httpURLConnection) { + MethodInfo methodInfo = MethodInfo.builder() + .invoker(httpURLConnection).retValue(httpURLConnection) + .build(); + return methodInfo; + } + + @SneakyThrows + static HttpURLConnection mockHttpURLConnection() { + URL url = new URL("http://127.0.0.1:8080"); + Map responseHeader = ImmutableMap.of(TestUtils.RESPONSE_TAG_NAME, TestUtils.RESPONSE_TAG_VALUE); + return getConnection(url, "GET", null, responseHeader); + } + + static HttpURLConnection getConnection( + URL url, String method, Map requestHeaders, Map responseHeader) throws IOException { + + HttpURLConnection conn = new HttpURLConnection(url) { + + @Override + public void connect() throws IOException { + + } + + @Override + public void disconnect() { + + } + + @Override + public boolean usingProxy() { + return false; + } + + @Override + public int getResponseCode() throws IOException { + return 200; + } + + @Override + public Map> getHeaderFields() { + Map> fields = new HashMap<>(); + for (String key : responseHeader.keySet()) { + fields.put(key, Lists.newArrayList(responseHeader.get(key))); + } + return fields; + } + }; + conn.setRequestMethod(method); + conn.setDoInput(true); + conn.setDoOutput(true); + conn.setRequestProperty(HttpHeaders.HOST, url.getHost()); + if (requestHeaders != null) { + for (String key : requestHeaders.keySet()) { + conn.setRequestProperty(key, requestHeaders.get(key)); + } + } + + return conn; + } +}