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

WIP: in-process propagation resolves opentracing/specification#23 #117

Closed
wants to merge 1 commit into from
Closed
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
7 changes: 6 additions & 1 deletion opentracing-api/src/main/java/io/opentracing/Span.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* Copyright 2016 The OpenTracing Authors
* Copyright 2016-2017 The OpenTracing Authors
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
Expand All @@ -22,6 +22,9 @@
* <p>Spans are created by the {@link Tracer#buildSpan} interface.
*/
public interface Span extends Closeable {

SpanManager.Visibility visibility();

/**
* Retrieve the associated SpanContext.
*
Expand All @@ -42,6 +45,8 @@ public interface Span extends Closeable {
void finish();

/**
* Deactivates spans from spanManager.
*
* Sets an explicit end timestamp and records the span.
*
* <p>With the exception of calls to Span.context(), this should be the last call made to the span instance, and to
Expand Down
70 changes: 70 additions & 0 deletions opentracing-api/src/main/java/io/opentracing/SpanManager.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/**
* Copyright 2016-2017 The OpenTracing Authors
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
package io.opentracing;

/**
* @author Pavol Loffay
*/
public interface SpanManager {

/**
* @param span span to bundle into visibility, there is always only one visibility per span
* @return visibility
*/
Visibility bundle(Span span);

/**
* @return not finished active span or null
*/
VisibilityContext active();

interface Visibility {
/**
* @return visibility context which is used to activate/deactivate span
*/
VisibilityContext capture();

/**
* @return associated span or null if visibility is marked as finished.
*/
Span span();
/**
* @return always spanContext
*/
SpanContext context();

/**
* Mark associated span as finished.
*
* Should be called by {@link Span#finish()} or directly if one does not want to expose span.
* This method should be idempotent.
*
* review note: reverse operation should not be allowed.
*/
void hideSpan();
}

interface VisibilityContext {
/**
* on/activate - {@link SpanManager#active()} will return this object.
*/
VisibilityContext on();
/**
* off/deactivate - {@link SpanManager#active()} will not return this object.
*/
VisibilityContext off();

Visibility visibility();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/**
* Copyright 2016-2017 The OpenTracing Authors
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
package io.opentracing;

import java.util.concurrent.atomic.AtomicBoolean;

/**
* @author Pavol Loffay
*/
public class ThreadLocalSpanManager implements SpanManager {

private final ThreadLocal<SimpleLinkedVisibilityContext> activeContext = new ThreadLocal<SimpleLinkedVisibilityContext>();

@Override
public Visibility bundle(Span span) {
return span.visibility() == null ? new SimpleVisibility(span) : span.visibility();
}

@Override
public SimpleLinkedVisibilityContext active() {
return activeContext.get();
}

class SimpleVisibility implements Visibility {
private final Span span;
private AtomicBoolean hideSpan = new AtomicBoolean(false);

public SimpleVisibility(Span span) {
this.span = span;
}

@Override
public Span span() {
return hideSpan.get() ? null : span;
}

@Override
public SpanContext context() {
return span.context();
}

@Override
public SimpleLinkedVisibilityContext capture() {
return new SimpleLinkedVisibilityContext(this);
}

@Override
public void hideSpan() {
hideSpan.set(true);
}
}

class SimpleLinkedVisibilityContext implements SpanManager.VisibilityContext {

private final SimpleVisibility visibility;
private SimpleLinkedVisibilityContext previous;

public SimpleLinkedVisibilityContext(SimpleVisibility visibility) {
this.visibility = visibility;
}

@Override
public SimpleLinkedVisibilityContext on() {
previous = activeContext.get();
activeContext.set(this);
return this;
}

@Override
public SimpleLinkedVisibilityContext off() {
if (this == activeContext.get()) {
activeContext.set(previous);
}
// else should not happen

return this;
}

@Override
public Visibility visibility() {
return visibility;
}
}
}
6 changes: 5 additions & 1 deletion opentracing-api/src/main/java/io/opentracing/Tracer.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@
*/
public interface Tracer {

// span could be directly returned
SpanManager spanManager();

/**
* Return a new SpanBuilder for a Span with the given `operationName`.
*
Expand Down Expand Up @@ -113,6 +116,8 @@ interface SpanBuilder extends SpanContext {
*/
SpanBuilder addReference(String referenceType, SpanContext referencedContext);

SpanBuilder asRoot();

/** Same as {@link Span#setTag(String, String)}, but for the span being built. */
SpanBuilder withTag(String key, String value);

Expand All @@ -127,6 +132,5 @@ interface SpanBuilder extends SpanContext {

/** Returns the started Span. */
Span start();

}
}
20 changes: 20 additions & 0 deletions opentracing-mock/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,26 @@
<groupId>${project.groupId}</groupId>
<artifactId>opentracing-api</artifactId>
</dependency>

<!-- for MDC demo will go away -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.23</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.23</version>
<scope>test</scope>
</dependency>
</dependencies>

</project>
18 changes: 17 additions & 1 deletion opentracing-mock/src/main/java/io/opentracing/mock/MockSpan.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

import io.opentracing.Span;
import io.opentracing.SpanContext;
import io.opentracing.SpanManager;

/**
* MockSpans are created via MockTracer.buildSpan(...), but they are also returned via calls to
Expand All @@ -29,6 +30,8 @@ public final class MockSpan implements Span {
// A simple-as-possible (consecutive for repeatability) id generator.
private static AtomicLong nextId = new AtomicLong(0);

private final SpanManager.Visibility visibility;

private final MockTracer mockTracer;
private MockContext context;
private final long parentId; // 0 if there's no parent.
Expand Down Expand Up @@ -93,6 +96,11 @@ public List<RuntimeException> generatedErrors() {
return new ArrayList<>(errors);
}

@Override
public SpanManager.Visibility visibility() {
return visibility;
}

@Override
public synchronized MockContext context() {
return this.context;
Expand All @@ -107,6 +115,7 @@ public void finish() {
public synchronized void finish(long finishMicros) {
finishedCheck("Finishing already finished span");
this.finishMicros = finishMicros;
visibility.hideSpan();
this.mockTracer.appendFinishedSpan(this);
this.finished = true;
}
Expand Down Expand Up @@ -248,10 +257,17 @@ 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
parent, boolean activate) {
this.mockTracer = tracer;
this.operationName = operationName;
this.startMicros = startMicros;

this.visibility = tracer.spanManager().bundle(this);
if (activate) {
this.visibility.capture().on();
}

if (initialTags == null) {
this.tags = new HashMap<>();
} else {
Expand Down
34 changes: 30 additions & 4 deletions opentracing-mock/src/main/java/io/opentracing/mock/MockTracer.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
import io.opentracing.References;
import io.opentracing.Span;
import io.opentracing.SpanContext;
import io.opentracing.SpanManager;
import io.opentracing.ThreadLocalSpanManager;
import io.opentracing.Tracer;
import io.opentracing.propagation.Format;
import io.opentracing.propagation.TextMap;
Expand All @@ -38,16 +40,22 @@
public class MockTracer implements Tracer {
private List<MockSpan> finishedSpans = new ArrayList<>();
private final Propagator propagator;
private final SpanManager spanManager;

public MockTracer() {
this(Propagator.PRINTER);
this(Propagator.PRINTER, new ThreadLocalSpanManager());
}

/**
* Create a new MockTracer that passes through any calls to inject() and/or extract().
*/
public MockTracer(Propagator propagator) {
this(propagator, new ThreadLocalSpanManager());
}

public MockTracer(Propagator propagator, SpanManager spanManager) {
this.propagator = propagator;
this.spanManager = spanManager;
}

/**
Expand Down Expand Up @@ -144,9 +152,14 @@ public <C> MockSpan.MockContext extract(Format<C> format, C carrier) {
};
}

@Override
public SpanManager spanManager() {
return spanManager;
}

@Override
public SpanBuilder buildSpan(String operationName) {
return new SpanBuilder(operationName);
return new SpanBuilder(operationName, spanManager);
}

@Override
Expand All @@ -170,8 +183,14 @@ public final class SpanBuilder implements Tracer.SpanBuilder {
private MockSpan.MockContext firstParent;
private Map<String, Object> initialTags = new HashMap<>();

SpanBuilder(String operationName) {
SpanBuilder(String operationName, SpanManager spanManager) {
this.operationName = operationName;

SpanManager.VisibilityContext inferredParent = spanManager.active();
if (inferredParent != null) {
addReference(inferredParent.visibility().span() == null ? References.FOLLOWS_FROM : References.CHILD_OF,
inferredParent.visibility().span().context());
}
}
@Override
public SpanBuilder asChildOf(SpanContext parent) {
Expand All @@ -192,6 +211,12 @@ public SpanBuilder addReference(String referenceType, SpanContext referencedCont
return this;
}

@Override
public Tracer.SpanBuilder asRoot() {
firstParent = null;
return this;
}

@Override
public SpanBuilder withTag(String key, String value) {
this.initialTags.put(key, value);
Expand Down Expand Up @@ -221,7 +246,8 @@ public MockSpan start() {
if (this.startMicros == 0) {
this.startMicros = MockSpan.nowMicros();
}
return new MockSpan(MockTracer.this, this.operationName, this.startMicros, initialTags, this.firstParent);
return new MockSpan(MockTracer.this, this.operationName, this.startMicros, initialTags,
this.firstParent, false);
}

@Override
Expand Down
Loading