From 78f203638e35358c698c2c7b68b9260a3cc54a13 Mon Sep 17 00:00:00 2001 From: dougqh Date: Tue, 1 Oct 2019 17:44:31 -0400 Subject: [PATCH] Introduced lazy proxy around DocRepository To shift the set-up timing without adding a lot of ugly code (as I did previously), I introduced a lazy dynamic proxy around the repository. I'm not really happy with this, but I consider it better than the prior approach. There is also probably a more "groovy" way to do this. As before, this change is itself non-functional. The subsequent test will enable spring-data instrumentation and alter the test. --- ...Elasticsearch53SpringRepositoryTest.groovy | 33 ++++++++++++++++--- .../transport-5.3/transport-5.3.gradle | 1 + 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/dd-java-agent/instrumentation/elasticsearch/transport-5.3/src/test/groovy/springdata/Elasticsearch53SpringRepositoryTest.groovy b/dd-java-agent/instrumentation/elasticsearch/transport-5.3/src/test/groovy/springdata/Elasticsearch53SpringRepositoryTest.groovy index 437a7e909d..c601ef1bdb 100644 --- a/dd-java-agent/instrumentation/elasticsearch/transport-5.3/src/test/groovy/springdata/Elasticsearch53SpringRepositoryTest.groovy +++ b/dd-java-agent/instrumentation/elasticsearch/transport-5.3/src/test/groovy/springdata/Elasticsearch53SpringRepositoryTest.groovy @@ -4,19 +4,44 @@ import com.anotherchrisberry.spock.extensions.retry.RetryOnFailure import datadog.trace.agent.test.AgentTestRunner import datadog.trace.api.DDSpanTypes import io.opentracing.tag.Tags -import org.springframework.context.ApplicationContext import org.springframework.context.annotation.AnnotationConfigApplicationContext import spock.lang.Shared +import java.lang.reflect.Proxy + +import java.lang.reflect.InvocationHandler +import java.lang.reflect.Method import static datadog.trace.agent.test.utils.TraceUtils.runUnderTrace @RetryOnFailure(times = 3, delaySeconds = 1) class Elasticsearch53SpringRepositoryTest extends AgentTestRunner { - @Shared - ApplicationContext applicationContext = new AnnotationConfigApplicationContext(Config) + // Setting up appContext & repo with @Shared doesn't allow + // spring-data instrumentation to applied. + // To change the timing without adding ugly checks everywhere - + // use a dynamic proxy. There's probably a more "groovy" way to do this. @Shared - DocRepository repo = applicationContext.getBean(DocRepository) + DocRepository repo = Proxy.newProxyInstance( + getClass().getClassLoader(), + [DocRepository] as Class[], + new LazyProxyInvoker()); + + static class LazyProxyInvoker implements InvocationHandler { + def repo; + + DocRepository getOrCreateRepository() { + if ( repo != null ) return repo; + + def applicationContext = new AnnotationConfigApplicationContext(Config) + repo = applicationContext.getBean(DocRepository) + return repo + } + + @Override + Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + return method.invoke(getOrCreateRepository(), args) + } + } def setup() { TEST_WRITER.clear() diff --git a/dd-java-agent/instrumentation/elasticsearch/transport-5.3/transport-5.3.gradle b/dd-java-agent/instrumentation/elasticsearch/transport-5.3/transport-5.3.gradle index 7dc6870d9b..ec47d057f2 100644 --- a/dd-java-agent/instrumentation/elasticsearch/transport-5.3/transport-5.3.gradle +++ b/dd-java-agent/instrumentation/elasticsearch/transport-5.3/transport-5.3.gradle @@ -35,6 +35,7 @@ dependencies { testCompile project(':dd-java-agent:instrumentation:apache-httpasyncclient-4') testCompile project(':dd-java-agent:instrumentation:netty-4.1') + // testCompile project(':dd-java-agent:instrumentation:spring-data-1.9') testCompile group: 'org.apache.logging.log4j', name: 'log4j-core', version: '2.11.0' testCompile group: 'org.apache.logging.log4j', name: 'log4j-api', version: '2.11.0'