adding a list of traces to rebuild the entire trace for DD
This commit is contained in:
parent
a3b1d24fa8
commit
7e7700f1e2
|
@ -1,6 +1,9 @@
|
||||||
package com.datadoghq.trace.impl;
|
package com.datadoghq.trace.impl;
|
||||||
|
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonGetter;
|
import com.fasterxml.jackson.annotation.JsonGetter;
|
||||||
|
|
||||||
|
@ -17,19 +20,27 @@ public class DDSpan implements io.opentracing.Span {
|
||||||
protected long startTimeNano; // Only used to measure nano time durations
|
protected long startTimeNano; // Only used to measure nano time durations
|
||||||
protected long durationNano;
|
protected long durationNano;
|
||||||
protected final DDSpanContext context;
|
protected final DDSpanContext context;
|
||||||
|
protected final LinkedHashSet<Span> traces;
|
||||||
|
|
||||||
DDSpan(
|
DDSpan(
|
||||||
Tracer tracer,
|
Tracer tracer,
|
||||||
String operationName,
|
String operationName,
|
||||||
|
LinkedHashSet<Span> traces,
|
||||||
Map<String, Object> tags,
|
Map<String, Object> tags,
|
||||||
Long timestamp,
|
Long timestamp,
|
||||||
DDSpanContext context) {
|
DDSpanContext context) {
|
||||||
|
|
||||||
this.tracer = tracer;
|
this.tracer = tracer;
|
||||||
this.operationName = operationName;
|
this.operationName = operationName;
|
||||||
|
this.traces = Optional.ofNullable(traces).orElse(new LinkedHashSet<>());
|
||||||
this.tags = tags;
|
this.tags = tags;
|
||||||
this.startTime = System.currentTimeMillis()*1000000;
|
this.startTime = System.currentTimeMillis() * 1000000;
|
||||||
this.startTimeNano = System.nanoTime();
|
this.startTimeNano = System.nanoTime();
|
||||||
this.context = context;
|
this.context = context;
|
||||||
|
|
||||||
|
// track each span of the trace
|
||||||
|
this.traces.add(this);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public SpanContext context() {
|
public SpanContext context() {
|
||||||
|
@ -37,17 +48,26 @@ public class DDSpan implements io.opentracing.Span {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void finish() {
|
public void finish() {
|
||||||
this.durationNano = System.nanoTime() - startTimeNano;
|
finish(System.nanoTime());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void finish(long stopTimeMicro) {
|
public void finish(long stopTimeMicro) {
|
||||||
this.durationNano = stopTimeMicro * 1000L - startTime;
|
this.durationNano = stopTimeMicro * 1000L - startTime;
|
||||||
|
if (this.isRootSpan()) {
|
||||||
|
this.traces.stream()
|
||||||
|
.filter(s -> ((DDSpanContext) s.context()).getSpanId() != ((DDSpanContext) this.context()).getSpanId())
|
||||||
|
.forEach(s -> s.finish());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void close() {
|
public void close() {
|
||||||
this.finish();
|
this.finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isRootSpan() {
|
||||||
|
return context.getTraceId() == context.getSpanId();
|
||||||
|
}
|
||||||
|
|
||||||
public io.opentracing.Span setTag(String tag, String value) {
|
public io.opentracing.Span setTag(String tag, String value) {
|
||||||
return this.setTag(tag, value);
|
return this.setTag(tag, value);
|
||||||
}
|
}
|
||||||
|
@ -91,9 +111,11 @@ public class DDSpan implements io.opentracing.Span {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Span setOperationName(String operationName) {
|
public Span setOperationName(String operationName) {
|
||||||
if(this.operationName!=null)
|
// FIXME: @renaud, the operationName (mandatory) is always set by the constructor
|
||||||
throw new IllegalArgumentException("The operationName is already assigned.");
|
// FIXME: should be an UnsupportedOperation if we don't want to update the operationName + final
|
||||||
|
if (this.operationName != null) {
|
||||||
|
throw new IllegalArgumentException("The operationName is already assigned.");
|
||||||
|
}
|
||||||
this.operationName = operationName;
|
this.operationName = operationName;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
@ -159,4 +181,8 @@ public class DDSpan implements io.opentracing.Span {
|
||||||
public int getError() {
|
public int getError() {
|
||||||
return context.getErrorFlag() ? 1 : 0;
|
return context.getErrorFlag() ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public LinkedHashSet<Span> getTraces() {
|
||||||
|
return traces;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,6 @@
|
||||||
package com.datadoghq.trace.impl;
|
package com.datadoghq.trace.impl;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.*;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
import com.datadoghq.trace.Utils.TracerLogger;
|
import com.datadoghq.trace.Utils.TracerLogger;
|
||||||
|
|
||||||
|
@ -34,7 +31,7 @@ public class Tracer implements io.opentracing.Tracer {
|
||||||
private final String operationName;
|
private final String operationName;
|
||||||
private Map<String, Object> tags = new HashMap<>();
|
private Map<String, Object> tags = new HashMap<>();
|
||||||
private Long timestamp;
|
private Long timestamp;
|
||||||
private SpanContext parent;
|
private DDSpan parent;
|
||||||
private String serviceName;
|
private String serviceName;
|
||||||
private String resourceName;
|
private String resourceName;
|
||||||
private boolean errorFlag;
|
private boolean errorFlag;
|
||||||
|
@ -45,12 +42,14 @@ public class Tracer implements io.opentracing.Tracer {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Tracer.SpanBuilder asChildOf(SpanContext spanContext) {
|
public Tracer.SpanBuilder asChildOf(SpanContext spanContext) {
|
||||||
this.parent = spanContext;
|
throw new UnsupportedOperationException("Should be a complete span");
|
||||||
return this;
|
//this.parent = spanContext;
|
||||||
|
//return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Tracer.SpanBuilder asChildOf(Span span) {
|
public Tracer.SpanBuilder asChildOf(Span span) {
|
||||||
return asChildOf(span.context());
|
this.parent = (DDSpan) span;
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Tracer.SpanBuilder addReference(String referenceType, SpanContext spanContext) {
|
public Tracer.SpanBuilder addReference(String referenceType, SpanContext spanContext) {
|
||||||
|
@ -106,9 +105,15 @@ public class Tracer implements io.opentracing.Tracer {
|
||||||
DDSpanContext context = buildTheSpanContext();
|
DDSpanContext context = buildTheSpanContext();
|
||||||
logger.startNewSpan(this.operationName, context.getSpanId());
|
logger.startNewSpan(this.operationName, context.getSpanId());
|
||||||
|
|
||||||
|
LinkedHashSet traces = null;
|
||||||
|
if (this.parent != null) {
|
||||||
|
traces = parent.getTraces();
|
||||||
|
}
|
||||||
|
|
||||||
return new DDSpan(
|
return new DDSpan(
|
||||||
Tracer.this,
|
Tracer.this,
|
||||||
this.operationName,
|
this.operationName,
|
||||||
|
traces,
|
||||||
this.tags,
|
this.tags,
|
||||||
this.timestamp,
|
this.timestamp,
|
||||||
context);
|
context);
|
||||||
|
@ -120,7 +125,7 @@ public class Tracer implements io.opentracing.Tracer {
|
||||||
|
|
||||||
long generatedId = generateNewId();
|
long generatedId = generateNewId();
|
||||||
if (this.parent != null) {
|
if (this.parent != null) {
|
||||||
DDSpanContext p = (DDSpanContext) this.parent;
|
DDSpanContext p = (DDSpanContext) this.parent.context();
|
||||||
context = new DDSpanContext(
|
context = new DDSpanContext(
|
||||||
p.getTraceId(),
|
p.getTraceId(),
|
||||||
generatedId,
|
generatedId,
|
||||||
|
@ -154,7 +159,7 @@ public class Tracer implements io.opentracing.Tracer {
|
||||||
if (parent == null) {
|
if (parent == null) {
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
return parent.baggageItems();
|
return parent.context().baggageItems();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,10 +27,8 @@ public class Example {
|
||||||
.withServiceName("service-name")
|
.withServiceName("service-name")
|
||||||
.start();
|
.start();
|
||||||
|
|
||||||
child.finish();
|
|
||||||
|
|
||||||
writer.write(parent);
|
|
||||||
writer.write(child);
|
|
||||||
|
|
||||||
writer.close();
|
writer.close();
|
||||||
|
|
||||||
|
|
|
@ -5,11 +5,13 @@ import org.junit.After;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
public class DDSpanBuilderTest {
|
public class DDSpanBuilderTest {
|
||||||
|
@ -168,4 +170,28 @@ public class DDSpanBuilderTest {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldTrackAllSpanInTrace() {
|
||||||
|
|
||||||
|
ArrayList<DDSpan> spans = new ArrayList<DDSpan>();
|
||||||
|
ArrayList<DDSpan> spansClone = new ArrayList<DDSpan>();
|
||||||
|
final int nbSamples = 10;
|
||||||
|
|
||||||
|
DDSpan root = (DDSpan) tracer.buildSpan("fake_O").start();
|
||||||
|
spans.add(root);
|
||||||
|
|
||||||
|
for (int i = 1; i <= 10; i++) {
|
||||||
|
spans.add((DDSpan) tracer.buildSpan("fake_" + i).asChildOf(spans.get(i - 1)).start());
|
||||||
|
}
|
||||||
|
|
||||||
|
assertThat(root.getTraces()).hasSize(nbSamples + 1);
|
||||||
|
assertThat(root.getTraces()).containsAll(spans);
|
||||||
|
assertThat(spans.get((int) (Math.random() * nbSamples)).getTraces()).containsAll(spans);
|
||||||
|
|
||||||
|
root.finish();
|
||||||
|
spans.forEach(span -> assertThat(span.getDurationNano()).isNotNull());
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -28,6 +28,7 @@ public class DDSpanTest {
|
||||||
"fakeName",
|
"fakeName",
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
|
null,
|
||||||
context
|
context
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -50,13 +51,13 @@ public class DDSpanTest {
|
||||||
expectedOperationName1,
|
expectedOperationName1,
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
|
null,
|
||||||
null
|
null
|
||||||
);
|
);
|
||||||
|
|
||||||
assertThat(span.getOperationName()).isEqualTo(expectedOperationName1);
|
assertThat(span.getOperationName()).isEqualTo(expectedOperationName1);
|
||||||
|
|
||||||
span.setOperationName(expectedOperationName2);
|
span.setOperationName(expectedOperationName2);
|
||||||
|
|
||||||
assertThat(span.getOperationName()).isEqualTo(expectedOperationName1);
|
assertThat(span.getOperationName()).isEqualTo(expectedOperationName1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue