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

Commit

Permalink
Add SELF reference
Browse files Browse the repository at this point in the history
  • Loading branch information
Felix Barnsteiner committed Nov 3, 2017
1 parent cdc9601 commit 5da56c8
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 40 deletions.
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";
}
38 changes: 15 additions & 23 deletions opentracing-mock/src/main/java/io/opentracing/mock/MockSpan.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicLong;

import io.opentracing.Span;
import io.opentracing.SpanContext;
Expand All @@ -30,12 +29,8 @@
* @see MockTracer#finishedSpans()
*/
public final class MockSpan implements Span {
// A simple-as-possible (consecutive for repeatability) id generator.
private static AtomicLong nextId = new AtomicLong(0);

private final MockTracer mockTracer;
private MockContext context;
private final long parentId; // 0 if there's no parent.
private final long startMicros;
private boolean finished;
private long finishMicros;
Expand Down Expand Up @@ -64,7 +59,7 @@ public MockSpan setOperationName(String operationName) {
* @see MockContext#spanId()
*/
public long parentId() {
return parentId;
return context().parentId();
}
public long startMicros() {
return startMicros;
Expand Down Expand Up @@ -180,6 +175,12 @@ public static final class MockContext implements SpanContext {
private final long traceId;
private final Map<String, String> baggage;
private final long spanId;
/**
* 0 if there's no parent.
*
* TODO: Support multiple parents in this API.
*/
private final long parentId;

/**
* A package-protected constructor to create a new MockContext. This should only be called by MockSpan and/or
Expand All @@ -189,7 +190,8 @@ public static final class MockContext implements SpanContext {
*
* @see MockContext#withBaggageItem(String, String)
*/
public MockContext(long traceId, long spanId, Map<String, String> baggage) {
MockContext(long parentId, long traceId, long spanId, Map<String, String> baggage) {
this.parentId = parentId;
this.baggage = baggage;
this.traceId = traceId;
this.spanId = spanId;
Expand All @@ -198,14 +200,16 @@ public MockContext(long traceId, long spanId, Map<String, String> baggage) {
public String getBaggageItem(String key) { return this.baggage.get(key); }
public long traceId() { return traceId; }
public long spanId() { return spanId; }
public long parentId() { return parentId; }
Map<String, String> baggage() { return baggage; }

/**
* Create and return a new (immutable) MockContext with the added baggage item.
*/
public MockContext withBaggageItem(String key, String val) {
Map<String, String> newBaggage = new HashMap<>(this.baggage);
newBaggage.put(key, val);
return new MockContext(this.traceId, this.spanId, newBaggage);
return new MockContext(this.parentId, this.traceId, this.spanId, newBaggage);
}

@Override
Expand All @@ -232,7 +236,7 @@ public long timestampMicros() {
}
}

MockSpan(MockTracer tracer, String operationName, long startMicros, Map<String, Object> initialTags, MockContext parent) {
MockSpan(MockTracer tracer, String operationName, long startMicros, Map<String, Object> initialTags, MockContext context) {
this.mockTracer = tracer;
this.operationName = operationName;
this.startMicros = startMicros;
Expand All @@ -241,19 +245,7 @@ public long timestampMicros() {
} else {
this.tags = new HashMap<>(initialTags);
}
if (parent == null) {
// We're a root Span.
this.context = new MockContext(nextId(), nextId(), new HashMap<String, String>());
this.parentId = 0;
} else {
// We're a child Span.
this.context = new MockContext(parent.traceId, nextId(), parent.baggage);
this.parentId = parent.spanId;
}
}

static long nextId() {
return nextId.addAndGet(1);
this.context = context;
}

static long nowMicros() {
Expand All @@ -273,7 +265,7 @@ public String toString() {
return "{" +
"traceId:" + context.traceId() +
", spanId:" + context.spanId() +
", parentId:" + parentId +
", parentId:" + context.parentId() +
", operationName:\"" + operationName + "\"}";
}
}
50 changes: 40 additions & 10 deletions opentracing-mock/src/main/java/io/opentracing/mock/MockTracer.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,22 +13,23 @@
*/
package io.opentracing.mock;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicLong;

import io.opentracing.References;
import io.opentracing.Scope;
import io.opentracing.ScopeManager;
import io.opentracing.Span;
import io.opentracing.noop.NoopScopeManager;
import io.opentracing.References;
import io.opentracing.SpanContext;
import io.opentracing.Tracer;
import io.opentracing.noop.NoopScopeManager;
import io.opentracing.propagation.Format;
import io.opentracing.propagation.TextMap;
import io.opentracing.util.ThreadLocalScopeManager;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
* MockTracer makes it easy to test the semantics of OpenTracing instrumentation.
*
Expand All @@ -38,6 +39,9 @@
* The MockTracerTest has simple usage examples.
*/
public class MockTracer implements Tracer {
// A simple-as-possible (consecutive for repeatability) id generator.
private static AtomicLong nextId = new AtomicLong(0);

private List<MockSpan> finishedSpans = new ArrayList<>();
private final Propagator propagator;
private ScopeManager scopeManager;
Expand Down Expand Up @@ -115,6 +119,7 @@ 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 PARENT_ID_KEY = "parentid";
public static final String BAGGAGE_KEY_PREFIX = "baggage-";

@Override
Expand All @@ -126,6 +131,9 @@ public <C> void inject(MockSpan.MockContext ctx, Format<C> format, C carrier) {
}
textMap.put(SPAN_ID_KEY, String.valueOf(ctx.spanId()));
textMap.put(TRACE_ID_KEY, String.valueOf(ctx.traceId()));
if (ctx.traceId() != 0) {
textMap.put(PARENT_ID_KEY, String.valueOf(ctx.traceId()));
}
} else {
throw new IllegalArgumentException("Unknown carrier");
}
Expand All @@ -135,6 +143,7 @@ public <C> void inject(MockSpan.MockContext ctx, Format<C> format, C carrier) {
public <C> MockSpan.MockContext extract(Format<C> format, C carrier) {
Long traceId = null;
Long spanId = null;
long parentId = 0;
Map<String, String> baggage = new HashMap<>();

if (carrier instanceof TextMap) {
Expand All @@ -144,6 +153,8 @@ public <C> MockSpan.MockContext extract(Format<C> format, C carrier) {
traceId = Long.valueOf(entry.getValue());
} else if (SPAN_ID_KEY.equals(entry.getKey())) {
spanId = Long.valueOf(entry.getValue());
} else if (PARENT_ID_KEY.equals(entry.getKey())) {
parentId = Long.valueOf(entry.getValue());
} else if (entry.getKey().startsWith(BAGGAGE_KEY_PREFIX)){
String key = entry.getKey().substring((BAGGAGE_KEY_PREFIX.length()));
baggage.put(key, entry.getValue());
Expand All @@ -154,7 +165,7 @@ public <C> MockSpan.MockContext extract(Format<C> format, C carrier) {
}

if (traceId != null && spanId != null) {
return new MockSpan.MockContext(traceId, spanId, baggage);
return new MockSpan.MockContext(parentId, traceId, spanId, baggage);
}

return null;
Expand Down Expand Up @@ -193,6 +204,7 @@ public final class SpanBuilder implements Tracer.SpanBuilder {
private MockSpan.MockContext firstParent;
private boolean ignoringActiveSpan;
private Map<String, Object> initialTags = new HashMap<>();
private MockSpan.MockContext selfContext;

SpanBuilder(String operationName) {
this.operationName = operationName;
Expand All @@ -218,7 +230,10 @@ public SpanBuilder ignoreActiveSpan() {
public SpanBuilder addReference(String referenceType, SpanContext referencedContext) {
if (firstParent == null && (
referenceType.equals(References.CHILD_OF) || referenceType.equals(References.FOLLOWS_FROM))) {
this.firstParent = (MockSpan.MockContext)referencedContext;
this.firstParent = (MockSpan.MockContext) referencedContext;
}
if (referenceType.equals(References.SELF)) {
this.selfContext = (MockSpan.MockContext) referencedContext;
}
return this;
}
Expand Down Expand Up @@ -273,7 +288,22 @@ public MockSpan startManual() {
firstParent = (MockSpan.MockContext) activeScope.span().context();
}
}
return new MockSpan(MockTracer.this, operationName, startMicros, initialTags, firstParent);
final MockSpan.MockContext context;
if (selfContext != null) {
// the context has been explicitly provided
context = selfContext;
} else if (firstParent == null) {
// We're a root Span.
context = new MockSpan.MockContext(0, nextId(), nextId(), new HashMap<String, String>());
} else {
// We're a child Span.
context = new MockSpan.MockContext(firstParent.spanId(), firstParent.traceId(), nextId(), firstParent.baggage());
}
return new MockSpan(MockTracer.this, operationName, startMicros, initialTags, context);
}
}

static long nextId() {
return nextId.addAndGet(1);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,23 @@
*/
package io.opentracing.mock;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import org.junit.Assert;
import org.junit.Test;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import io.opentracing.References;
import io.opentracing.Span;
import io.opentracing.SpanContext;
import io.opentracing.Tracer;
import io.opentracing.propagation.Format;
import io.opentracing.propagation.TextMapExtractAdapter;
import io.opentracing.propagation.TextMapInjectAdapter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.junit.Assert;
import org.junit.Test;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;

public class MockTracerTest {
@Test
Expand Down Expand Up @@ -209,4 +212,23 @@ public void testReset() {
mockTracer.reset();
assertEquals(0, mockTracer.finishedSpans().size());
}

@Test
public void testSelfReference() throws Exception {
MockTracer mockTracer = new MockTracer(MockTracer.Propagator.TEXT_MAP);

final HashMap<String, String> map = new HashMap<>();
map.put("traceid", "42");
map.put("spanid", "42");

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

assertEquals(1, mockTracer.finishedSpans().size());
assertEquals(42, mockTracer.finishedSpans().get(0).context().traceId());
assertEquals(42, mockTracer.finishedSpans().get(0).context().spanId());
assertEquals(0, mockTracer.finishedSpans().get(0).context().parentId());
}
}

0 comments on commit 5da56c8

Please sign in to comment.