未验证 提交 f52f7f46 编写于 作者: K kezhenxu94 提交者: GitHub

Support collecting http parameters (#4162)

Plugins of Tomcat, Spring MVC, Armeria are supported for now
上级 4012545e
......@@ -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;
}
}
}
......@@ -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");
}
}
/*
* 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<String, String[]> map) {
return map
.entrySet()
.stream()
.map(entry -> entry.getKey() + "=" + Arrays.toString(entry.getValue()))
.collect(Collectors.joining("\n"));
}
}
......@@ -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<String, String[]> 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 {
......
......@@ -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<String, String[]> parameterMap = new HashMap<>();
final org.apache.coyote.Request coyoteRequest = request.getCoyoteRequest();
final Parameters parameters = coyoteRequest.getParameters();
for (final Enumeration<String> 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,
......
......@@ -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
......
......@@ -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.
......
......@@ -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/
......
......@@ -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<String> 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" :
......
......@@ -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());
......
......@@ -38,6 +38,8 @@ public interface IConfiguration {
String startScript();
String catalinaOpts();
String entryService();
String dockerImageName();
......
......@@ -24,8 +24,11 @@ docker run \
<#if start_script??>
--env SCENARIO_START_SCRIPT=${start_script} \
</#if>
--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} \
</#if>
-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
......
......@@ -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
......@@ -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=[中文]
......@@ -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
......@@ -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
......@@ -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
......@@ -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}'
......
......@@ -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
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册