-
Notifications
You must be signed in to change notification settings - Fork 312
Dougqh/spring data support #1014
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
Changes from all commits
5f7e060
6d38831
1335296
7a366f0
60e9cc2
ab52988
5f5605f
d2ba6af
122533f
0c3e057
85389b4
e43baf8
172ff74
7c5e74b
6b5acc8
8a89547
a242e08
680c442
02c7e5b
64e3ebc
d0cf564
682cc40
59416bf
64a5fd6
1e8af55
3b14a1c
eb05fc7
45f6edf
4d287c6
56cebb1
5cb0cc7
d192811
ac557ed
b91648d
48b7018
1b1cc34
3780cec
aeef4f4
8b42d28
02c2d43
ec9e220
0dc63d7
85240a9
78f2036
dfcf9c6
001d1d8
b01bef7
5edff68
01b9220
e696aa7
3e6419d
63ef181
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,19 +4,52 @@ 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 | ||
} | ||
|
||
TEST_WRITER.clear() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think a helper routine for this capture set-up traces and discard idiom might be worth adding. |
||
runUnderTrace("setup") { | ||
def applicationContext = new AnnotationConfigApplicationContext(Config) | ||
repo = applicationContext.getBean(DocRepository) | ||
} | ||
TEST_WRITER.waitForTraces(1) | ||
TEST_WRITER.clear() | ||
|
||
return repo | ||
} | ||
|
||
@Override | ||
Object invoke(Object proxy, Method method, Object[] args) throws Throwable { | ||
return method.invoke(getOrCreateRepository(), args) | ||
} | ||
} | ||
|
||
def setup() { | ||
TEST_WRITER.clear() | ||
|
@@ -36,13 +69,25 @@ class Elasticsearch53SpringRepositoryTest extends AgentTestRunner { | |
|
||
and: | ||
assertTraces(1) { | ||
trace(0, 1) { | ||
trace(0, 2) { | ||
span(0) { | ||
operationName "repository.operation" | ||
resourceName "CrudRepository.findAll" | ||
tags { | ||
"$Tags.COMPONENT.key" "spring-data" | ||
"$Tags.SPAN_KIND.key" Tags.SPAN_KIND_CLIENT | ||
defaultTags() | ||
} | ||
} | ||
|
||
span(1) { | ||
serviceName "elasticsearch" | ||
resourceName "SearchAction" | ||
operationName "elasticsearch.query" | ||
spanType DDSpanTypes.ELASTICSEARCH | ||
errored false | ||
childOf(span(0)) | ||
|
||
tags { | ||
"$Tags.COMPONENT.key" "elasticsearch-java" | ||
"$Tags.DB_TYPE.key" "elasticsearch" | ||
|
@@ -69,34 +114,23 @@ class Elasticsearch53SpringRepositoryTest extends AgentTestRunner { | |
repo.index(doc) == doc | ||
|
||
and: | ||
assertTraces(2) { | ||
trace(0, 1) { | ||
assertTraces(1) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Rarely (<5%) of the time, I haven't seen index actions fail. I'd like to address this is possible rather than introducing additional instability into the tests. |
||
trace(0, 3) { | ||
span(0) { | ||
resourceName "IndexAction" | ||
operationName "elasticsearch.query" | ||
spanType DDSpanTypes.ELASTICSEARCH | ||
resourceName "ElasticsearchRepository.index" | ||
operationName "repository.operation" | ||
tags { | ||
"$Tags.COMPONENT.key" "elasticsearch-java" | ||
"$Tags.DB_TYPE.key" "elasticsearch" | ||
"$Tags.COMPONENT.key" "spring-data" | ||
"$Tags.SPAN_KIND.key" Tags.SPAN_KIND_CLIENT | ||
"elasticsearch.action" "IndexAction" | ||
"elasticsearch.request" "IndexRequest" | ||
"elasticsearch.request.indices" indexName | ||
"elasticsearch.request.write.type" "doc" | ||
"elasticsearch.request.write.version"(-3) | ||
"elasticsearch.response.status" 201 | ||
"elasticsearch.shard.replication.failed" 0 | ||
"elasticsearch.shard.replication.successful" 1 | ||
"elasticsearch.shard.replication.total" 2 | ||
defaultTags() | ||
} | ||
} | ||
} | ||
trace(1, 1) { | ||
span(0) { | ||
|
||
span(1) { | ||
resourceName "RefreshAction" | ||
operationName "elasticsearch.query" | ||
spanType DDSpanTypes.ELASTICSEARCH | ||
childOf(span(0)) | ||
tags { | ||
"$Tags.COMPONENT.key" "elasticsearch-java" | ||
"$Tags.DB_TYPE.key" "elasticsearch" | ||
|
@@ -110,6 +144,28 @@ class Elasticsearch53SpringRepositoryTest extends AgentTestRunner { | |
defaultTags() | ||
} | ||
} | ||
|
||
span(2) { | ||
resourceName "IndexAction" | ||
operationName "elasticsearch.query" | ||
spanType DDSpanTypes.ELASTICSEARCH | ||
childOf(span(0)) | ||
tags { | ||
"$Tags.COMPONENT.key" "elasticsearch-java" | ||
"$Tags.DB_TYPE.key" "elasticsearch" | ||
"$Tags.SPAN_KIND.key" Tags.SPAN_KIND_CLIENT | ||
"elasticsearch.action" "IndexAction" | ||
"elasticsearch.request" "IndexRequest" | ||
"elasticsearch.request.indices" indexName | ||
"elasticsearch.request.write.type" "doc" | ||
"elasticsearch.request.write.version"(-3) | ||
"elasticsearch.response.status" 201 | ||
"elasticsearch.shard.replication.failed" 0 | ||
"elasticsearch.shard.replication.successful" 1 | ||
"elasticsearch.shard.replication.total" 2 | ||
defaultTags() | ||
} | ||
} | ||
} | ||
} | ||
TEST_WRITER.clear() | ||
|
@@ -119,12 +175,23 @@ class Elasticsearch53SpringRepositoryTest extends AgentTestRunner { | |
|
||
and: | ||
assertTraces(1) { | ||
trace(0, 1) { | ||
trace(0, 2) { | ||
span(0) { | ||
resourceName "CrudRepository.findById" | ||
operationName "repository.operation" | ||
tags { | ||
"$Tags.COMPONENT.key" "spring-data" | ||
"$Tags.SPAN_KIND.key" Tags.SPAN_KIND_CLIENT | ||
defaultTags() | ||
} | ||
} | ||
|
||
span(1) { | ||
serviceName "elasticsearch" | ||
resourceName "GetAction" | ||
operationName "elasticsearch.query" | ||
spanType DDSpanTypes.ELASTICSEARCH | ||
childOf(span(0)) | ||
tags { | ||
"$Tags.COMPONENT.key" "elasticsearch-java" | ||
"$Tags.DB_TYPE.key" "elasticsearch" | ||
|
@@ -150,12 +217,40 @@ class Elasticsearch53SpringRepositoryTest extends AgentTestRunner { | |
repo.findById("1").get() == doc | ||
|
||
and: | ||
assertTraces(3) { | ||
trace(0, 1) { | ||
assertTraces(2) { | ||
trace(0, 3) { | ||
span(0) { | ||
resourceName "ElasticsearchRepository.index" | ||
operationName "repository.operation" | ||
tags { | ||
"$Tags.COMPONENT.key" "spring-data" | ||
"$Tags.SPAN_KIND.key" Tags.SPAN_KIND_CLIENT | ||
defaultTags() | ||
} | ||
} | ||
span(1) { | ||
resourceName "RefreshAction" | ||
operationName "elasticsearch.query" | ||
spanType DDSpanTypes.ELASTICSEARCH | ||
childOf(span(0)) | ||
tags { | ||
"$Tags.COMPONENT.key" "elasticsearch-java" | ||
dougqh marked this conversation as resolved.
Show resolved
Hide resolved
|
||
"$Tags.DB_TYPE.key" "elasticsearch" | ||
"$Tags.SPAN_KIND.key" Tags.SPAN_KIND_CLIENT | ||
"elasticsearch.action" "RefreshAction" | ||
"elasticsearch.request" "RefreshRequest" | ||
"elasticsearch.request.indices" indexName | ||
"elasticsearch.shard.broadcast.failed" 0 | ||
"elasticsearch.shard.broadcast.successful" 5 | ||
"elasticsearch.shard.broadcast.total" 10 | ||
defaultTags() | ||
} | ||
} | ||
span(2) { | ||
resourceName "IndexAction" | ||
operationName "elasticsearch.query" | ||
spanType DDSpanTypes.ELASTICSEARCH | ||
childOf(span(0)) | ||
tags { | ||
"$Tags.COMPONENT.key" "elasticsearch-java" | ||
"$Tags.DB_TYPE.key" "elasticsearch" | ||
|
@@ -173,31 +268,23 @@ class Elasticsearch53SpringRepositoryTest extends AgentTestRunner { | |
} | ||
} | ||
} | ||
trace(1, 1) { | ||
trace(1, 2) { | ||
span(0) { | ||
resourceName "RefreshAction" | ||
operationName "elasticsearch.query" | ||
spanType DDSpanTypes.ELASTICSEARCH | ||
resourceName "CrudRepository.findById" | ||
operationName "repository.operation" | ||
tags { | ||
"$Tags.COMPONENT.key" "elasticsearch-java" | ||
"$Tags.DB_TYPE.key" "elasticsearch" | ||
"$Tags.COMPONENT.key" "spring-data" | ||
"$Tags.SPAN_KIND.key" Tags.SPAN_KIND_CLIENT | ||
"elasticsearch.action" "RefreshAction" | ||
"elasticsearch.request" "RefreshRequest" | ||
"elasticsearch.request.indices" indexName | ||
"elasticsearch.shard.broadcast.failed" 0 | ||
"elasticsearch.shard.broadcast.successful" 5 | ||
"elasticsearch.shard.broadcast.total" 10 | ||
defaultTags() | ||
} | ||
} | ||
} | ||
trace(2, 1) { | ||
span(0) { | ||
|
||
span(1) { | ||
serviceName "elasticsearch" | ||
resourceName "GetAction" | ||
operationName "elasticsearch.query" | ||
spanType DDSpanTypes.ELASTICSEARCH | ||
childOf(span(0)) | ||
tags { | ||
"$Tags.COMPONENT.key" "elasticsearch-java" | ||
"$Tags.DB_TYPE.key" "elasticsearch" | ||
|
@@ -222,12 +309,41 @@ class Elasticsearch53SpringRepositoryTest extends AgentTestRunner { | |
!repo.findAll().iterator().hasNext() | ||
|
||
and: | ||
assertTraces(3) { | ||
trace(0, 1) { | ||
assertTraces(2) { | ||
trace(0, 3) { | ||
span(0) { | ||
resourceName "CrudRepository.deleteById" | ||
operationName "repository.operation" | ||
tags { | ||
"$Tags.COMPONENT.key" "spring-data" | ||
"$Tags.SPAN_KIND.key" Tags.SPAN_KIND_CLIENT | ||
defaultTags() | ||
} | ||
} | ||
|
||
span(1) { | ||
resourceName "RefreshAction" | ||
operationName "elasticsearch.query" | ||
spanType DDSpanTypes.ELASTICSEARCH | ||
childOf(span(0)) | ||
tags { | ||
"$Tags.COMPONENT.key" "elasticsearch-java" | ||
"$Tags.DB_TYPE.key" "elasticsearch" | ||
"$Tags.SPAN_KIND.key" Tags.SPAN_KIND_CLIENT | ||
"elasticsearch.action" "RefreshAction" | ||
"elasticsearch.request" "RefreshRequest" | ||
"elasticsearch.request.indices" indexName | ||
"elasticsearch.shard.broadcast.failed" 0 | ||
"elasticsearch.shard.broadcast.successful" 5 | ||
"elasticsearch.shard.broadcast.total" 10 | ||
defaultTags() | ||
} | ||
} | ||
span(2) { | ||
resourceName "DeleteAction" | ||
operationName "elasticsearch.query" | ||
spanType DDSpanTypes.ELASTICSEARCH | ||
childOf(span(0)) | ||
tags { | ||
"$Tags.COMPONENT.key" "elasticsearch-java" | ||
"$Tags.DB_TYPE.key" "elasticsearch" | ||
|
@@ -244,31 +360,24 @@ class Elasticsearch53SpringRepositoryTest extends AgentTestRunner { | |
} | ||
} | ||
} | ||
trace(1, 1) { | ||
|
||
trace(1, 2) { | ||
span(0) { | ||
resourceName "RefreshAction" | ||
operationName "elasticsearch.query" | ||
spanType DDSpanTypes.ELASTICSEARCH | ||
resourceName "CrudRepository.findAll" | ||
operationName "repository.operation" | ||
tags { | ||
"$Tags.COMPONENT.key" "elasticsearch-java" | ||
"$Tags.DB_TYPE.key" "elasticsearch" | ||
"$Tags.COMPONENT.key" "spring-data" | ||
"$Tags.SPAN_KIND.key" Tags.SPAN_KIND_CLIENT | ||
"elasticsearch.action" "RefreshAction" | ||
"elasticsearch.request" "RefreshRequest" | ||
"elasticsearch.request.indices" indexName | ||
"elasticsearch.shard.broadcast.failed" 0 | ||
"elasticsearch.shard.broadcast.successful" 5 | ||
"elasticsearch.shard.broadcast.total" 10 | ||
defaultTags() | ||
} | ||
} | ||
} | ||
trace(2, 1) { | ||
span(0) { | ||
|
||
span(1) { | ||
serviceName "elasticsearch" | ||
resourceName "SearchAction" | ||
operationName "elasticsearch.query" | ||
spanType DDSpanTypes.ELASTICSEARCH | ||
childOf(span(0)) | ||
tags { | ||
"$Tags.COMPONENT.key" "elasticsearch-java" | ||
"$Tags.DB_TYPE.key" "elasticsearch" | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
package spring; | ||
package spring.jpa; | ||
|
||
import javax.persistence.Entity; | ||
import javax.persistence.GeneratedValue; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I created this lazy proxy because otherwise Spring is configured before the spring-data instrumentation is available, but I don't particularly like it.
I could also change how the test set-up is done, but that was ugly in terms of refactoring the test.
Ultimately, I think it would be better if we enabled instrumentation before @shared set-up is run, but clearly, that would be larger change probably with significant ripple effects.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's kind of tricky because spock controls when
@Shared
variables are initialized and we already apply the instrumentation as early as possible. I believe any further changes would need to be done in the test runner.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If nothing else, I would think the instrumentation itself could be enabled via
@Shared
. I don't love that solution, but it is probably cleaner than what I currently resorted to doing.