RUM-3294 Add the Core Tracer tests#1924
Conversation
b9eca27 to
5eb2941
Compare
Codecov Report❌ Patch coverage is Please upload reports for the commit bac5936 to get more accurate results. Additional details and impacted files@@ Coverage Diff @@
## feature/otel-support #1924 +/- ##
========================================================
+ Coverage 56.46% 59.70% +3.24%
========================================================
Files 796 797 +1
Lines 29589 29612 +23
Branches 4852 4854 +2
========================================================
+ Hits 16705 17678 +973
+ Misses 11776 10736 -1040
- Partials 1108 1198 +90
🚀 New features to boost your workflow:
|
8e26066 to
858200e
Compare
a514f5b to
c1dc25b
Compare
858200e to
dcd9317
Compare
fd62be7 to
2c936c4
Compare
79efa36 to
d607e0a
Compare
0xnm
left a comment
There was a problem hiding this comment.
I gave it a quick look and added some comments. Also my concern is that some things are public now, can we review if all of them are needed to be public for the sake of the tests? Maybe it is better to access them with reflection instead of making public for everyone?
| policy: pull | ||
| script: | ||
| - rm -rf ~/.gradle/daemon/ | ||
| - GRADLE_OPTS="-Xmx3072m" DD_TAGS="test.configuration.variant:release" ./gradlew :features:dd-sdk-android-trace:testDebugUnitTest --stacktrace |
There was a problem hiding this comment.
| - GRADLE_OPTS="-Xmx3072m" DD_TAGS="test.configuration.variant:release" ./gradlew :features:dd-sdk-android-trace:testDebugUnitTest --stacktrace | |
| - GRADLE_OPTS="-Xmx3072m" DD_TAGS="test.configuration.variant:debug" ./gradlew :features:dd-sdk-android-trace:testDebugUnitTest --stacktrace |
There was a problem hiding this comment.
why restored ? these are api changes reflected by the changes we added in the java project to make some classes/properties available for our unit tests.
There was a problem hiding this comment.
because this file is deleted completely in this PR. It should still be there with the actual Kotlin API of this module.
|
|
||
| // This has to be placed after all other static fields to give them a chance to initialize | ||
|
|
||
| private static final Config INSTANCE = |
There was a problem hiding this comment.
why we remove this one if anyway we are going to use reflection here?
There was a problem hiding this comment.
I am removing the final modifier as I can't use reflection on that anymore with JDK17 :(. Are you aware of anyway to do it in JDK17 ?
There was a problem hiding this comment.
yes, we have tests which set static final on JDK 17 :)
| } | ||
|
|
||
| // This has to be placed after all other static fields to give them a chance to initialize | ||
| private static final InstrumenterConfig INSTANCE = |
| fun `should build span timestamp in nano`() { | ||
| // time in micro |
There was a problem hiding this comment.
| fun `should build span timestamp in nano`() { | |
| // time in micro | |
| fun `should build span timestamp in nanoseconds`() { | |
| // time in microseconds |
|
|
||
| // auto-timestamp in nanoseconds | ||
| val start = System.currentTimeMillis() | ||
| span = tracer.buildSpan(instrumentationName, expectedName).withServiceName("foo").start() |
There was a problem hiding this comment.
| span = tracer.buildSpan(instrumentationName, expectedName).withServiceName("foo").start() | |
| val secondSpan = tracer.buildSpan(instrumentationName, expectedName).withServiceName("foo").start() |
same suggestion applies to other tests - instead of using var and changing the reference, it is better to be more explicit in saying that it is another instance.
| // Give a range of +/- 5 millis | ||
| assertThat(span.startTime).isGreaterThanOrEqualTo(TimeUnit.MILLISECONDS.toNanos(start - 1)) | ||
| assertThat(span.startTime).isLessThanOrEqualTo(TimeUnit.MILLISECONDS.toNanos(stop + 1)) |
There was a problem hiding this comment.
actual offset is 1 millisecond, not 5 as it is said in the comment
There was a problem hiding this comment.
yeah...I guess they modified it without modifying the comment
| assertThat(span.traceId).isNotEqualTo(DDTraceId.ZERO) | ||
| assertThat(span.parentId).isEqualTo(DDSpanId.ZERO) | ||
| val samplingPriority = span.samplingPriority | ||
| assert(samplingPriority == null) |
There was a problem hiding this comment.
| assert(samplingPriority == null) | |
| assertThat(samplingPriority).isNull() |
There was a problem hiding this comment.
yeah for some reason that is not working, failing with a NPE and I think is because of the Java function signature at the end of the line.
There was a problem hiding this comment.
I'm not clear what do you mean. It shouldn't be any NPE here, assertThat accepts null values, so the proposed suggestion should work fine. The only assumption which comes to my mind is that type of samplingPriority is Int? and by some reason Kotlin tries to cast it to Int, but it is quite unlikely.
| val customTracer = tracerBuilder().writer(writer).config(Config.get()).defaultSpanTags(tags).build() | ||
| val span = customTracer.buildSpan(instrumentationName, "op name").withServiceName("foo").start() |
There was a problem hiding this comment.
it is better to wrap such lines call-per-call (and in other tests as well)
f7bff6f to
e87032a
Compare
0xnm
left a comment
There was a problem hiding this comment.
nice work! I added few comments/suggestions, but nothing blocking.
|
|
||
| KUBERNETES_MEMORY_REQUEST: "8Gi" | ||
| KUBERNETES_MEMORY_LIMIT: "16Gi" | ||
| DD_TRACE_REMOVE_INTEGRATION_SERVICE_NAMES_ENABLED: "false" |
There was a problem hiding this comment.
I think it is better to set this env variable only in the tasks which require it to be set (trace-debug and trace-release, probably). Not sure what it does though.
There was a problem hiding this comment.
it is not affecting any other tests, it is strictly related with the tracing tests and code but yes I could add it there, I just did not want to duplicate this line.
| * @param context the context used for the span | ||
| */ | ||
| private DDSpan( | ||
| public DDSpan( |
There was a problem hiding this comment.
is it possible to put VisibleForTesting annotation to the elements we are making public just for testing?
| whenever(mockTracer.partialFlushMinSpans) doReturn 1 | ||
| val fakeTraceId = BigInteger.valueOf(forge.aLong()) | ||
| val pendingTrace = PendingTrace(mockTracer, fakeTraceId) | ||
| val pendingTrace = createInstanceWithPrivateConstructor(PendingTrace::class.java, mockTracer, fakeTraceId) |
There was a problem hiding this comment.
which constructor is private here? we made one constructor of PendingTrace public, was it the necessary change if we are calling private constructor anyway?
There was a problem hiding this comment.
yeah forgot to turn the constructor private back
| } | ||
|
|
||
| @Test | ||
| fun `should build span timestamp in nano`() { |
There was a problem hiding this comment.
| fun `should build span timestamp in nano`() { | |
| fun `should build span timestamp in nanoseconds`() { |
| @Suppress("DEPRECATION") | ||
| span1.samplingPriority = PrioritySampling.USER_KEEP.toInt() |
There was a problem hiding this comment.
I see that we have 2 PrioritySampling classes:
com.datadog.trace.api.sampling.PrioritySamplingcom.datadog.trace.common.sampling.PrioritySampling
The latter one is deprecated, the former one is not. Probably we need to use the former one here to avoid deprecation warning?
There was a problem hiding this comment.
In their tests they are using the same class so I would rather keep it but will double check.
There was a problem hiding this comment.
well, this is essentially the same class in 2 different places of the codebase. Anyway, not sure what is the point to use the deprecated one when there is non-deprecated.
There was a problem hiding this comment.
yes, I know, I will probably figure it out better later. For now I checked their tests source and they are using the same.
| } | ||
| // When |
There was a problem hiding this comment.
| } | |
| // When | |
| } | |
| // When |
| @Test | ||
| fun `test getCurrentTimeNano`() { | ||
| // Generous 5 seconds to execute this test | ||
| assertThat( | ||
| Math.abs( | ||
| TimeUnit.NANOSECONDS.toSeconds(trace.currentTimeNano) - | ||
| TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis()) | ||
| ) | ||
| ).isLessThan(5) | ||
| } |
There was a problem hiding this comment.
what is the exact point of this test? not quite clear
There was a problem hiding this comment.
not sure, this is what they have in their test classes, I think they want to assert that the clock is not skewed
There was a problem hiding this comment.
there is non-system clock in the code we are porting? is it using NTP then or what if it is the case?
There was a problem hiding this comment.
I am really not sure, I really cannot without asking them and I cannot really ask all these details. We have 2 options here, decide to keep all the tests they have or we drop some.
There was a problem hiding this comment.
ok, let's keep it then. If there is a NTP support, then it is probably some code around it/network stack while we have our own NTP support (so double the code for the same).
| params[it]?.javaClass ?: Any::class.java | ||
| } | ||
|
|
||
| val method = this.getDeclaredMethodRecursively(methodName, true, declarationParams) |
There was a problem hiding this comment.
it is useful to search method recursively given that static methods cannot be overridden and normally, if called directly, without reflection, IDE should give a warning if method is called on the class it doesn't belong directly?
There was a problem hiding this comment.
yeah you are right it is not needed here.
a999274 to
b767ff6
Compare
0xnm
left a comment
There was a problem hiding this comment.
lgtm. I left few questions, but nothing blocking.
Also speaking of #1924 (comment) - should we add nullable/non-nullable annotations to the public Java API we bringing to have a better interop with Kotlin in order to avoid such things on the customer side? Or the only API exposed / advised to be used will be in Kotlin?
|
|
||
| public class com/datadog/trace/core/DDSpan : com/datadog/trace/api/profiling/TransientProfilingContextHolder, com/datadog/trace/bootstrap/instrumentation/api/AgentSpan, com/datadog/trace/bootstrap/instrumentation/api/AttachableWrapper, com/datadog/trace/core/CoreSpan { | ||
| public static final field CHECKPOINTED_TAG Ljava/lang/String; | ||
| public fun <init> (Ljava/lang/String;JLcom/datadog/trace/core/DDSpanContext;Ljava/util/List;)V |
There was a problem hiding this comment.
minor: given that we have a method to call private constructor now, should we make this constructor public?
There was a problem hiding this comment.
I am not really sure where this is coming from as I am just exposing the class not the constructors so I will leave it as is. I need the class exposed to cast to DDSpan in the unit tests.
There was a problem hiding this comment.
It is from this change https://github.com/DataDog/dd-sdk-android/pull/1924/files#diff-1c12b21f74915bf39d879d5d17374ad221d56bb67bed99743adc8a86dfbf944cR127 where private constructor was made public. But that is ok I believe, just was wondering about the consistency in the approach (since for PendingTrace we are using reflection to create an instance).
| stage: test | ||
| timeout: 1h | ||
| variables: | ||
| DD_TRACE_REMOVE_INTEGRATION_SERVICE_NAMES_ENABLED: "false" |
There was a problem hiding this comment.
btw is this flag still needed given that we clean up env variable in the DDSpecification and default value of this one in Config is false?
There was a problem hiding this comment.
yes I am not sure where exactly before that is still used...before the Config is even created. as you could see in my tests I assert that there is no more any DD_ property in any System or System.env and still this poses problems. Alessio from APM team recommended me to add it like this to make sure.
There was a problem hiding this comment.
We can remove it and see if it is still needed. Maybe it is not anymore.
There was a problem hiding this comment.
I tried, I will try again ;)
We only want to provide Kotlin support so normally they should not touch the Java API but it might be worthy to have the discussion for any other Java support we offer, outside of Trace. |
|
@mariusc83 Cannot it be the case that some Java objects (like spans, etc.) are exposed in the Kotlin APIs we are going to provide? |
The idea about OTel support is to only use the OTel API so they should not see any Java objects in their code. I think we are safe here. |
2bc67ec to
42d50f9
Compare
What does this PR do?
In this PR we are porting the core unit tests for the Java CoreTracer logic we borrowed from the APM Agent Java project. Please have in mind that in order to have consistency those tests and the logic around are matching exactly their groovy equivalents so no randomness was used in the input data and no forgery was added.
Motivation
What inspired you to submit this pull request?
Additional Notes
Anything else we should know when reviewing?
Review checklist (to be filled by reviewers)