-
Notifications
You must be signed in to change notification settings - Fork 0
RFC only! (ActiveSpanManager etc) #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| package io.opentracing; | ||
|
|
||
| public interface ActiveSpanManager { | ||
| // Basically a marker interface | ||
| public interface Snapshot { | ||
| Span span(); | ||
| } | ||
|
|
||
| // Get the currently active Span (perhaps for this thread, etc) | ||
| Span active(); | ||
|
|
||
| // Create a Snapshot encapsulating both the given Span and any state needed to activate/deactivate (see below) | ||
| Snapshot snapshot(Span span); | ||
|
|
||
| // Make the Snapshot and the Span it contains "active" per active(). | ||
| // | ||
| // *Must* be paired with a subsequent call to deactivate(). | ||
| Span activate(Snapshot snapshot); | ||
|
|
||
| // See activate() above. | ||
| void deactivate(Snapshot snapshot); | ||
|
|
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,80 @@ | ||
| package io.opentracing; | ||
|
|
||
| import org.slf4j.MDC; | ||
| import sun.awt.image.ImageWatched; | ||
|
|
||
| import java.util.Map; | ||
|
|
||
| /** | ||
| * XXX: comment | ||
| */ | ||
| public class MDCActiveSpanManager implements io.opentracing.ActiveSpanManager { | ||
|
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. proving to myself that this can work well with MDC and the context map. |
||
| private final ThreadLocal<MDCSnapshot> tlsSnapshot = new ThreadLocal<MDCSnapshot>(); | ||
|
|
||
| class MDCSnapshot implements ActiveSpanManager.Snapshot { | ||
| private final Map<String, String> mdcContext; | ||
| private final Span span; | ||
| private MDCSnapshot toRestore = null; | ||
|
|
||
| MDCSnapshot(Span span) { | ||
| this.mdcContext = MDC.getCopyOfContextMap(); | ||
| this.span = span; | ||
| } | ||
|
|
||
| public Span span() { | ||
| return span; | ||
| } | ||
|
|
||
| void setToRestore(MDCSnapshot toRestore) { | ||
| this.toRestore = toRestore; | ||
| } | ||
|
|
||
| MDCSnapshot toRestore() { | ||
| return toRestore; | ||
| } | ||
| } | ||
|
|
||
| @Override | ||
| public Span active() { | ||
| MDCSnapshot snapshot = tlsSnapshot.get(); | ||
| if (snapshot == null) { | ||
| return null; | ||
| } | ||
| return snapshot.span(); | ||
| } | ||
|
|
||
| @Override | ||
| public MDCSnapshot snapshot(Span span) { | ||
| return new MDCSnapshot(span); | ||
| } | ||
|
|
||
| @Override | ||
| public Span activate(Snapshot snapshot) { | ||
| if (!(snapshot instanceof MDCSnapshot)) { | ||
| throw new IllegalArgumentException("activate() expected MDCSnapshot"); | ||
| } | ||
| ((MDCSnapshot) snapshot).setToRestore(tlsSnapshot.get()); | ||
| tlsSnapshot.set((MDCSnapshot)snapshot); | ||
| return snapshot.span(); | ||
| } | ||
|
|
||
| @Override | ||
| public void deactivate(Snapshot snapshot) { | ||
| if (!(snapshot instanceof MDCSnapshot)) { | ||
| throw new IllegalArgumentException("deactivate() expected MDCSnapshot"); | ||
| } | ||
|
|
||
| if (tlsSnapshot.get() != snapshot) { | ||
| // do nothing | ||
| return; | ||
| } | ||
| MDCSnapshot nextActiveSnapshot = ((MDCSnapshot)snapshot).toRestore(); | ||
| while (nextActiveSnapshot != null) { | ||
| if (!nextActiveSnapshot.span().isFinished()) { | ||
| break; | ||
| } | ||
| nextActiveSnapshot = nextActiveSnapshot.toRestore(); | ||
| } | ||
| tlsSnapshot.set(nextActiveSnapshot); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -41,6 +41,9 @@ public interface Span extends Closeable { | |
| */ | ||
| void finish(); | ||
|
|
||
| // XXX: comment | ||
| boolean isFinished(); | ||
|
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this is necessary if we want to avoid Tracer/Span wrappers (which I kinda want to avoid) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 💯 |
||
|
|
||
| /** | ||
| * Sets an explicit end timestamp and records the span. | ||
| * | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| package io.opentracing.concurrent; | ||
|
|
||
| import io.opentracing.ActiveSpanManager; | ||
| import io.opentracing.Span; | ||
| import io.opentracing.Tracer; | ||
| import io.opentracing.impl.GlobalTracer; | ||
|
|
||
| import java.util.concurrent.Callable; | ||
|
|
||
| public class TracedCallable<T> implements Callable<T> { | ||
| private ActiveSpanManager.Snapshot snapshot; | ||
| private ActiveSpanManager manager; | ||
| private Callable<T> callable; | ||
|
|
||
| public TracedCallable(Callable<T> callable) { | ||
| this(callable, GlobalTracer.get().activeSpanManager()); | ||
| } | ||
|
|
||
| public TracedCallable(Callable<T> callable, ActiveSpanManager manager) { | ||
| this(callable, manager.active(), manager); | ||
| } | ||
|
|
||
| public TracedCallable(Callable<T> callable, Span span, ActiveSpanManager manager) { | ||
| if (callable == null) throw new NullPointerException("Callable is <null>."); | ||
| this.callable= callable; | ||
| this.manager = manager; | ||
| this.snapshot = manager.snapshot(span); | ||
| } | ||
|
|
||
| public T call() throws Exception { | ||
| final Span span = manager.activate(snapshot); | ||
| try { | ||
| return callable.call(); | ||
| } finally { | ||
| manager.deactivate(snapshot); | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,102 @@ | ||
| package io.opentracing.concurrent; | ||
|
|
||
| import io.opentracing.ActiveSpanManager; | ||
| import io.opentracing.Span; | ||
| import io.opentracing.Tracer; | ||
| import io.opentracing.impl.GlobalTracer; | ||
|
|
||
| import java.util.ArrayList; | ||
| import java.util.Collection; | ||
| import java.util.List; | ||
| import java.util.concurrent.*; | ||
|
|
||
| public class TracedExecutorService implements ExecutorService { | ||
| private ExecutorService executor; | ||
| private ActiveSpanManager manager; | ||
|
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. note how this thing does not need a Tracer ref anymore, and it's also pretty easy to write given an ASM. |
||
|
|
||
| public TracedExecutorService(ExecutorService executor){ | ||
| this(executor, GlobalTracer.get().activeSpanManager()); | ||
| } | ||
|
|
||
| public TracedExecutorService(ExecutorService executor, ActiveSpanManager manager) { | ||
| if (executor == null) throw new NullPointerException("Executor is <null>."); | ||
| if (manager == null) throw new NullPointerException("ActiveSpanManager is <null>."); | ||
| this.executor = executor; | ||
| this.manager = manager; | ||
| } | ||
|
|
||
| @Override | ||
| public void execute(Runnable command) { | ||
| executor.execute(new TracedRunnable(command, manager)); | ||
| } | ||
|
|
||
| @Override | ||
| public Future<?> submit(Runnable task) { | ||
| return executor.submit(new TracedRunnable(task, manager)); | ||
| } | ||
|
|
||
| @Override | ||
| public <T> Future<T> submit(Runnable task, T result) { | ||
| return executor.submit(new TracedRunnable(task, manager), result); | ||
| } | ||
|
|
||
| @Override | ||
| public <T> Future<T> submit(Callable<T> task) { | ||
| return executor.submit(new TracedCallable(task, manager)); | ||
| } | ||
|
|
||
| @Override | ||
| public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks) throws InterruptedException { | ||
| return executor.invokeAll(tasksWithTracing(tasks)); | ||
| } | ||
|
|
||
| @Override | ||
| public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit) | ||
| throws InterruptedException { | ||
| return executor.invokeAll(tasksWithTracing(tasks), timeout, unit); | ||
| } | ||
|
|
||
| @Override | ||
| public <T> T invokeAny(Collection<? extends Callable<T>> tasks) throws InterruptedException, ExecutionException { | ||
| return executor.invokeAny(tasksWithTracing(tasks)); | ||
| } | ||
|
|
||
| @Override | ||
| public <T> T invokeAny(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit) | ||
| throws InterruptedException, ExecutionException, TimeoutException { | ||
| return executor.invokeAny(tasksWithTracing(tasks), timeout, unit); | ||
| } | ||
|
|
||
| @Override | ||
| public void shutdown() { | ||
| executor.shutdown(); | ||
| } | ||
|
|
||
| @Override | ||
| public List<Runnable> shutdownNow() { | ||
| return executor.shutdownNow(); | ||
| } | ||
|
|
||
| @Override | ||
| public boolean isShutdown() { | ||
| return executor.isShutdown(); | ||
| } | ||
|
|
||
| @Override | ||
| public boolean isTerminated() { | ||
| return executor.isTerminated(); | ||
| } | ||
|
|
||
| @Override | ||
| public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException { | ||
| return executor.awaitTermination(timeout, unit); | ||
| } | ||
|
|
||
| private <T> Collection<? extends Callable<T>> tasksWithTracing( | ||
| Collection<? extends Callable<T>> tasks) { | ||
| if (tasks == null) throw new NullPointerException("Collection of tasks is <null>."); | ||
| Collection<Callable<T>> result = new ArrayList<Callable<T>>(tasks.size()); | ||
| for (Callable<T> task : tasks) result.add(new TracedCallable(task, manager)); | ||
| return result; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,42 @@ | ||
| package io.opentracing.concurrent; | ||
|
|
||
| import io.opentracing.ActiveSpanManager; | ||
| import io.opentracing.Span; | ||
| import io.opentracing.Tracer; | ||
| import io.opentracing.impl.GlobalTracer; | ||
|
|
||
|
|
||
| public class TracedRunnable implements Runnable { | ||
| private Runnable runnable; | ||
| private ActiveSpanManager manager; | ||
| private ActiveSpanManager.Snapshot snapshot; | ||
|
|
||
| public TracedRunnable(Runnable runnable) { | ||
| this(runnable, GlobalTracer.get().activeSpanManager()); | ||
| } | ||
|
|
||
| public TracedRunnable(Runnable runnable, Span span) { | ||
| this(runnable, span, GlobalTracer.get().activeSpanManager()); | ||
| } | ||
|
|
||
| public TracedRunnable(Runnable runnable, ActiveSpanManager manager) { | ||
| this(runnable, manager.active(), manager); | ||
| } | ||
|
|
||
| public TracedRunnable(Runnable runnable, Span span, ActiveSpanManager manager) { | ||
| if (runnable == null) throw new NullPointerException("Runnable is <null>."); | ||
| this.runnable = runnable; | ||
| this.manager = manager; | ||
| this.snapshot = manager.snapshot(span); | ||
| } | ||
|
|
||
| @Override | ||
| public void run() { | ||
| final Span span = manager.activate(this.snapshot); | ||
| try { | ||
| runnable.run(); | ||
| } finally { | ||
| manager.deactivate(this.snapshot); | ||
| } | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍