diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/conf/Config.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/conf/Config.java index 0b0842cf93..0327b3613f 100755 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/conf/Config.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/conf/Config.java @@ -353,5 +353,19 @@ public class Config { */ public static String THREADING_CLASS_PREFIXES = ""; } + + public static class Http { + /** + * This config item controls that whether the plugins related to HTTP should + * collect the parameters of the request. + */ + public static boolean COLLECT_HTTP_PARAMS = false; + /** + * When {@link #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-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/tag/Tags.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/tag/Tags.java index 80d52e46be..310025af23 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/tag/Tags.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/tag/Tags.java @@ -76,5 +76,7 @@ public final class Tags { public static final class HTTP { public static final StringTag METHOD = new StringTag(10, "http.method"); + + public static final StringTag PARAMS = new StringTag(11, "http.params"); } } diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/util/CollectionUtil.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/util/CollectionUtil.java new file mode 100644 index 0000000000..a46cae8f18 --- /dev/null +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/util/CollectionUtil.java @@ -0,0 +1,40 @@ +/* + * 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.agent.core.util; + +import java.util.Arrays; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * Some utility methods for collections. + * Reinvent the wheels because importing third-party libs just for some methods is not worthwhile in agent side + * + * @author kezhenxu94 + * @since 7.0.0 + */ +public final class CollectionUtil { + public static String toString(final Map map) { + return map + .entrySet() + .stream() + .map(entry -> entry.getKey() + "=" + Arrays.toString(entry.getValue())) + .collect(Collectors.joining("\n")); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/commons/interceptor/AbstractMethodInterceptor.java b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/commons/interceptor/AbstractMethodInterceptor.java index 85734df5bd..b046eb4594 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/commons/interceptor/AbstractMethodInterceptor.java +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/commons/interceptor/AbstractMethodInterceptor.java @@ -19,6 +19,7 @@ package org.apache.skywalking.apm.plugin.spring.mvc.commons.interceptor; import java.lang.reflect.Method; +import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.skywalking.apm.agent.core.conf.Config; @@ -31,11 +32,13 @@ import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer; import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; 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.agent.core.util.CollectionUtil; import org.apache.skywalking.apm.agent.core.util.MethodUtil; import org.apache.skywalking.apm.network.trace.component.ComponentsDefine; import org.apache.skywalking.apm.plugin.spring.mvc.commons.EnhanceRequireObjectCache; import org.apache.skywalking.apm.plugin.spring.mvc.commons.exception.IllegalMethodStackDepthException; import org.apache.skywalking.apm.plugin.spring.mvc.commons.exception.ServletResponseNotFoundException; +import org.apache.skywalking.apm.util.StringUtil; import static org.apache.skywalking.apm.plugin.spring.mvc.commons.Constants.CONTROLLER_METHOD_STACK_DEPTH; import static org.apache.skywalking.apm.plugin.spring.mvc.commons.Constants.FORWARD_REQUEST_FLAG; @@ -104,6 +107,17 @@ public abstract class AbstractMethodInterceptor implements InstanceMethodsAround span.setComponent(ComponentsDefine.SPRING_MVC_ANNOTATION); SpanLayer.asHttp(span); + if (Config.Plugin.Http.COLLECT_HTTP_PARAMS) { + final Map parameterMap = request.getParameterMap(); + if (parameterMap != null && !parameterMap.isEmpty()) { + String tagValue = CollectionUtil.toString(parameterMap); + tagValue = Config.Plugin.Http.HTTP_PARAMS_LENGTH_THRESHOLD > 0 + ? StringUtil.cut(tagValue, Config.Plugin.Http.HTTP_PARAMS_LENGTH_THRESHOLD) + : tagValue; + Tags.HTTP.PARAMS.set(span, tagValue); + } + } + stackDepth = new StackDepth(); ContextManager.getRuntimeContext().put(CONTROLLER_METHOD_STACK_DEPTH, stackDepth); } else { diff --git a/apm-sniffer/apm-sdk-plugin/tomcat-7.x-8.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat78x/TomcatInvokeInterceptor.java b/apm-sniffer/apm-sdk-plugin/tomcat-7.x-8.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat78x/TomcatInvokeInterceptor.java index bb609a92e0..112d1c1c58 100644 --- a/apm-sniffer/apm-sdk-plugin/tomcat-7.x-8.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat78x/TomcatInvokeInterceptor.java +++ b/apm-sniffer/apm-sdk-plugin/tomcat-7.x-8.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat78x/TomcatInvokeInterceptor.java @@ -19,9 +19,15 @@ package org.apache.skywalking.apm.plugin.tomcat78x; -import java.lang.reflect.Method; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import java.lang.reflect.Method; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Map; + +import org.apache.catalina.connector.Request; +import org.apache.skywalking.apm.agent.core.conf.Config; 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; @@ -32,8 +38,11 @@ import org.apache.skywalking.apm.agent.core.context.trace.TraceSegment; import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; 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.agent.core.util.CollectionUtil; import org.apache.skywalking.apm.agent.core.util.MethodUtil; import org.apache.skywalking.apm.network.trace.component.ComponentsDefine; +import org.apache.skywalking.apm.util.StringUtil; +import org.apache.tomcat.util.http.Parameters; /** * {@link TomcatInvokeInterceptor} fetch the serialized context data by using {@link @@ -63,7 +72,7 @@ public class TomcatInvokeInterceptor implements InstanceMethodsAroundInterceptor */ @Override public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, MethodInterceptResult result) throws Throwable { - HttpServletRequest request = (HttpServletRequest)allArguments[0]; + Request request = (Request) allArguments[0]; ContextCarrier contextCarrier = new ContextCarrier(); CarrierItem next = contextCarrier.items(); @@ -78,6 +87,23 @@ public class TomcatInvokeInterceptor implements InstanceMethodsAroundInterceptor span.setComponent(ComponentsDefine.TOMCAT); SpanLayer.asHttp(span); + if (Config.Plugin.Http.COLLECT_HTTP_PARAMS) { + final Map parameterMap = new HashMap<>(); + final org.apache.coyote.Request coyoteRequest = request.getCoyoteRequest(); + final Parameters parameters = coyoteRequest.getParameters(); + for (final Enumeration names = parameters.getParameterNames(); names.hasMoreElements(); ) { + final String name = names.nextElement(); + parameterMap.put(name, parameters.getParameterValues(name)); + } + + if (!parameterMap.isEmpty()) { + String tagValue = CollectionUtil.toString(parameterMap); + tagValue = Config.Plugin.Http.HTTP_PARAMS_LENGTH_THRESHOLD > 0 + ? StringUtil.cut(tagValue, Config.Plugin.Http.HTTP_PARAMS_LENGTH_THRESHOLD) + : tagValue; + Tags.HTTP.PARAMS.set(span, tagValue); + } + } } @Override public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, diff --git a/apm-sniffer/apm-sdk-plugin/tomcat-7.x-8.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/tomcat78x/TomcatInvokeInterceptorTest.java b/apm-sniffer/apm-sdk-plugin/tomcat-7.x-8.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/tomcat78x/TomcatInvokeInterceptorTest.java index a649327a93..3ca932199e 100644 --- a/apm-sniffer/apm-sdk-plugin/tomcat-7.x-8.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/tomcat78x/TomcatInvokeInterceptorTest.java +++ b/apm-sniffer/apm-sdk-plugin/tomcat-7.x-8.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/tomcat78x/TomcatInvokeInterceptorTest.java @@ -19,8 +19,9 @@ package org.apache.skywalking.apm.plugin.tomcat78x; import java.util.List; -import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; + +import org.apache.catalina.connector.Request; import org.apache.skywalking.apm.agent.core.conf.Config; import org.apache.skywalking.apm.agent.core.context.SW3CarrierItem; import org.apache.skywalking.apm.agent.core.context.trace.AbstractTracingSpan; @@ -66,7 +67,7 @@ public class TomcatInvokeInterceptorTest { public AgentServiceRule serviceRule = new AgentServiceRule(); @Mock - private HttpServletRequest request; + private Request request; @Mock private HttpServletResponse response; @Mock diff --git a/docs/en/setup/service-agent/java-agent/README.md b/docs/en/setup/service-agent/java-agent/README.md index 56a9a860d9..fbea288976 100755 --- a/docs/en/setup/service-agent/java-agent/README.md +++ b/docs/en/setup/service-agent/java-agent/README.md @@ -118,6 +118,8 @@ property key | Description | Default | `plugin.opgroup.*`|Support operation name customize group rules in different plugins. Read [Group rule supported plugins](op_name_group_rule.md)|Not set| `plugin.springtransaction.simplify_transaction_definition_name`|If true, the transaction definition name will be simplified.|false| `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.http.collect_http_params`| This config item controls that whether the plugins related to HTTP should collect the parameters of the request. The name `plugin.http.collect_http_params` is rather general, but it doesn't guarantee that all http plugins should be under its control, unless the plugin itself takes this config item into consideration, such as Tomcat, Spring MVC, and Armeria plugin. | `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` | ## Optional Plugins Java agent plugins are all pluggable. Optional plugins could be provided in `optional-plugins` folder under agent or 3rd party repositories. diff --git a/test/plugin/containers/tomcat-container/docker/Dockerfile b/test/plugin/containers/tomcat-container/docker/Dockerfile index 3c70887079..ee2ed2de90 100644 --- a/test/plugin/containers/tomcat-container/docker/Dockerfile +++ b/test/plugin/containers/tomcat-container/docker/Dockerfile @@ -18,6 +18,8 @@ FROM tomcat:8.5.42-jdk8-openjdk MAINTAINER zhangxin@apache.org WORKDIR /usr/local/skywalking/tools +ENV CATALINA_OPTS "" + COPY run.sh / COPY catalina.sh /usr/local/tomcat/bin/ diff --git a/test/plugin/runner-helper/src/main/java/org/apache/skywalking/plugin/test/helper/ConfigurationImpl.java b/test/plugin/runner-helper/src/main/java/org/apache/skywalking/plugin/test/helper/ConfigurationImpl.java index 8271aa40c5..ce9cfae851 100644 --- a/test/plugin/runner-helper/src/main/java/org/apache/skywalking/plugin/test/helper/ConfigurationImpl.java +++ b/test/plugin/runner-helper/src/main/java/org/apache/skywalking/plugin/test/helper/ConfigurationImpl.java @@ -25,6 +25,8 @@ import org.yaml.snakeyaml.Yaml; import java.io.File; import java.io.FileNotFoundException; import java.io.FileReader; +import java.util.Collections; +import java.util.List; public class ConfigurationImpl implements IConfiguration { private CaseConfiguration configuration; @@ -97,6 +99,12 @@ public class ConfigurationImpl implements IConfiguration { return this.configuration.getStartScript(); } + @Override + public String catalinaOpts() { + List environment = this.configuration.getEnvironment() != null ? this.configuration.getEnvironment() : Collections.emptyList(); + return environment.stream().filter(it -> it.startsWith("CATALINA_OPTS=")).findFirst().orElse("").replaceAll("^CATALINA_OPTS=", ""); + } + @Override public String dockerImageName() { switch (this.configuration.getType().toLowerCase()) { case "tomcat" : diff --git a/test/plugin/runner-helper/src/main/java/org/apache/skywalking/plugin/test/helper/DockerContainerRunningGenerator.java b/test/plugin/runner-helper/src/main/java/org/apache/skywalking/plugin/test/helper/DockerContainerRunningGenerator.java index b9d4355622..4e1a1bfefe 100644 --- a/test/plugin/runner-helper/src/main/java/org/apache/skywalking/plugin/test/helper/DockerContainerRunningGenerator.java +++ b/test/plugin/runner-helper/src/main/java/org/apache/skywalking/plugin/test/helper/DockerContainerRunningGenerator.java @@ -45,6 +45,7 @@ public class DockerContainerRunningGenerator extends AbstractRunningGenerator { root.put("scenario_version", configuration.scenarioVersion()); root.put("health_check", configuration.healthCheck()); root.put("start_script", configuration.startScript()); + root.put("catalina_opts", configuration.catalinaOpts()); root.put("entry_service", configuration.entryService()); root.put("test_framework", configuration.testFramework()); root.put("docker_image_name", configuration.dockerImageName()); diff --git a/test/plugin/runner-helper/src/main/java/org/apache/skywalking/plugin/test/helper/IConfiguration.java b/test/plugin/runner-helper/src/main/java/org/apache/skywalking/plugin/test/helper/IConfiguration.java index 4068884213..e7332d9e4e 100644 --- a/test/plugin/runner-helper/src/main/java/org/apache/skywalking/plugin/test/helper/IConfiguration.java +++ b/test/plugin/runner-helper/src/main/java/org/apache/skywalking/plugin/test/helper/IConfiguration.java @@ -38,6 +38,8 @@ public interface IConfiguration { String startScript(); + String catalinaOpts(); + String entryService(); String dockerImageName(); diff --git a/test/plugin/runner-helper/src/main/resources/container-start-script.template b/test/plugin/runner-helper/src/main/resources/container-start-script.template index 7215c2d30e..8cacdd6bba 100644 --- a/test/plugin/runner-helper/src/main/resources/container-start-script.template +++ b/test/plugin/runner-helper/src/main/resources/container-start-script.template @@ -24,8 +24,11 @@ docker run \ <#if start_script??> --env SCENARIO_START_SCRIPT=${start_script} \ - --env SCENARIO_ENTRY_SERVICE=${entry_service} \ + --env SCENARIO_ENTRY_SERVICE=${entry_service} \ --env SCENARIO_HEALTH_CHECK_URL=${health_check} \ + <#if catalina_opts??> + --env CATALINA_OPTS=${catalina_opts} \ + -v ${agent_home}:/usr/local/skywalking/scenario/agent \ -v ${scenario_home}:/usr/local/skywalking/scenario \ ${docker_image_name}:${docker_image_version} 1>${scenario_home}/logs/container.log diff --git a/test/plugin/scenarios/armeria-0.96minus-scenario/bin/startup.sh b/test/plugin/scenarios/armeria-0.96minus-scenario/bin/startup.sh index 22aa8dc704..0735902561 100644 --- a/test/plugin/scenarios/armeria-0.96minus-scenario/bin/startup.sh +++ b/test/plugin/scenarios/armeria-0.96minus-scenario/bin/startup.sh @@ -18,4 +18,4 @@ home="$(cd "$(dirname $0)"; pwd)" -java -jar ${agent_opts} ${home}/../libs/armeria-0.96minus-scenario.jar & \ No newline at end of file +java -jar -Dskywalking.plugin.http.collect_http_params=true ${agent_opts} ${home}/../libs/armeria-0.96minus-scenario.jar & \ No newline at end of file diff --git a/test/plugin/scenarios/armeria-0.96minus-scenario/config/expectedData.yaml b/test/plugin/scenarios/armeria-0.96minus-scenario/config/expectedData.yaml index bb987fd556..7ad070c57d 100644 --- a/test/plugin/scenarios/armeria-0.96minus-scenario/config/expectedData.yaml +++ b/test/plugin/scenarios/armeria-0.96minus-scenario/config/expectedData.yaml @@ -82,4 +82,8 @@ segmentItems: peerId: 0 tags: - {key: url, value: 'http://localhost:8080/greet/skywalking'} - - {key: http.method, value: GET} \ No newline at end of file + - {key: http.method, value: GET} + - key: http.params + value: |- + q1=[v1] + chinese=[中文] diff --git a/test/plugin/scenarios/armeria-0.96minus-scenario/configuration.yml b/test/plugin/scenarios/armeria-0.96minus-scenario/configuration.yml index 75002bc76c..7ff2750a17 100644 --- a/test/plugin/scenarios/armeria-0.96minus-scenario/configuration.yml +++ b/test/plugin/scenarios/armeria-0.96minus-scenario/configuration.yml @@ -15,7 +15,7 @@ # limitations under the License. type: jvm -entryService: http://localhost:8080/greet/skywalking +entryService: '"http://localhost:8080/greet/skywalking?q1=v1&chinese=%e4%b8%ad%e6%96%87"' healthCheck: http://localhost:8080/healthCheck startScript: ./bin/startup.sh framework: Armeria 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 85ea877df4..42388b7af0 100644 --- a/test/plugin/scenarios/httpclient-3.x-scenario/config/expectedData.yaml +++ b/test/plugin/scenarios/httpclient-3.x-scenario/config/expectedData.yaml @@ -83,4 +83,8 @@ segmentItems: peerId: 0 tags: - {key: url, value: 'http://localhost:8080/httpclient-3.x-scenario/case/httpclient'} - - {key: http.method, value: GET} \ No newline at end of file + - {key: http.method, value: GET} + - key: http.params + value: |- + q1=[v1] + chinese=[中文] \ No newline at end of file diff --git a/test/plugin/scenarios/httpclient-3.x-scenario/configuration.yml b/test/plugin/scenarios/httpclient-3.x-scenario/configuration.yml index 053a7d81ff..e9e2644d7a 100644 --- a/test/plugin/scenarios/httpclient-3.x-scenario/configuration.yml +++ b/test/plugin/scenarios/httpclient-3.x-scenario/configuration.yml @@ -15,6 +15,8 @@ # limitations under the License. type: tomcat -entryService: http://localhost:8080/httpclient-3.x-scenario/case/httpclient +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 framework: httpclient +environment: + - CATALINA_OPTS="-Dskywalking.plugin.http.collect_http_params=true" \ No newline at end of file diff --git a/test/plugin/scenarios/spring-3.1.x-scenario/config/expectedData.yaml b/test/plugin/scenarios/spring-3.1.x-scenario/config/expectedData.yaml index 5f5acdfdc1..a6192ada23 100644 --- a/test/plugin/scenarios/spring-3.1.x-scenario/config/expectedData.yaml +++ b/test/plugin/scenarios/spring-3.1.x-scenario/config/expectedData.yaml @@ -274,6 +274,10 @@ segmentItems: tags: - {key: url, value: 'http://localhost:8080/spring-3.1.x-scenario/case/resttemplate'} - {key: http.method, value: GET} + - key: http.params + value: |- + q1=[v1] + chinese=[中文] - segmentId: not null spans: - operationName: '{PUT}/update/{id}' diff --git a/test/plugin/scenarios/spring-3.1.x-scenario/configuration.yml b/test/plugin/scenarios/spring-3.1.x-scenario/configuration.yml index 05a385f363..bb95c255d2 100644 --- a/test/plugin/scenarios/spring-3.1.x-scenario/configuration.yml +++ b/test/plugin/scenarios/spring-3.1.x-scenario/configuration.yml @@ -15,8 +15,10 @@ # limitations under the License. type: tomcat -entryService: http://localhost:8080/spring-3.1.x-scenario/case/resttemplate +entryService: '"http://localhost:8080/spring-3.1.x-scenario/case/resttemplate?q1=v1&chinese=%e4%b8%ad%e6%96%87"' healthCheck: http://localhost:8080/spring-3.1.x-scenario/healthCheck runningMode: with_optional withPlugins: apm-spring-annotation-plugin-*.jar -framework: spring \ No newline at end of file +framework: spring +environment: + - CATALINA_OPTS="-Dskywalking.plugin.http.collect_http_params=true" \ No newline at end of file