Last active
August 3, 2017 23:15
-
-
Save mabn/9246ebb03aa1534b33b98bd728158b11 to your computer and use it in GitHub Desktop.
Making scope work?
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.io.Closeable; | |
interface ActiveSpanSource { | |
// no changes | |
ActiveSpan makeActive(Span span); | |
} | |
interface Tracer extends ActiveSpanSource{ | |
// no changes | |
SpanBuilder buildSpan(String operationName); | |
} | |
interface Span extends AutoCloseable { | |
Span setTag(String key, String value); | |
// Creates "an inactive ActiveSpan" which can be "activated" and turned into regular ActiveSpan. It | |
// has only a single purpose - to carry some contextual information to another thread. Using | |
// "capture" is not mandatory | |
Continuation capture(); | |
/** | |
* By default deactivates the span (if it was active) and finishes the span. The behaviour | |
* is defined by the lifecycle used to create the span and another lifecycle can be provided | |
* at span creation. | |
*/ | |
@Override | |
void close(); | |
// yes! it's back! | |
void finish(); | |
} | |
interface SpanBuilder { | |
// starts span and makes it active in the current thread | |
Span startActive(); | |
// allows to alter span's lifecycle management - e.g. how Span.close() behaves | |
Span startActive(SpanLifecycle lifecycle); | |
// no changes, starts inactive span | |
Span startManual(); | |
SpanBuilder childOf(Span span); | |
} | |
// represents the scope of span activity. provides access to the span that is active in this scope | |
// via span(). closed ActiveSpan is no longer valid - it's an error to call span() on it | |
interface ActiveSpan extends Closeable { | |
// the main change - it has no span method! instead - span get be obtained with span() | |
Span span(); | |
/** | |
* By default deactivates current ActiveSpan (but does not finish the span!). The behaviour is | |
* defined by the lifecycle used to create the span and another lifecycle can be provided at | |
* span creation. | |
*/ | |
@Override | |
void close(); | |
} | |
interface Continuation { | |
ActiveSpan activate(); | |
} | |
interface SpanLifecycle { | |
void onClose(Span span); | |
} | |
public class Test { | |
Tracer tracer = null; | |
ActiveSpanSource activeSpanSource = tracer; | |
void active_span_in_current_thread() { | |
tracer.buildSpan("a").startActive(); | |
try (Span span = tracer.buildSpan("a").startActive()) { | |
doSomething(); | |
} // at this point I'm done, no more interactions with the span. It should be deactivated | |
// and finished | |
} | |
void activate_span_in_other_thread() { | |
try (Span span = tracer.buildSpan("a").startActive()){ | |
inOtherThread(() -> { | |
try (ActiveSpan active = activeSpanSource.makeActive(span)){ | |
active.span().setTag("k","v"); | |
} // here the ActiveSpan deactivates, but the span is not finished | |
}); | |
} // at this point I'm done, no more interactions with the span. it should be deactivated | |
// and finished. This is the default behavior of startActive() | |
} | |
void automatic_finish_is_possible_but_optional() { | |
// this span has non-default lifecycle management: | |
try (Span span = tracer.buildSpan("a").startActive(new AutoFinisher())){ | |
inOtherThread(() -> { // Assume that the child thread lives longer than the parent | |
try (ActiveSpan active = activeSpanSource.makeActive(span)){ | |
active.span().setTag("k","v"); | |
} // this finishes the span because AutoFinisher counts activations, | |
// deactivations and finishes the span after the Span and the last ActiveSpan are closed | |
}); | |
} // this does not finish the span as it is still active in the child thread - that's the behaviour | |
// of AutoFinisher | |
} | |
void carry_thread_locals_to_child_thread() { | |
try (Span span = tracer.buildSpan("a").startActive()){ | |
Continuation toActivate = span.capture(); | |
inOtherThread(() -> { | |
try (ActiveSpan active = toActivate.activate()){ | |
} // here the ActiveSpan deactivates, but the span is not finished | |
}); | |
} // at this point I'm done, no more interactions with the span. it should be | |
// deactivated and finished (the child thread finishes before the parent) | |
} | |
void create_child_span_in_the_same_thread() { | |
try (Span parent = tracer.buildSpan("parent").startActive()){ | |
try(Span child = tracer.buildSpan("child").childOf(parent).startActive()) { | |
doSomething(); | |
}; // deactivates and finishes child | |
} // deactivates and finishes parent | |
} | |
void create_child_span_in_another_thread() { | |
try (Span parent = tracer.buildSpan("parent").startActive()){ | |
inOtherThread(() -> { | |
try(Span child = tracer.buildSpan("child").childOf(parent).startActive()) { | |
doSomething(); | |
}; // deactivates and finishes child | |
}); | |
} // deactivates and finishes parent | |
} | |
// stuff to make this thing compile | |
void doSomething(){} | |
void inOtherThread(RunnableWithException c){} | |
interface RunnableWithException { | |
void run() throws Exception; | |
} | |
class AutoFinisher implements SpanLifecycle { | |
@Override | |
public void onClose(Span span) { | |
throw new UnsupportedOperationException(); | |
} | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment