Skip to content

Commit

Permalink
[#10377] Backport: Add uri stat user input for tomcat plugin
Browse files Browse the repository at this point in the history
  • Loading branch information
ga-ram committed Oct 10, 2023
1 parent 091523d commit 1cd7497
Show file tree
Hide file tree
Showing 6 changed files with 104 additions and 0 deletions.
2 changes: 2 additions & 0 deletions agent/src/main/resources/profiles/local/pinpoint.config
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,8 @@ profiler.uri.stat.vertx.enable=true
profiler.uri.stat.vertx.useuserinput=false
profiler.uri.stat.spring.webflux.enable=true
profiler.uri.stat.spring.webflux.useuserinput=false
profiler.uri.stat.tomcat.useuserinput=false

###########################################################
# TOMCAT #
###########################################################
Expand Down
1 change: 1 addition & 0 deletions agent/src/main/resources/profiles/release/pinpoint.config
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,7 @@ profiler.uri.stat.vertx.enable=true
profiler.uri.stat.vertx.useuserinput=false
profiler.uri.stat.spring.webflux.enable=true
profiler.uri.stat.spring.webflux.useuserinput=false
profiler.uri.stat.tomcat.useuserinput=false

###########################################################
# TOMCAT #
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ public class TomcatConfig {
private final String realIpEmptyValue;
private final Filter<String> excludeProfileMethodFilter;

private final boolean uriStatEnable;
private final boolean uriStatUseUserInput;
private final boolean uriStatCollectMethod;

public TomcatConfig(ProfilerConfig config) {
Objects.requireNonNull(config, "config");

Expand All @@ -53,6 +57,10 @@ public TomcatConfig(ProfilerConfig config) {
this.realIpHeader = serverConfig.getRealIpHeader("profiler.tomcat.realipheader");
this.realIpEmptyValue = serverConfig.getRealIpEmptyValue("profiler.tomcat.realipemptyvalue");
this.excludeProfileMethodFilter = serverConfig.getExcludeMethodFilter("profiler.tomcat.excludemethod");
// uri stat
this.uriStatEnable = config.readBoolean("profiler.uri.stat.enable", true);
this.uriStatUseUserInput = config.readBoolean("profiler.uri.stat.tomcat.useuserinput", false);
this.uriStatCollectMethod = config.readBoolean("profiler.uri.stat.collect.http.method", false);
}

public boolean isEnable() {
Expand Down Expand Up @@ -87,6 +95,18 @@ public Filter<String> getExcludeProfileMethodFilter() {
return excludeProfileMethodFilter;
}

public boolean isUriStatEnable() {
return uriStatEnable;
}

public boolean isUriStatUseUserInput() {
return uriStatUseUserInput;
}

public boolean isUriStatCollectMethod() {
return uriStatCollectMethod;
}

@Override
public String toString() {
final StringBuilder sb = new StringBuilder("TomcatConfig{");
Expand All @@ -101,4 +121,5 @@ public String toString() {
sb.append('}');
return sb.toString();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,5 @@ private TomcatConstants() {
*/
public static final String JAVAX_ERROR_EXCEPTION = "javax.servlet.error.exception";
public static final String JAKARTA_ERROR_EXCEPTION = "jakarta.servlet.error.exception";
public static final String[] TOMCAT_URI_USER_INPUT_ATTRIBUTE_KEYS = {"pinpoint.metric.uri-template"};
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@

import com.navercorp.pinpoint.bootstrap.config.ProfilerConfig;
import com.navercorp.pinpoint.bootstrap.context.MethodDescriptor;
import com.navercorp.pinpoint.bootstrap.context.SpanRecorder;
import com.navercorp.pinpoint.bootstrap.context.Trace;
import com.navercorp.pinpoint.bootstrap.context.TraceContext;
import com.navercorp.pinpoint.bootstrap.interceptor.AroundInterceptor;
import com.navercorp.pinpoint.bootstrap.logging.PLogger;
Expand All @@ -34,6 +36,7 @@
import com.navercorp.pinpoint.bootstrap.plugin.response.ServletResponseListenerBuilder;
import com.navercorp.pinpoint.bootstrap.util.argument.Validation;
import com.navercorp.pinpoint.bootstrap.util.argument.Validator;
import com.navercorp.pinpoint.common.util.StringUtils;
import com.navercorp.pinpoint.plugin.common.servlet.jakarta.util.HttpServletRequestAdaptor;
import com.navercorp.pinpoint.plugin.common.servlet.jakarta.util.HttpServletResponseAdaptor;
import com.navercorp.pinpoint.plugin.common.servlet.jakarta.util.ParameterRecorderFactory;
Expand All @@ -57,14 +60,22 @@ public class StandardHostValveInvokeInterceptor implements AroundInterceptor {
private final ServletRequestListener<HttpServletRequest> servletRequestListener;
private final ServletResponseListener<HttpServletResponse> servletResponseListener;

private final TraceContext traceContext;
private final boolean uriStatEnable;
private final boolean uriStatUseUserInput;
private final boolean uriStatCollectMethod;

public StandardHostValveInvokeInterceptor(TraceContext traceContext, MethodDescriptor descriptor,
RequestRecorderFactory<HttpServletRequest> requestRecorderFactory) {
this.traceContext = traceContext;
this.methodDescriptor = descriptor;

this.validator = buildValidator();
final TomcatConfig config = new TomcatConfig(traceContext.getProfilerConfig());

this.uriStatEnable = config.isUriStatEnable();
this.uriStatUseUserInput = config.isUriStatUseUserInput();
this.uriStatCollectMethod = config.isUriStatCollectMethod();

RequestAdaptor<HttpServletRequest> requestAdaptor = new HttpServletRequestAdaptor();
ParameterRecorder<HttpServletRequest> parameterRecorder = ParameterRecorderFactory.newParameterRecorderFactory(config.getExcludeProfileMethodFilter(), config.isTraceRequestParam());
Expand Down Expand Up @@ -147,13 +158,41 @@ public void after(Object target, Object[] args, Object result, Throwable throwab
}
}
}
if (uriStatEnable && uriStatUseUserInput) {
recordUserUriTemplate(request);
}
this.servletResponseListener.destroyed(response, throwable, statusCode); //must before request listener due to trace block ending
this.servletRequestListener.destroyed(request, throwable, statusCode);
} catch (Throwable t) {
logger.info("Failed to servlet request event handle.", t);
}
}

private void recordUserUriTemplate(HttpServletRequest request) {
final Trace trace = traceContext.currentRawTraceObject();
if (trace == null) {
return;
}
for (String attributeName : TomcatConstants.TOMCAT_URI_USER_INPUT_ATTRIBUTE_KEYS) {
final Object uriMapping = request.getAttribute(attributeName);
if (!(uriMapping instanceof String)) {
continue;
}

String uriTemplate = (String) uriMapping;
if (!StringUtils.hasLength(uriTemplate)) {
continue;
}

if (uriStatCollectMethod) {
uriTemplate = request.getMethod() + " " + uriTemplate;
}

final SpanRecorder spanRecorder = trace.getSpanRecorder();
spanRecorder.recordUriTemplate(uriTemplate, true);
}
}

private int getStatusCode(final HttpServletResponse response) {
try {
// Tomcat 6
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@

import com.navercorp.pinpoint.bootstrap.config.ProfilerConfig;
import com.navercorp.pinpoint.bootstrap.context.MethodDescriptor;
import com.navercorp.pinpoint.bootstrap.context.SpanRecorder;
import com.navercorp.pinpoint.bootstrap.context.Trace;
import com.navercorp.pinpoint.bootstrap.context.TraceContext;
import com.navercorp.pinpoint.bootstrap.interceptor.AroundInterceptor;
import com.navercorp.pinpoint.bootstrap.logging.PLogger;
Expand All @@ -34,6 +36,7 @@
import com.navercorp.pinpoint.bootstrap.plugin.response.ServletResponseListenerBuilder;
import com.navercorp.pinpoint.bootstrap.util.argument.Validation;
import com.navercorp.pinpoint.bootstrap.util.argument.Validator;
import com.navercorp.pinpoint.common.util.StringUtils;
import com.navercorp.pinpoint.plugin.common.servlet.util.HttpServletRequestAdaptor;
import com.navercorp.pinpoint.plugin.common.servlet.util.HttpServletResponseAdaptor;
import com.navercorp.pinpoint.plugin.common.servlet.util.ParameterRecorderFactory;
Expand All @@ -58,14 +61,23 @@ public class StandardHostValveInvokeInterceptor implements AroundInterceptor {
private final ServletRequestListener<HttpServletRequest> servletRequestListener;
private final ServletResponseListener<HttpServletResponse> servletResponseListener;

private final TraceContext traceContext;
private final boolean uriStatEnable;
private final boolean uriStatUseUserInput;
private final boolean uriStatCollectMethod;


public StandardHostValveInvokeInterceptor(TraceContext traceContext, MethodDescriptor descriptor,
RequestRecorderFactory<HttpServletRequest> requestRecorderFactory) {
this.traceContext = traceContext;
this.methodDescriptor = descriptor;

this.validator = buildValidator();
final TomcatConfig config = new TomcatConfig(traceContext.getProfilerConfig());

this.uriStatEnable = config.isUriStatEnable();
this.uriStatUseUserInput = config.isUriStatUseUserInput();
this.uriStatCollectMethod = config.isUriStatCollectMethod();

RequestAdaptor<HttpServletRequest> requestAdaptor = new HttpServletRequestAdaptor();
ParameterRecorder<HttpServletRequest> parameterRecorder = ParameterRecorderFactory.newParameterRecorderFactory(config.getExcludeProfileMethodFilter(), config.isTraceRequestParam());
Expand Down Expand Up @@ -148,13 +160,41 @@ public void after(Object target, Object[] args, Object result, Throwable throwab
}
}
}
if (uriStatEnable && uriStatUseUserInput) {
recordUserUriTemplate(request);
}
this.servletResponseListener.destroyed(response, throwable, statusCode); //must before request listener due to trace block ending
this.servletRequestListener.destroyed(request, throwable, statusCode);
} catch (Throwable t) {
logger.info("Failed to servlet request event handle.", t);
}
}

private void recordUserUriTemplate(HttpServletRequest request) {
final Trace trace = traceContext.currentRawTraceObject();
if (trace == null) {
return;
}
for (String attributeName : TomcatConstants.TOMCAT_URI_USER_INPUT_ATTRIBUTE_KEYS) {
final Object uriMapping = request.getAttribute(attributeName);
if (!(uriMapping instanceof String)) {
continue;
}

String uriTemplate = (String) uriMapping;
if (!StringUtils.hasLength(uriTemplate)) {
continue;
}

if (uriStatCollectMethod) {
uriTemplate = request.getMethod() + " " + uriTemplate;
}

final SpanRecorder spanRecorder = trace.getSpanRecorder();
spanRecorder.recordUriTemplate(uriTemplate, true);
}
}

private int getStatusCode(final HttpServletResponse response) {
try {
// Tomcat 6
Expand Down

0 comments on commit 1cd7497

Please sign in to comment.