Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve resource naming for spring data repositories #4411

Merged
merged 1 commit into from
Dec 15, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import java.lang.reflect.Method
import java.lang.reflect.Proxy

import static datadog.trace.agent.test.utils.TraceUtils.runUnderTrace
import static datadog.trace.api.config.TraceInstrumentationConfig.SPRING_DATA_REPOSITORY_INTERFACE_RESOURCE_NAME
import static datadog.trace.bootstrap.instrumentation.api.AgentTracer.activeSpan

@Retry(count = 3, delay = 1000, mode = Retry.Mode.SETUP_FEATURE_CLEANUP)
Expand Down Expand Up @@ -74,7 +75,7 @@ class Elasticsearch53SpringRepositoryTest extends AgentTestRunner {

def "test empty repo"() {
setup:

injectSysConfig(SPRING_DATA_REPOSITORY_INTERFACE_RESOURCE_NAME, "false")
when:
def result = repo.findAll()

Expand Down Expand Up @@ -135,7 +136,7 @@ class Elasticsearch53SpringRepositoryTest extends AgentTestRunner {
sortSpansByStart()
trace(3) {
span {
resourceName "ElasticsearchRepository.index"
resourceName "DocRepository.index"
operationName "repository.operation"
tags {
"$Tags.COMPONENT" "spring-data"
Expand Down Expand Up @@ -210,7 +211,7 @@ class Elasticsearch53SpringRepositoryTest extends AgentTestRunner {
sortSpansByStart()
trace(2) {
span {
resourceName "CrudRepository.findById"
resourceName "DocRepository.findById"
operationName "repository.operation"
tags {
"$Tags.COMPONENT" "spring-data"
Expand Down Expand Up @@ -254,7 +255,7 @@ class Elasticsearch53SpringRepositoryTest extends AgentTestRunner {
sortSpansByStart()
trace(3) {
span {
resourceName "ElasticsearchRepository.index"
resourceName "DocRepository.index"
operationName "repository.operation"
tags {
"$Tags.COMPONENT" "spring-data"
Expand Down Expand Up @@ -304,7 +305,7 @@ class Elasticsearch53SpringRepositoryTest extends AgentTestRunner {
}
trace(2) {
span {
resourceName "CrudRepository.findById"
resourceName "DocRepository.findById"
operationName "repository.operation"
tags {
"$Tags.COMPONENT" "spring-data"
Expand Down Expand Up @@ -347,7 +348,7 @@ class Elasticsearch53SpringRepositoryTest extends AgentTestRunner {
sortSpansByStart()
trace(3) {
span {
resourceName "CrudRepository.deleteById"
resourceName "DocRepository.deleteById"
operationName "repository.operation"
tags {
"$Tags.COMPONENT" "spring-data"
Expand Down Expand Up @@ -397,7 +398,7 @@ class Elasticsearch53SpringRepositoryTest extends AgentTestRunner {

trace(2) {
span {
resourceName "CrudRepository.findAll"
resourceName "DocRepository.findAll"
operationName "repository.operation"
tags {
"$Tags.COMPONENT" "spring-data"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,6 @@ public final class InterceptingRepositoryProxyPostProcessor
@Override
public void postProcess(
final ProxyFactory factory, final RepositoryInformation repositoryInformation) {
factory.addAdvice(0, RepositoryInterceptor.INSTANCE);
factory.addAdvice(0, new RepositoryInterceptor(repositoryInformation.getRepositoryInterface()));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,11 @@
import org.springframework.data.repository.Repository;

final class RepositoryInterceptor implements MethodInterceptor {
public static final MethodInterceptor INSTANCE = new RepositoryInterceptor();
private final Class<?> repositoryInterface;

private RepositoryInterceptor() {}
RepositoryInterceptor(Class<?> repositoryInterface) {
this.repositoryInterface = repositoryInterface;
}

@Override
public Object invoke(final MethodInvocation methodInvocation) throws Throwable {
Expand All @@ -31,7 +33,7 @@ public Object invoke(final MethodInvocation methodInvocation) throws Throwable {

final AgentSpan span = startSpan(REPOSITORY_OPERATION);
DECORATOR.afterStart(span);
DECORATOR.onOperation(span, invokedMethod);
DECORATOR.onOperation(span, invokedMethod, repositoryInterface);

final AgentScope scope = activateSpan(span);
scope.setAsyncPropagation(true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,19 @@

package datadog.trace.instrumentation.springdata;

import datadog.trace.api.Config;
import datadog.trace.bootstrap.instrumentation.api.AgentSpan;
import datadog.trace.bootstrap.instrumentation.api.UTF8BytesString;
import datadog.trace.bootstrap.instrumentation.decorator.ClientDecorator;
import java.lang.reflect.Method;
import javax.annotation.Nullable;

public final class SpringDataDecorator extends ClientDecorator {
public static final CharSequence REPOSITORY_OPERATION =
UTF8BytesString.create("repository.operation");
public static final CharSequence SPRING_DATA = UTF8BytesString.create("spring-data");
public static final SpringDataDecorator DECORATOR = new SpringDataDecorator();

private SpringDataDecorator() {}

@Override
protected String service() {
return null;
Expand All @@ -35,13 +35,14 @@ protected CharSequence component() {
return SPRING_DATA;
}

public AgentSpan onOperation(final AgentSpan span, final Method method) {
public void onOperation(
final AgentSpan span, final Method method, @Nullable final Class<?> repositoryIntf) {
assert span != null;
assert method != null;

if (method != null) {
if (repositoryIntf != null && Config.get().isSpringDataRepositoryInterfaceResourceName()) {
span.setResourceName(spanNameForMethod(repositoryIntf, method));
} else {
span.setResourceName(spanNameForMethod(method));
}
return span;
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// This file includes software developed at SignalFx

import datadog.trace.agent.test.AgentTestRunner
import datadog.trace.api.config.TraceInstrumentationConfig
import datadog.trace.bootstrap.instrumentation.api.Tags
import org.springframework.context.annotation.AnnotationConfigApplicationContext
import spring.jpa.JpaCustomer
Expand Down Expand Up @@ -51,6 +52,7 @@ class SpringJpaTest extends AgentTestRunner {
TEST_WRITER.clear()

setup:
injectSysConfig(TraceInstrumentationConfig.SPRING_DATA_REPOSITORY_INTERFACE_RESOURCE_NAME, useEnhancedNaming)
def customer = new JpaCustomer("Bob", "Anonymous")

expect:
Expand All @@ -61,7 +63,7 @@ class SpringJpaTest extends AgentTestRunner {
trace(2) {
span {
operationName "repository.operation"
resourceName "JpaRepository.findAll"
resourceName "${intfName}.findAll"
errored false
measured true
tags {
Expand Down Expand Up @@ -100,7 +102,7 @@ class SpringJpaTest extends AgentTestRunner {
trace(2) {
span {
operationName "repository.operation"
resourceName "CrudRepository.save"
resourceName "${intfName}.save"
errored false
measured true
tags {
Expand Down Expand Up @@ -139,7 +141,7 @@ class SpringJpaTest extends AgentTestRunner {
trace(3) {
span {
operationName "repository.operation"
resourceName "CrudRepository.save"
resourceName "${intfName}.save"
errored false
measured true
tags {
Expand Down Expand Up @@ -227,7 +229,7 @@ class SpringJpaTest extends AgentTestRunner {
trace(3) {
span {
operationName "repository.operation"
resourceName "CrudRepository.delete"
resourceName "${intfName}.delete"
errored false
measured true
tags {
Expand Down Expand Up @@ -269,5 +271,9 @@ class SpringJpaTest extends AgentTestRunner {
}
}
TEST_WRITER.clear()
where:
useEnhancedNaming | intfName
"true" | "JpaCustomerRepository"
"false" | "CrudRepository"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
package spring.jpa;

import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.repository.CrudRepository;

public interface JpaCustomerRepository extends JpaRepository<JpaCustomer, Long> {
public interface JpaCustomerRepository extends CrudRepository<JpaCustomer, Long> {
List<JpaCustomer> findByLastName(String lastName);
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ class SpringBootWebfluxIntegrationTest extends AbstractServerSmokeTest {
protected Set<String> expectedTraces() {
return [
"\\[netty\\.request:GET /fruits/\\{name}\\[FruitRouter\\.lambda:FruitRouter\\.lambda]\\[repository\\.operation:FruitRepository\\.findByName\\[h2\\.query:.*",
"\\[netty\\.request:GET /fruits\\[FruitRouter\\.lambda:FruitRouter\\.lambda]\\[repository\\.operation:CrudRepository\\.findAll\\[h2.query:.*",
"\\[netty\\.request:GET /fruits\\[FruitRouter\\.lambda:FruitRouter\\.lambda]\\[repository\\.operation:FruitRepository\\.findAll\\[h2.query:.*",
Pattern.quote("[netty.request:GET /hello[WebController.hello:WebController.hello]]")
]
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ class SpringBootWebmvcIntegrationTest extends AbstractServerSmokeTest {
@Override
protected Set<String> expectedTraces() {
return [
"\\[servlet\\.request:GET /fruits\\[spring\\.handler:FruitController\\.listFruits\\[repository\\.operation:CrudRepository\\.findAll\\[h2\\.query:.*",
"\\[servlet\\.request:GET /fruits\\[spring\\.handler:FruitController\\.listFruits\\[repository\\.operation:FruitRepository\\.findAll\\[h2\\.query:.*",
"\\[servlet\\.request:GET /fruits/\\{name}\\[spring\\.handler:FruitController\\.findOneFruit\\[repository\\.operation:FruitRepository\\.findByName\\[h2\\.query:.*"
]
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ class SpringBootWebfluxIntegrationTest extends AbstractServerSmokeTest {
protected Set<String> expectedTraces() {
return [
"\\[netty\\.request:GET /fruits/\\{name}\\[FruitRouter\\.lambda:FruitRouter\\.lambda]\\[repository\\.operation:FruitRepository\\.findByName\\[h2\\.query:.*",
"\\[netty\\.request:GET /fruits\\[FruitRouter\\.lambda:FruitRouter\\.lambda]\\[repository\\.operation:CrudRepository\\.findAll\\[h2.query:.*",
"\\[netty\\.request:GET /fruits\\[FruitRouter\\.lambda:FruitRouter\\.lambda]\\[repository\\.operation:FruitRepository\\.findAll\\[h2.query:.*",
Pattern.quote("[netty.request:GET /hello[WebController.hello:WebController.hello]]")
]
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ class SpringBootWebfluxIntegrationTest extends AbstractServerSmokeTest {
protected Set<String> expectedTraces() {
return [
"\\[netty\\.request:GET /fruits/\\{name}\\[FruitRouter\\.lambda:FruitRouter\\.lambda]\\[repository\\.operation:FruitRepository\\.findByName\\[h2\\.query:.*",
"\\[netty\\.request:GET /fruits\\[FruitRouter\\.lambda:FruitRouter\\.lambda]\\[repository\\.operation:CrudRepository\\.findAll\\[h2.query:.*",
"\\[netty\\.request:GET /fruits\\[FruitRouter\\.lambda:FruitRouter\\.lambda]\\[repository\\.operation:FruitRepository\\.findAll\\[h2.query:.*",
Pattern.quote("[netty.request:GET /hello[WebController.hello:WebController.hello]]")
]
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ class SpringBootWebmvcIntegrationTest extends AbstractServerSmokeTest {
@Override
protected Set<String> expectedTraces() {
return [
"\\[servlet\\.request:GET /fruits\\[repository\\.operation:CrudRepository\\.findAll\\[h2\\.query:.*",
"\\[servlet\\.request:GET /fruits\\[repository\\.operation:FruitRepository\\.findAll\\[h2\\.query:.*",
//FIXME: it should rather be
//"\\[servlet\\.request:GET /fruits\\[spring\\.handler:FruitController\\.listFruits\\[repository\\.operation:CrudRepository\\.findAll\\[h2\\.query:.*",
//"\\[servlet\\.request:GET /fruits\\[spring\\.handler:FruitController\\.listFruits\\[repository\\.operation:FruitRepository\\.findAll\\[h2\\.query:.*",
"\\[servlet\\.request:GET /fruits/banana\\[repository\\.operation:FruitRepository\\.findByName\\[h2\\.query:.*"
//FIXME: it should rather be:
// "\\[servlet\\.request:GET /fruits/\\{name}\\[spring\\.handler:FruitController\\.findOneFruit\\[repository\\.operation:FruitRepository\\.findByName\\[h2\\.query:.*"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,9 @@ public final class TraceInstrumentationConfig {
public static final String SERVLET_ROOT_CONTEXT_SERVICE_NAME =
"trace.servlet.root-context.service.name";

public static final String SPRING_DATA_REPOSITORY_INTERFACE_RESOURCE_NAME =
"spring-data.repository.interface.resource-name";

public static final String RESOLVER_CACHE_CONFIG = "resolver.cache.config";
public static final String RESOLVER_USE_LOADCLASS = "resolver.use.loadclass";
public static final String RESOLVER_RESET_INTERVAL = "resolver.reset.interval";
Expand Down
10 changes: 10 additions & 0 deletions internal-api/src/main/java/datadog/trace/api/Config.java
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,7 @@
import static datadog.trace.api.config.TraceInstrumentationConfig.SERVLET_ASYNC_TIMEOUT_ERROR;
import static datadog.trace.api.config.TraceInstrumentationConfig.SERVLET_PRINCIPAL_ENABLED;
import static datadog.trace.api.config.TraceInstrumentationConfig.SERVLET_ROOT_CONTEXT_SERVICE_NAME;
import static datadog.trace.api.config.TraceInstrumentationConfig.SPRING_DATA_REPOSITORY_INTERFACE_RESOURCE_NAME;
import static datadog.trace.api.config.TracerConfig.AGENT_HOST;
import static datadog.trace.api.config.TracerConfig.AGENT_NAMED_PIPE;
import static datadog.trace.api.config.TracerConfig.AGENT_PORT_LEGACY;
Expand Down Expand Up @@ -561,6 +562,8 @@ static class HostNameHolder {
private final boolean servletPrincipalEnabled;
private final boolean servletAsyncTimeoutError;

private final boolean springDataRepositoryInterfaceResourceName;

private final int xDatadogTagsMaxLength;

private final boolean traceAgentV05Enabled;
Expand Down Expand Up @@ -837,6 +840,9 @@ private Config(final ConfigProvider configProvider, final InstrumenterConfig ins

splitByTags = tryMakeImmutableSet(configProvider.getList(SPLIT_BY_TAGS));

springDataRepositoryInterfaceResourceName =
configProvider.getBoolean(SPRING_DATA_REPOSITORY_INTERFACE_RESOURCE_NAME, true);

scopeDepthLimit = configProvider.getInteger(SCOPE_DEPTH_LIMIT, DEFAULT_SCOPE_DEPTH_LIMIT);

scopeStrictMode = configProvider.getBoolean(SCOPE_STRICT_MODE, false);
Expand Down Expand Up @@ -1976,6 +1982,10 @@ public boolean isServletPrincipalEnabled() {
return servletPrincipalEnabled;
}

public boolean isSpringDataRepositoryInterfaceResourceName() {
return springDataRepositoryInterfaceResourceName;
}

public int getxDatadogTagsMaxLength() {
return xDatadogTagsMaxLength;
}
Expand Down