Skip to content
This repository has been archived by the owner on May 23, 2023. It is now read-only.

Add SELF reference #212

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions opentracing-api/src/main/java/io/opentracing/References.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,9 @@ private References(){}
* See http://opentracing.io/spec/#causal-span-references for more information about FOLLOWS_FROM references
*/
public static final String FOLLOWS_FROM = "follows_from";

/**
* The self reference class can be used to construct a {@link Span} instance with a specific {@link SpanContext}.
*/
public static final String SELF = "self";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tedsuo should this go through Specification RFC first?

If we are making this a new required reference type, there needs to be more details about the expected tracer behavior and/or description of the use case. For example, what happens to startTime field in this case?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, just seeing this! Yes, @felixbarny an RFC would be appreciated, you can find the template here: https://github.com/opentracing/specification/blob/master/rfc_template.md

}
28 changes: 22 additions & 6 deletions opentracing-mock/src/main/java/io/opentracing/mock/MockSpan.java
Original file line number Diff line number Diff line change
Expand Up @@ -285,27 +285,43 @@ public int hashCode() {
this.references = new ArrayList<>(refs);
}
MockContext parent = findPreferredParentRef(this.references);
MockContext self = findFirstReference(this.references, References.SELF);
if (parent == null) {
// We're a root Span.
this.context = new MockContext(nextId(), nextId(), new HashMap<String, String>());
this.context = new MockContext(self != null ? self.traceId : nextId(), self != null ? self.spanId : nextId(),
self != null ? self.baggage : new HashMap<String, String>());
this.parentId = 0;
} else {
// We're a child Span.
this.context = new MockContext(parent.traceId, nextId(), mergeBaggages(this.references));
this.context = new MockContext(self != null ? self.traceId : parent.traceId, self != null ? self.spanId : nextId(),
mergeBaggages(this.references));
this.parentId = parent.spanId;
}
}

private static MockContext findPreferredParentRef(List<Reference> references) {
if(references.isEmpty()) {
return null;
MockContext firstChildOf = findFirstReference(references, References.CHILD_OF);
if (firstChildOf == null) {
// return first non self reference
// self references can never be a parent reference
for (Reference reference : references) {
if (!References.SELF.equals(reference.getReferenceType())) {
return reference.getContext();
}
}
} else {
return firstChildOf;
}
return null;
}

private static MockContext findFirstReference(List<Reference> references, String referenceToFind) {
for (Reference reference : references) {
if (References.CHILD_OF.equals(reference.getReferenceType())) {
if (referenceToFind.equals(reference.getReferenceType())) {
return reference.getContext();
}
}
return references.get(0).getContext();
return null;
}

private static Map<String, String> mergeBaggages(List<Reference> references) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,10 +112,12 @@ public <C> MockSpan.MockContext extract(Format<C> format, C carrier) {
}
};

Propagator TEXT_MAP = new Propagator() {
public static final String SPAN_ID_KEY = "spanid";
public static final String TRACE_ID_KEY = "traceid";
public static final String BAGGAGE_KEY_PREFIX = "baggage-";
Propagator TEXT_MAP = new TextMapPropagator();

class TextMapPropagator implements Propagator {
static final String SPAN_ID_KEY = "spanid";
static final String TRACE_ID_KEY = "traceid";
static final String BAGGAGE_KEY_PREFIX = "baggage-";

@Override
public <C> void inject(MockSpan.MockContext ctx, Format<C> format, C carrier) {
Expand Down Expand Up @@ -159,7 +161,7 @@ public <C> MockSpan.MockContext extract(Format<C> format, C carrier) {

return null;
}
};
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@
*/
package io.opentracing.mock;

import static io.opentracing.mock.MockTracer.Propagator.TextMapPropagator.BAGGAGE_KEY_PREFIX;
import static io.opentracing.mock.MockTracer.Propagator.TextMapPropagator.SPAN_ID_KEY;
import static io.opentracing.mock.MockTracer.Propagator.TextMapPropagator.TRACE_ID_KEY;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
Expand Down Expand Up @@ -201,7 +204,7 @@ public void testTextMapPropagatorHttpHeaders() {
Assert.assertEquals(finishedSpans.get(0).context().traceId(), finishedSpans.get(1).context().traceId());
Assert.assertEquals(finishedSpans.get(0).context().spanId(), finishedSpans.get(1).parentId());
}

@Test
public void testActiveSpan() {
MockTracer mockTracer = new MockTracer();
Expand Down Expand Up @@ -319,4 +322,54 @@ public void testChildOfWithNullParentDoesNotThrowException() {
Span span = tracer.buildSpan("foo").asChildOf(parent).start();
span.finish();
}

@Test
public void testSelfReferenceWithParent() {
MockTracer mockTracer = new MockTracer(MockTracer.Propagator.TEXT_MAP);

final HashMap<String, String> selfIds = new HashMap<>();
selfIds.put(TRACE_ID_KEY, "40");
selfIds.put(SPAN_ID_KEY, "42");
selfIds.put(BAGGAGE_KEY_PREFIX + "foo", "bar");
final HashMap<String, String> parentSpanId = new HashMap<>();
parentSpanId.put(TRACE_ID_KEY, "40");
parentSpanId.put(SPAN_ID_KEY, "41");

mockTracer.buildSpan("foo")
.addReference(References.SELF, mockTracer.extract(Format.Builtin.TEXT_MAP, new TextMapExtractAdapter(selfIds)))
.addReference(References.CHILD_OF, mockTracer.extract(Format.Builtin.TEXT_MAP, new TextMapExtractAdapter(parentSpanId)))
.startManual()
.finish();

assertEquals(1, mockTracer.finishedSpans().size());
assertEquals(40, mockTracer.finishedSpans().get(0).context().traceId());
assertEquals(42, mockTracer.finishedSpans().get(0).context().spanId());
final Map.Entry<String, String> firstBaggageItem = mockTracer.finishedSpans().get(0).context().baggageItems().iterator().next();
assertEquals("foo", firstBaggageItem.getKey());
assertEquals("bar", firstBaggageItem.getValue());
assertEquals(41, mockTracer.finishedSpans().get(0).parentId());
}

@Test
public void testSelfReferenceWithoutParent() {
MockTracer mockTracer = new MockTracer(MockTracer.Propagator.TEXT_MAP);

final HashMap<String, String> selfIds = new HashMap<>();
selfIds.put(TRACE_ID_KEY, "40");
selfIds.put(SPAN_ID_KEY, "42");
selfIds.put(BAGGAGE_KEY_PREFIX + "foo", "bar");

mockTracer.buildSpan("foo")
.addReference(References.SELF, mockTracer.extract(Format.Builtin.TEXT_MAP, new TextMapExtractAdapter(selfIds)))
.startManual()
.finish();

assertEquals(1, mockTracer.finishedSpans().size());
assertEquals(40, mockTracer.finishedSpans().get(0).context().traceId());
assertEquals(42, mockTracer.finishedSpans().get(0).context().spanId());
final Map.Entry<String, String> firstBaggageItem = mockTracer.finishedSpans().get(0).context().baggageItems().iterator().next();
assertEquals("foo", firstBaggageItem.getKey());
assertEquals("bar", firstBaggageItem.getValue());
assertEquals(0, mockTracer.finishedSpans().get(0).parentId());
}
}