From 96686722056b7fbbb9a7af664643748b2bbd295a Mon Sep 17 00:00:00 2001 From: xbkaishui Date: Sat, 31 Oct 2020 23:49:15 +0800 Subject: [PATCH] add http client parameter collector (#5756) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * add http client parameter collector * Update CHANGES.md Co-authored-by: kezhenxu94 Co-authored-by: 吴晟 Wu Sheng --- CHANGES.md | 1 + .../httpClient-4.x-plugin/pom.xml | 6 +++ .../v4/HttpClientExecuteInterceptor.java | 32 ++++++++++++-- .../v4/HttpClientExecuteInterceptorTest.java | 13 ++++-- .../httpasyncclient-4.x-plugin/pom.xml | 6 +++ .../HttpAsyncRequestExecutorInterceptor.java | 19 ++++++++ .../v4/HttpAsyncClientInterceptorTest.java | 5 +++ .../httpclient-3.x-plugin/pom.xml | 6 +++ .../v3/HttpClientExecuteInterceptor.java | 43 +++++++++++++------ .../apm-sdk-plugin/httpclient-commons/pom.xml | 40 +++++++++++++++++ .../httpclient/HttpClientPluginConfig.java | 43 +++++++++++++++++++ apm-sniffer/apm-sdk-plugin/pom.xml | 1 + .../setup/service-agent/java-agent/README.md | 1 + .../config/expectedData.yaml | 7 ++- .../httpclient-3.x-scenario/configuration.yml | 2 +- .../apm/testcase/httpclient/CaseServlet.java | 2 +- 16 files changed, 203 insertions(+), 24 deletions(-) create mode 100644 apm-sniffer/apm-sdk-plugin/httpclient-commons/pom.xml create mode 100644 apm-sniffer/apm-sdk-plugin/httpclient-commons/src/main/java/org/apache/skywalking/apm/plugin/httpclient/HttpClientPluginConfig.java diff --git a/CHANGES.md b/CHANGES.md index 163c07732b..7fff1356c1 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -7,6 +7,7 @@ Release Notes. #### Project #### Java Agent +* Make HttpClient 3.x, 4.x, and HttpAsyncClient 3.x plugins to support collecting HTTP parameters. * Make the Feign plugin to support Java 14 * Make the okhttp3 plugin to support Java 14 diff --git a/apm-sniffer/apm-sdk-plugin/httpClient-4.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/httpClient-4.x-plugin/pom.xml index 307cb28351..5fd641b5fe 100644 --- a/apm-sniffer/apm-sdk-plugin/httpClient-4.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/httpClient-4.x-plugin/pom.xml @@ -45,6 +45,12 @@ provided + + org.apache.skywalking + apm-httpclient-commons + ${project.version} + provided + junit diff --git a/apm-sniffer/apm-sdk-plugin/httpClient-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/httpClient/v4/HttpClientExecuteInterceptor.java b/apm-sniffer/apm-sdk-plugin/httpClient-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/httpClient/v4/HttpClientExecuteInterceptor.java index d84f862665..38edb702df 100644 --- a/apm-sniffer/apm-sdk-plugin/httpClient-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/httpClient/v4/HttpClientExecuteInterceptor.java +++ b/apm-sniffer/apm-sdk-plugin/httpClient-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/httpClient/v4/HttpClientExecuteInterceptor.java @@ -20,11 +20,14 @@ package org.apache.skywalking.apm.plugin.httpClient.v4; import java.lang.reflect.Method; import java.net.MalformedURLException; +import java.net.URI; import java.net.URL; + import org.apache.http.HttpHost; import org.apache.http.HttpRequest; import org.apache.http.HttpResponse; import org.apache.http.StatusLine; +import org.apache.http.client.methods.HttpUriRequest; import org.apache.skywalking.apm.agent.core.context.CarrierItem; import org.apache.skywalking.apm.agent.core.context.ContextCarrier; import org.apache.skywalking.apm.agent.core.context.ContextManager; @@ -35,12 +38,14 @@ import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedI import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor; import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult; import org.apache.skywalking.apm.network.trace.component.ComponentsDefine; +import org.apache.skywalking.apm.plugin.httpclient.HttpClientPluginConfig; +import org.apache.skywalking.apm.util.StringUtil; public class HttpClientExecuteInterceptor implements InstanceMethodsAroundInterceptor { @Override public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, - MethodInterceptResult result) throws Throwable { + MethodInterceptResult result) throws Throwable { if (allArguments[0] == null || allArguments[1] == null) { // illegal args, can't trace. ignore. return; @@ -66,11 +71,14 @@ public class HttpClientExecuteInterceptor implements InstanceMethodsAroundInterc next = next.next(); httpRequest.setHeader(next.getHeadKey(), next.getHeadValue()); } + if (HttpClientPluginConfig.Plugin.HttpClient.COLLECT_HTTP_PARAMS) { + collectHttpParam(httpRequest, span); + } } @Override public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, - Object ret) throws Throwable { + Object ret) throws Throwable { if (allArguments[0] == null || allArguments[1] == null) { return ret; } @@ -85,6 +93,11 @@ public class HttpClientExecuteInterceptor implements InstanceMethodsAroundInterc span.errorOccurred(); Tags.STATUS_CODE.set(span, Integer.toString(statusCode)); } + HttpRequest httpRequest = (HttpRequest) allArguments[1]; + // Active HTTP parameter collection automatically in the profiling context. + if (!HttpClientPluginConfig.Plugin.HttpClient.COLLECT_HTTP_PARAMS && span.isProfiling()) { + collectHttpParam(httpRequest, span); + } } } @@ -94,7 +107,7 @@ public class HttpClientExecuteInterceptor implements InstanceMethodsAroundInterc @Override public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, - Class[] argumentsTypes, Throwable t) { + Class[] argumentsTypes, Throwable t) { AbstractSpan activeSpan = ContextManager.activeSpan(); activeSpan.log(t); } @@ -132,4 +145,17 @@ public class HttpClientExecuteInterceptor implements InstanceMethodsAroundInterc int port = httpHost.getPort(); return port > 0 ? port : "https".equals(httpHost.getSchemeName().toLowerCase()) ? 443 : 80; } + + private void collectHttpParam(HttpRequest httpRequest, AbstractSpan span) { + if (httpRequest instanceof HttpUriRequest) { + URI uri = ((HttpUriRequest) httpRequest).getURI(); + String tagValue = uri.getQuery(); + if (StringUtil.isNotEmpty(tagValue)) { + tagValue = HttpClientPluginConfig.Plugin.Http.HTTP_PARAMS_LENGTH_THRESHOLD > 0 ? + StringUtil.cut(tagValue, HttpClientPluginConfig.Plugin.Http.HTTP_PARAMS_LENGTH_THRESHOLD) : + tagValue; + Tags.HTTP.PARAMS.set(span, tagValue); + } + } + } } diff --git a/apm-sniffer/apm-sdk-plugin/httpClient-4.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/httpClient/v4/HttpClientExecuteInterceptorTest.java b/apm-sniffer/apm-sdk-plugin/httpClient-4.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/httpClient/v4/HttpClientExecuteInterceptorTest.java index 7270989837..4e139e735a 100644 --- a/apm-sniffer/apm-sdk-plugin/httpClient-4.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/httpClient/v4/HttpClientExecuteInterceptorTest.java +++ b/apm-sniffer/apm-sdk-plugin/httpClient-4.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/httpClient/v4/HttpClientExecuteInterceptorTest.java @@ -18,13 +18,14 @@ package org.apache.skywalking.apm.plugin.httpClient.v4; +import java.net.URI; import java.util.List; import org.apache.http.HttpHost; -import org.apache.http.HttpRequest; import org.apache.http.HttpResponse; import org.apache.http.ProtocolVersion; import org.apache.http.RequestLine; import org.apache.http.StatusLine; +import org.apache.http.client.methods.HttpGet; import org.apache.skywalking.apm.agent.core.boot.ServiceManager; import org.apache.skywalking.apm.agent.core.context.trace.AbstractTracingSpan; import org.apache.skywalking.apm.agent.core.context.trace.LogDataEntity; @@ -37,6 +38,7 @@ import org.apache.skywalking.apm.agent.test.tools.AgentServiceRule; import org.apache.skywalking.apm.agent.test.tools.SegmentStorage; import org.apache.skywalking.apm.agent.test.tools.SegmentStoragePoint; import org.apache.skywalking.apm.agent.test.tools.TracingSegmentRunner; +import org.apache.skywalking.apm.plugin.httpclient.HttpClientPluginConfig; import org.hamcrest.CoreMatchers; import org.junit.Assert; import org.junit.Before; @@ -72,7 +74,7 @@ public class HttpClientExecuteInterceptorTest { @Mock private HttpHost httpHost; @Mock - private HttpRequest request; + private HttpGet request; @Mock private HttpResponse httpResponse; @Mock @@ -89,6 +91,7 @@ public class HttpClientExecuteInterceptorTest { ServiceManager.INSTANCE.boot(); httpClientExecuteInterceptor = new HttpClientExecuteInterceptor(); + HttpClientPluginConfig.Plugin.HttpClient.COLLECT_HTTP_PARAMS = true; PowerMockito.mock(HttpHost.class); when(statusLine.getStatusCode()).thenReturn(200); @@ -112,6 +115,7 @@ public class HttpClientExecuteInterceptorTest { } }); when(httpHost.getPort()).thenReturn(8080); + when(request.getURI()).thenReturn(new URI("http://127.0.0.1:8080/test-web/test?a=1&b=test")); allArguments = new Object[] { httpHost, @@ -149,8 +153,8 @@ public class HttpClientExecuteInterceptorTest { assertThat(spans.size(), is(1)); List tags = SpanHelper.getTags(spans.get(0)); - assertThat(tags.size(), is(3)); - assertThat(tags.get(2).getValue(), is("500")); + assertThat(tags.size(), is(4)); + assertThat(tags.get(3).getValue(), is("500")); assertHttpSpan(spans.get(0)); assertThat(SpanHelper.getErrorOccurred(spans.get(0)), is(true)); @@ -223,6 +227,7 @@ public class HttpClientExecuteInterceptorTest { List tags = SpanHelper.getTags(span); assertThat(tags.get(0).getValue(), is("http://127.0.0.1:8080/test-web/test")); assertThat(tags.get(1).getValue(), is("GET")); + assertThat(tags.get(2).getValue(), is("a=1&b=test")); assertThat(span.isExit(), is(true)); } diff --git a/apm-sniffer/apm-sdk-plugin/httpasyncclient-4.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/httpasyncclient-4.x-plugin/pom.xml index 356cfdb3d2..46c97f5e7d 100644 --- a/apm-sniffer/apm-sdk-plugin/httpasyncclient-4.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/httpasyncclient-4.x-plugin/pom.xml @@ -42,5 +42,11 @@ ${apache-httpasyncclient.version} provided + + org.apache.skywalking + apm-httpclient-commons + ${project.version} + provided + diff --git a/apm-sniffer/apm-sdk-plugin/httpasyncclient-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/httpasyncclient/v4/HttpAsyncRequestExecutorInterceptor.java b/apm-sniffer/apm-sdk-plugin/httpasyncclient-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/httpasyncclient/v4/HttpAsyncRequestExecutorInterceptor.java index 0df1d23fbe..f89409eac9 100644 --- a/apm-sniffer/apm-sdk-plugin/httpasyncclient-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/httpasyncclient/v4/HttpAsyncRequestExecutorInterceptor.java +++ b/apm-sniffer/apm-sdk-plugin/httpasyncclient-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/httpasyncclient/v4/HttpAsyncRequestExecutorInterceptor.java @@ -32,8 +32,11 @@ import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedI import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor; import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult; import org.apache.skywalking.apm.network.trace.component.ComponentsDefine; +import org.apache.skywalking.apm.plugin.httpclient.HttpClientPluginConfig; +import org.apache.skywalking.apm.util.StringUtil; import java.lang.reflect.Method; +import java.net.URI; import java.net.URL; import static org.apache.skywalking.apm.plugin.httpasyncclient.v4.SessionRequestCompleteInterceptor.CONTEXT_LOCAL; @@ -69,6 +72,9 @@ public class HttpAsyncRequestExecutorInterceptor implements InstanceMethodsAroun next = next.next(); requestWrapper.setHeader(next.getHeadKey(), next.getHeadValue()); } + if (HttpClientPluginConfig.Plugin.HttpClient.COLLECT_HTTP_PARAMS) { + collectHttpParam(requestWrapper.getURI(), span); + } } @Override @@ -82,4 +88,17 @@ public class HttpAsyncRequestExecutorInterceptor implements InstanceMethodsAroun Class[] argumentsTypes, Throwable t) { } + + private void collectHttpParam(URI uri, AbstractSpan span) { + if (uri == null) { + return; + } + String tagValue = uri.getQuery(); + if (StringUtil.isNotEmpty(tagValue)) { + tagValue = HttpClientPluginConfig.Plugin.Http.HTTP_PARAMS_LENGTH_THRESHOLD > 0 ? + StringUtil.cut(tagValue, HttpClientPluginConfig.Plugin.Http.HTTP_PARAMS_LENGTH_THRESHOLD) : + tagValue; + Tags.HTTP.PARAMS.set(span, tagValue); + } + } } diff --git a/apm-sniffer/apm-sdk-plugin/httpasyncclient-4.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/httpasyncclient/v4/HttpAsyncClientInterceptorTest.java b/apm-sniffer/apm-sdk-plugin/httpasyncclient-4.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/httpasyncclient/v4/HttpAsyncClientInterceptorTest.java index d2efaa13a4..ed306300b2 100644 --- a/apm-sniffer/apm-sdk-plugin/httpasyncclient-4.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/httpasyncclient/v4/HttpAsyncClientInterceptorTest.java +++ b/apm-sniffer/apm-sdk-plugin/httpasyncclient-4.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/httpasyncclient/v4/HttpAsyncClientInterceptorTest.java @@ -17,6 +17,7 @@ package org.apache.skywalking.apm.plugin.httpasyncclient.v4; +import java.net.URI; import java.util.List; import org.apache.http.HttpHost; import org.apache.http.HttpResponse; @@ -47,6 +48,7 @@ import org.apache.skywalking.apm.agent.test.tools.SegmentStoragePoint; import org.apache.skywalking.apm.agent.test.tools.TracingSegmentRunner; import org.apache.skywalking.apm.plugin.httpasyncclient.v4.wrapper.FutureCallbackWrapper; import org.apache.skywalking.apm.plugin.httpasyncclient.v4.wrapper.HttpAsyncResponseConsumerWrapper; +import org.apache.skywalking.apm.plugin.httpclient.HttpClientPluginConfig; import org.junit.Assert; import org.junit.Before; import org.junit.Rule; @@ -119,6 +121,7 @@ public class HttpAsyncClientInterceptorTest { httpContext.setAttribute(HttpClientContext.HTTP_REQUEST, requestWrapper); httpContext.setAttribute(HttpClientContext.HTTP_TARGET_HOST, httpHost); CONTEXT_LOCAL.set(httpContext); + HttpClientPluginConfig.Plugin.HttpClient.COLLECT_HTTP_PARAMS = true; when(httpHost.getHostName()).thenReturn("127.0.0.1"); when(httpHost.getSchemeName()).thenReturn("http"); @@ -158,6 +161,7 @@ public class HttpAsyncClientInterceptorTest { when(requestWrapper.getRequestLine()).thenReturn(requestLine); when(requestWrapper.getOriginal()).thenReturn(new HttpGet("http://localhost:8081/original/test")); + when(requestWrapper.getURI()).thenReturn(new URI("http://localhost:8081/original/test?a=1&b=test")); when(httpHost.getPort()).thenReturn(8080); enhancedInstance = new EnhancedInstance() { @@ -266,6 +270,7 @@ public class HttpAsyncClientInterceptorTest { List tags = SpanHelper.getTags(span); assertThat(tags.get(0).getValue(), is("http://localhost:8081/original/test")); assertThat(tags.get(1).getValue(), is("GET")); + assertThat(tags.get(2).getValue(), is("a=1&b=test")); assertThat(span.isExit(), is(true)); } diff --git a/apm-sniffer/apm-sdk-plugin/httpclient-3.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/httpclient-3.x-plugin/pom.xml index 322f71faa3..65895f1e86 100644 --- a/apm-sniffer/apm-sdk-plugin/httpclient-3.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/httpclient-3.x-plugin/pom.xml @@ -44,5 +44,11 @@ ${commons-httpclient.version} provided + + org.apache.skywalking + apm-httpclient-commons + ${project.version} + provided + diff --git a/apm-sniffer/apm-sdk-plugin/httpclient-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/httpclient/v3/HttpClientExecuteInterceptor.java b/apm-sniffer/apm-sdk-plugin/httpclient-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/httpclient/v3/HttpClientExecuteInterceptor.java index a2a4312ef7..b23990cbaf 100644 --- a/apm-sniffer/apm-sdk-plugin/httpclient-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/httpclient/v3/HttpClientExecuteInterceptor.java +++ b/apm-sniffer/apm-sdk-plugin/httpclient-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/httpclient/v3/HttpClientExecuteInterceptor.java @@ -20,8 +20,6 @@ package org.apache.skywalking.apm.plugin.httpclient.v3; import java.lang.reflect.Method; -import org.apache.commons.httpclient.HostConfiguration; -import org.apache.commons.httpclient.HttpClient; import org.apache.commons.httpclient.HttpMethod; import org.apache.commons.httpclient.URI; import org.apache.commons.httpclient.URIException; @@ -35,21 +33,19 @@ import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedI import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor; import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult; import org.apache.skywalking.apm.network.trace.component.ComponentsDefine; +import org.apache.skywalking.apm.plugin.httpclient.HttpClientPluginConfig; +import org.apache.skywalking.apm.util.StringUtil; public class HttpClientExecuteInterceptor implements InstanceMethodsAroundInterceptor { @Override public void beforeMethod(final EnhancedInstance objInst, final Method method, final Object[] allArguments, - final Class[] argumentsTypes, final MethodInterceptResult result) throws Throwable { - - final HttpClient client = (HttpClient) objInst; - - HostConfiguration hostConfiguration = (HostConfiguration) allArguments[0]; - if (hostConfiguration == null) { - hostConfiguration = client.getHostConfiguration(); - } + final Class[] argumentsTypes, final MethodInterceptResult result) throws Throwable { final HttpMethod httpMethod = (HttpMethod) allArguments[1]; + if (httpMethod == null) { + return; + } final String remotePeer = httpMethod.getURI().getHost() + ":" + httpMethod.getURI().getPort(); final URI uri = httpMethod.getURI(); @@ -67,12 +63,15 @@ public class HttpClientExecuteInterceptor implements InstanceMethodsAroundInterc next = next.next(); httpMethod.setRequestHeader(next.getHeadKey(), next.getHeadValue()); } + + if (HttpClientPluginConfig.Plugin.HttpClient.COLLECT_HTTP_PARAMS) { + collectHttpParam(httpMethod, span); + } } @Override public Object afterMethod(final EnhancedInstance objInst, final Method method, final Object[] allArguments, - final Class[] argumentsTypes, final Object ret) { - + final Class[] argumentsTypes, final Object ret) { if (ret != null) { final int statusCode = (Integer) ret; final AbstractSpan span = ContextManager.activeSpan(); @@ -80,15 +79,22 @@ public class HttpClientExecuteInterceptor implements InstanceMethodsAroundInterc span.errorOccurred(); Tags.STATUS_CODE.set(span, Integer.toString(statusCode)); } + final HttpMethod httpMethod = (HttpMethod) allArguments[1]; + if (httpMethod == null) { + return ret; + } + // Active HTTP parameter collection automatically in the profiling context. + if (!HttpClientPluginConfig.Plugin.HttpClient.COLLECT_HTTP_PARAMS && span.isProfiling()) { + collectHttpParam(httpMethod, span); + } } - ContextManager.stopSpan(); return ret; } @Override public void handleMethodException(final EnhancedInstance objInst, final Method method, final Object[] allArguments, - final Class[] argumentsTypes, final Throwable t) { + final Class[] argumentsTypes, final Throwable t) { ContextManager.activeSpan().log(t); } @@ -97,4 +103,13 @@ public class HttpClientExecuteInterceptor implements InstanceMethodsAroundInterc return requestPath != null && requestPath.length() > 0 ? requestPath : "/"; } + private void collectHttpParam(HttpMethod httpMethod, AbstractSpan span) { + String tagValue = httpMethod.getQueryString(); + if (StringUtil.isNotEmpty(tagValue)) { + tagValue = HttpClientPluginConfig.Plugin.Http.HTTP_PARAMS_LENGTH_THRESHOLD > 0 ? + StringUtil.cut(tagValue, HttpClientPluginConfig.Plugin.Http.HTTP_PARAMS_LENGTH_THRESHOLD) : + tagValue; + Tags.HTTP.PARAMS.set(span, tagValue); + } + } } diff --git a/apm-sniffer/apm-sdk-plugin/httpclient-commons/pom.xml b/apm-sniffer/apm-sdk-plugin/httpclient-commons/pom.xml new file mode 100644 index 0000000000..28daa0c383 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/httpclient-commons/pom.xml @@ -0,0 +1,40 @@ + + + + + 4.0.0 + + apm-sdk-plugin + org.apache.skywalking + 8.3.0-SNAPSHOT + + + apm-httpclient-commons + + UTF-8 + + + + + + maven-deploy-plugin + + + + diff --git a/apm-sniffer/apm-sdk-plugin/httpclient-commons/src/main/java/org/apache/skywalking/apm/plugin/httpclient/HttpClientPluginConfig.java b/apm-sniffer/apm-sdk-plugin/httpclient-commons/src/main/java/org/apache/skywalking/apm/plugin/httpclient/HttpClientPluginConfig.java new file mode 100644 index 0000000000..9a4a94cdb1 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/httpclient-commons/src/main/java/org/apache/skywalking/apm/plugin/httpclient/HttpClientPluginConfig.java @@ -0,0 +1,43 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.skywalking.apm.plugin.httpclient; + +import org.apache.skywalking.apm.agent.core.boot.PluginConfig; + +public class HttpClientPluginConfig { + public static class Plugin { + @PluginConfig(root = HttpClientPluginConfig.class) + public static class HttpClient { + /** + * This config item controls that whether the HttpClient plugin should collect the parameters of the request. + */ + public static boolean COLLECT_HTTP_PARAMS = false; + } + + @PluginConfig(root = HttpClientPluginConfig.class) + public static class Http { + /** + * When either {@link HttpClient#COLLECT_HTTP_PARAMS} is enabled, how many characters to keep and send to the + * OAP backend, use negative values to keep and send the complete parameters, NB. this config item is added + * for the sake of performance + */ + public static int HTTP_PARAMS_LENGTH_THRESHOLD = 1024; + } + } +} diff --git a/apm-sniffer/apm-sdk-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/pom.xml index 907123207f..679672300b 100644 --- a/apm-sniffer/apm-sdk-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/pom.xml @@ -101,6 +101,7 @@ graphql-plugin xxl-job-2.x-plugin thrift-plugin + httpclient-commons pom diff --git a/docs/en/setup/service-agent/java-agent/README.md b/docs/en/setup/service-agent/java-agent/README.md index 44750dbdc8..a752a2b9d0 100755 --- a/docs/en/setup/service-agent/java-agent/README.md +++ b/docs/en/setup/service-agent/java-agent/README.md @@ -133,6 +133,7 @@ property key | Description | Default | `plugin.jdkthreading.threading_class_prefixes` | Threading classes (`java.lang.Runnable` and `java.util.concurrent.Callable`) and their subclasses, including anonymous inner classes whose name match any one of the `THREADING_CLASS_PREFIXES` (splitted by `,`) will be instrumented, make sure to only specify as narrow prefixes as what you're expecting to instrument, (`java.` and `javax.` will be ignored due to safety issues) | Not set | `plugin.tomcat.collect_http_params`| This config item controls that whether the Tomcat plugin should collect the parameters of the request. Also, activate implicitly in the profiled trace. | `false` | `plugin.springmvc.collect_http_params`| This config item controls that whether the SpringMVC plugin should collect the parameters of the request, when your Spring application is based on Tomcat, consider only setting either `plugin.tomcat.collect_http_params` or `plugin.springmvc.collect_http_params`. Also, activate implicitly in the profiled trace. | `false` | +`plugin.httpclient.collect_http_params`| This config item controls that whether the HttpClient plugin should collect the parameters of the request | `false` | `plugin.http.http_params_length_threshold`| When `COLLECT_HTTP_PARAMS` is enabled, how many characters to keep and send to the OAP backend, use negative values to keep and send the complete parameters, NB. this config item is added for the sake of performance. | `1024` | `plugin.http.http_headers_length_threshold`| When `include_http_headers` declares header names, this threshold controls the length limitation of all header values. use negative values to keep and send the complete headers. Note. this config item is added for the sake of performance. | `2048` | `plugin.http.include_http_headers`| Set the header names, which should be collected by the plugin. Header name must follow `javax.servlet.http` definition. Multiple names should be split by comma. | ``(No header would be collected) | diff --git a/test/plugin/scenarios/httpclient-3.x-scenario/config/expectedData.yaml b/test/plugin/scenarios/httpclient-3.x-scenario/config/expectedData.yaml index 890791b19b..bef00d4f50 100644 --- a/test/plugin/scenarios/httpclient-3.x-scenario/config/expectedData.yaml +++ b/test/plugin/scenarios/httpclient-3.x-scenario/config/expectedData.yaml @@ -33,6 +33,10 @@ segmentItems: tags: - {key: url, value: 'http://localhost:8080/httpclient-3.x-scenario/case/context-propagate'} - {key: http.method, value: GET} + - key: http.params + value: |- + q1=[v1] + chinese=[中文] refs: - {parentEndpoint: /httpclient-3.x-scenario/case/httpclient, networkAddress: 'localhost:8080', refType: CrossProcess, parentSpanId: 1, parentTraceSegmentId: not null, parentServiceInstance: not @@ -52,8 +56,9 @@ segmentItems: spanType: Exit peer: localhost:8080 tags: - - {key: url, value: 'http://localhost:8080/httpclient-3.x-scenario/case/context-propagate'} + - {key: url, value: 'http://localhost:8080/httpclient-3.x-scenario/case/context-propagate?q1=v1&chinese=%e4%b8%ad%e6%96%87'} - {key: http.method, value: GET} + - {key: http.params, value: q1=v1&chinese=%e4%b8%ad%e6%96%87} skipAnalysis: 'false' - operationName: /httpclient-3.x-scenario/case/httpclient operationId: 0 diff --git a/test/plugin/scenarios/httpclient-3.x-scenario/configuration.yml b/test/plugin/scenarios/httpclient-3.x-scenario/configuration.yml index 278d9ca090..1008dfe8df 100644 --- a/test/plugin/scenarios/httpclient-3.x-scenario/configuration.yml +++ b/test/plugin/scenarios/httpclient-3.x-scenario/configuration.yml @@ -18,4 +18,4 @@ type: tomcat entryService: '"http://localhost:8080/httpclient-3.x-scenario/case/httpclient?q1=v1&chinese=%e4%b8%ad%e6%96%87"' healthCheck: http://localhost:8080/httpclient-3.x-scenario/healthCheck environment: - - CATALINA_OPTS="-Dskywalking.plugin.tomcat.collect_http_params=true" + - CATALINA_OPTS="-Dskywalking.plugin.tomcat.collect_http_params=true -Dskywalking.plugin.httpclient.collect_http_params=true" diff --git a/test/plugin/scenarios/httpclient-3.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/httpclient/CaseServlet.java b/test/plugin/scenarios/httpclient-3.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/httpclient/CaseServlet.java index c903c7a938..1f11dddec2 100644 --- a/test/plugin/scenarios/httpclient-3.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/httpclient/CaseServlet.java +++ b/test/plugin/scenarios/httpclient-3.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/httpclient/CaseServlet.java @@ -35,7 +35,7 @@ public class CaseServlet extends HttpServlet { MultiThreadedHttpConnectionManager httpConnectionManager = new MultiThreadedHttpConnectionManager(); HttpClient client = new HttpClient(httpConnectionManager); - HttpMethod httpGet = new GetMethod("http://localhost:8080" + req.getContextPath() + "/case/context-propagate"); + HttpMethod httpGet = new GetMethod("http://localhost:8080" + req.getContextPath() + "/case/context-propagate?q1=v1&chinese=%e4%b8%ad%e6%96%87"); int statusCode = client.executeMethod(httpGet); try (PrintWriter printWriter = resp.getWriter()) { -- GitLab