Don't report traces closed by garbage collection.
MODIFY
dd-trace-ot/src/main/java/datadog/opentracing/DDTracer.java
dd-trace-ot/src/main/java/datadog/opentracing/DDTracer.java
@@ -297,12 +297,17 @@ public class DDTracer implements io.opentracing.Tracer, Closeable {
}
}
}
- traceCount.incrementAndGet();
+ incrementTraceCount();
if (!writtenTrace.isEmpty() && sampler.sample(writtenTrace.get(0))) {
writer.write(writtenTrace);
}
}
+ /** Increment the reported trace count, but do not write a trace. */
+ void incrementTraceCount() {
+ traceCount.incrementAndGet();
+ }
+
@Override
public void close() {
PendingTrace.close();

MODIFY
dd-trace-ot/src/main/java/datadog/opentracing/PendingTrace.java
dd-trace-ot/src/main/java/datadog/opentracing/PendingTrace.java
@@ -204,11 +204,19 @@ public class PendingTrace extends ConcurrentLinkedDeque<DDSpan> {
int count = 0;
while ((ref = referenceQueue.poll()) != null) {
weakReferences.remove(ref);
+ if (isWritten.compareAndSet(false, true)) {
+ // preserve throughput count.
+ // Don't report the trace because the data comes from buggy uses of the api and is suspect.
+ tracer.incrementTraceCount();
+ }
count++;
expireReference();
}
if (count > 0) {
- log.debug("{} unfinished spans garbage collected!", count);
+ log.debug(
+ "trace {} : {} unfinished spans garbage collected. Trace will not report.",
+ traceId,
+ count);
}
return count > 0;
}

MODIFY
dd-trace-ot/src/test/groovy/datadog/opentracing/PendingTraceTest.groovy
dd-trace-ot/src/test/groovy/datadog/opentracing/PendingTraceTest.groovy
@@ -94,7 +94,7 @@ class PendingTraceTest extends Specification {
traceCount.get() == 1
}
- def "trace reported when unfinished child discarded"() {
+ def "trace does not report when unfinished child discarded"() {
when:
def child = tracer.buildSpan("child").asChildOf(rootSpan).start()
rootSpan.finish()
@@ -116,7 +116,7 @@ class PendingTraceTest extends Specification {
trace.pendingReferenceCount.get() == 0
trace.weakReferences.size() == 0
trace.asList() == [rootSpan]
- writer == [[rootSpan]]
+ writer == []
traceCount.get() == 1
}

MODIFY
dd-trace-ot/src/test/groovy/datadog/opentracing/scopemanager/ScopeManagerTest.groovy
dd-trace-ot/src/test/groovy/datadog/opentracing/scopemanager/ScopeManagerTest.groovy
@@ -10,8 +10,10 @@ import io.opentracing.Span
import io.opentracing.noop.NoopSpan
import spock.lang.Specification
import spock.lang.Subject
+import spock.lang.Timeout
import java.lang.ref.WeakReference
+import java.util.concurrent.TimeUnit
import java.util.concurrent.atomic.AtomicBoolean
import java.util.concurrent.atomic.AtomicReference
@@ -179,11 +181,13 @@ class ScopeManagerTest extends Specification {
false | true
}
+ @Timeout(value = 60, unit = TimeUnit.SECONDS)
def "hard reference on continuation prevents trace from reporting"() {
setup:
def builder = tracer.buildSpan("test")
def scope = (ContinuableScope) builder.startActive(false)
def span = scope.span()
+ def traceCount = ((DDSpan) span).context().tracer.traceCount
scope.setAsyncPropagation(true)
def continuation = scope.capture()
scope.close()
@@ -199,7 +203,9 @@ class ScopeManagerTest extends Specification {
def continuationRef = new WeakReference<>(continuation)
continuation = null // Continuation references also hold up traces.
TestUtils.awaitGC(continuationRef)
- writer.waitForTraces(1)
+ while (traceCount.get() == 0) {
+ // wait until trace count increments or timeout expires
+ }
}
if (autoClose) {
if (continuation != null) {
@@ -208,7 +214,8 @@ class ScopeManagerTest extends Specification {
}
then:
- writer == [[span]]
+ forceGC ? true : writer == [[span]]
+ traceCount.get() == 1
where:
autoClose | forceGC

Don't report traces closed by garbage collection.