diff --git a/dd-java-agent/instrumentation/spring/spring-webmvc/spring-webmvc-3.1/src/main/java/datadog/trace/instrumentation/springweb/SpringWebHttpServerDecorator.java b/dd-java-agent/instrumentation/spring/spring-webmvc/spring-webmvc-3.1/src/main/java/datadog/trace/instrumentation/springweb/SpringWebHttpServerDecorator.java index 52ce8855048..9a596ae90a1 100644 --- a/dd-java-agent/instrumentation/spring/spring-webmvc/spring-webmvc-3.1/src/main/java/datadog/trace/instrumentation/springweb/SpringWebHttpServerDecorator.java +++ b/dd-java-agent/instrumentation/spring/spring-webmvc/spring-webmvc-3.1/src/main/java/datadog/trace/instrumentation/springweb/SpringWebHttpServerDecorator.java @@ -8,6 +8,7 @@ import datadog.trace.bootstrap.instrumentation.api.URIDataAdapter; import datadog.trace.bootstrap.instrumentation.api.UTF8BytesString; import datadog.trace.bootstrap.instrumentation.decorator.HttpServerDecorator; +import datadog.trace.util.Strings; import java.lang.reflect.Method; import javax.servlet.Servlet; import javax.servlet.http.HttpServletRequest; @@ -20,6 +21,9 @@ public class SpringWebHttpServerDecorator extends HttpServerDecorator { + // source for limits: https://docs.datadoghq.com/tracing/troubleshooting + static final int VIEW_NAME_RESOURCE_LIMIT = 5_000; + static final int VIEW_NAME_TAG_LIMIT = 25_000; private static final CharSequence SPRING_HANDLER = UTF8BytesString.create("spring.handler"); public static final CharSequence RESPONSE_RENDER = UTF8BytesString.create("response.render"); @@ -142,8 +146,8 @@ private String getMethodName(final Object handler) { public AgentSpan onRender(final AgentSpan span, final ModelAndView mv) { final String viewName = mv.getViewName(); if (viewName != null) { - span.setTag("view.name", viewName); - span.setResourceName(viewName); + span.setTag("view.name", Strings.truncate(viewName, VIEW_NAME_TAG_LIMIT)); + span.setResourceName(Strings.truncate(viewName, VIEW_NAME_RESOURCE_LIMIT)); } if (mv.getView() != null) { span.setTag("view.type", className(mv.getView().getClass())); diff --git a/dd-java-agent/instrumentation/spring/spring-webmvc/spring-webmvc-3.1/src/test/groovy/datadog/trace/instrumentation/springweb/SpringWebHttpServerDecoratorTest.groovy b/dd-java-agent/instrumentation/spring/spring-webmvc/spring-webmvc-3.1/src/test/groovy/datadog/trace/instrumentation/springweb/SpringWebHttpServerDecoratorTest.groovy new file mode 100644 index 00000000000..28952694a40 --- /dev/null +++ b/dd-java-agent/instrumentation/spring/spring-webmvc/spring-webmvc-3.1/src/test/groovy/datadog/trace/instrumentation/springweb/SpringWebHttpServerDecoratorTest.groovy @@ -0,0 +1,25 @@ +package datadog.trace.instrumentation.springweb + +import datadog.trace.agent.test.InstrumentationSpecification +import org.springframework.web.servlet.ModelAndView + +class SpringWebHttpServerDecoratorTest extends InstrumentationSpecification { + + def "onRender truncates long view name for tag and resource"() { + given: + def viewName = "a" * (SpringWebHttpServerDecorator.VIEW_NAME_TAG_LIMIT + 12) + def modelAndView = Stub(ModelAndView) { + getViewName() >> viewName + getView() >> null + } + def span = TEST_TRACER.buildSpan("testInstrumentation", "my operation").start() + + when: + SpringWebHttpServerDecorator.DECORATE_RENDER.onRender(span, modelAndView) + span.finish() + + then: + span.getTag("view.name").toString().length() == SpringWebHttpServerDecorator.VIEW_NAME_TAG_LIMIT + span.getResourceName().length() == SpringWebHttpServerDecorator.VIEW_NAME_RESOURCE_LIMIT + } +} diff --git a/dd-java-agent/instrumentation/spring/spring-webmvc/spring-webmvc-6.0/src/main/java17/datadog/trace/instrumentation/springweb6/SpringWebHttpServerDecorator.java b/dd-java-agent/instrumentation/spring/spring-webmvc/spring-webmvc-6.0/src/main/java17/datadog/trace/instrumentation/springweb6/SpringWebHttpServerDecorator.java index 79b89c1aad5..162e750fbb4 100644 --- a/dd-java-agent/instrumentation/spring/spring-webmvc/spring-webmvc-6.0/src/main/java17/datadog/trace/instrumentation/springweb6/SpringWebHttpServerDecorator.java +++ b/dd-java-agent/instrumentation/spring/spring-webmvc/spring-webmvc-6.0/src/main/java17/datadog/trace/instrumentation/springweb6/SpringWebHttpServerDecorator.java @@ -3,11 +3,13 @@ import static datadog.trace.bootstrap.instrumentation.decorator.http.HttpResourceDecorator.HTTP_RESOURCE_DECORATOR; import datadog.context.Context; +import datadog.trace.bootstrap.config.provider.ConfigProvider; import datadog.trace.bootstrap.instrumentation.api.AgentPropagation; import datadog.trace.bootstrap.instrumentation.api.AgentSpan; import datadog.trace.bootstrap.instrumentation.api.URIDataAdapter; import datadog.trace.bootstrap.instrumentation.api.UTF8BytesString; import datadog.trace.bootstrap.instrumentation.decorator.HttpServerDecorator; +import datadog.trace.util.Strings; import jakarta.servlet.Servlet; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; @@ -23,6 +25,11 @@ public class SpringWebHttpServerDecorator private static final String DD_FILTERED_SPRING_ROUTE_ALREADY_APPLIED = "datadog.filter.spring.route.applied"; + // source for limits: https://docs.datadoghq.com/tracing/troubleshooting + static final int VIEW_NAME_RESOURCE_LIMIT = 5_000; + static final int VIEW_NAME_TAG_LIMIT = 25_000; + private static final boolean VIEW_NAME_ENABLED = + ConfigProvider.getInstance().getBoolean("trace.spring-web.view-name.enabled", true); private static final CharSequence SPRING_HANDLER = UTF8BytesString.create("spring.handler"); public static final CharSequence RESPONSE_RENDER = UTF8BytesString.create("response.render"); @@ -147,10 +154,12 @@ private String getMethodName(final Object handler) { } public AgentSpan onRender(final AgentSpan span, final ModelAndView mv) { - final String viewName = mv.getViewName(); - if (viewName != null) { - span.setTag("view.name", viewName); - span.setResourceName(viewName); + if (VIEW_NAME_ENABLED) { + final String viewName = mv.getViewName(); + if (viewName != null) { + span.setTag("view.name", Strings.truncate(viewName, VIEW_NAME_TAG_LIMIT)); + span.setResourceName(Strings.truncate(viewName, VIEW_NAME_RESOURCE_LIMIT)); + } } if (mv.getView() != null) { span.setTag("view.type", className(mv.getView().getClass())); diff --git a/dd-java-agent/instrumentation/spring/spring-webmvc/spring-webmvc-6.0/src/test/groovy/datadog/trace/instrumentation/springweb6/SpringWebHttpServerDecoratorTest.groovy b/dd-java-agent/instrumentation/spring/spring-webmvc/spring-webmvc-6.0/src/test/groovy/datadog/trace/instrumentation/springweb6/SpringWebHttpServerDecoratorTest.groovy new file mode 100644 index 00000000000..6979a46dff6 --- /dev/null +++ b/dd-java-agent/instrumentation/spring/spring-webmvc/spring-webmvc-6.0/src/test/groovy/datadog/trace/instrumentation/springweb6/SpringWebHttpServerDecoratorTest.groovy @@ -0,0 +1,25 @@ +package datadog.trace.instrumentation.springweb6 + +import datadog.trace.agent.test.InstrumentationSpecification +import org.springframework.web.servlet.ModelAndView + +class SpringWebHttpServerDecoratorTest extends InstrumentationSpecification { + + def "onRender truncates long view name for tag and resource"() { + given: + def viewName = "a" * (SpringWebHttpServerDecorator.VIEW_NAME_TAG_LIMIT + 12) + def modelAndView = Stub(ModelAndView) { + getViewName() >> viewName + getView() >> null + } + def span = TEST_TRACER.buildSpan("testInstrumentation", "my operation").start() + + when: + SpringWebHttpServerDecorator.DECORATE_RENDER.onRender(span, modelAndView) + span.finish() + + then: + span.getTag("view.name").toString().length() == SpringWebHttpServerDecorator.VIEW_NAME_TAG_LIMIT + span.getResourceName().length() == SpringWebHttpServerDecorator.VIEW_NAME_RESOURCE_LIMIT + } +}