-
Notifications
You must be signed in to change notification settings - Fork 20
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
Adds support for AutoFinishScope #12
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 |
---|---|---|
|
@@ -34,8 +34,8 @@ | |
</developers> | ||
|
||
<properties> | ||
<maven.compiler.source>1.6</maven.compiler.source> | ||
<maven.compiler.target>1.6</maven.compiler.target> | ||
<maven.compiler.source>1.7</maven.compiler.source> | ||
<maven.compiler.target>1.7</maven.compiler.target> | ||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> | ||
|
||
<version.junit>4.12</version.junit> | ||
|
@@ -48,6 +48,7 @@ | |
<version.maven-javadoc-plugin>2.10.4</version.maven-javadoc-plugin> | ||
<version.io.takari-maven>0.3.4</version.io.takari-maven> | ||
<version.io.zikin.centralsync-maven-plugin>0.1.0</version.io.zikin.centralsync-maven-plugin> | ||
<version.awaitility>3.0.0</version.awaitility> | ||
</properties> | ||
|
||
<dependencyManagement> | ||
|
@@ -91,6 +92,12 @@ | |
<version>${version.junit}</version> | ||
<scope>test</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.awaitility</groupId> | ||
<artifactId>awaitility</artifactId> | ||
<version>${version.awaitility}</version> | ||
<scope>test</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>io.opentracing</groupId> | ||
<artifactId>opentracing-mock</artifactId> | ||
|
@@ -99,7 +106,6 @@ | |
<dependency> | ||
<groupId>io.opentracing</groupId> | ||
<artifactId>opentracing-util</artifactId> | ||
<scope>test</scope> | ||
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. Please make this provided and optional=true to avoid unnecessary transitive dependencies 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. It would result in 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.
Currently, yes. Libraries should not 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. That can be quite expensive to have it in runnable/callable. 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. if (tracer.scopeManager() instanceof AutoFinishScopeManager && tracer.scopeManager().active() != null)
cont = ((AutoFinishScope) tracer.scopeManager().active()).capture();
else
cont = null; Could be replaced by: if (hasAutoFinishScopeManager(tracer) && tracer.scopeManager().active() != null) {
cont = ((io.opentracing.util.AutoFinishScope) tracer.scopeManager().active()).capture();
}
...
private static boolean hasAutoFinishScopeManager(Tracer tracer) {
try {
return tracer.scopeManager() instanceof io.opentracing.util.AutoFinishScopeManager;
} catch (NoClassDefFoundError utilityJarNotLoaded) {
LOGGER.finest("The opentracing-util library is not available, therefore the ScopeManager cannot be the AutoFinishScopeManager.");
return false;
}
} Just make sure not to import I agree this borders on being too far-fetched, just pointing out the possibilities. 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. A better way would be to wrap all auto-finish related coded in its own (package protected) class and only access that if the hasAutoFinish.. test returned true. 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.
Ok, then create a boolean constant and populate it in a static code block when the class is loaded.. For inspiration, you could look at PriorityComparator (optional use of javax.annotation.Priority) or TracerResolver (optional use of io.opentracing.util.GlobalTracer) 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. If we have consensus on the last proposal, static boolean. Then I don't mind adding that. |
||
</dependency> | ||
</dependencies> | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,27 +3,41 @@ | |
import io.opentracing.Scope; | ||
import io.opentracing.Span; | ||
import io.opentracing.Tracer; | ||
import io.opentracing.util.AutoFinishScope; | ||
import io.opentracing.util.AutoFinishScopeManager; | ||
|
||
import java.util.concurrent.Callable; | ||
|
||
/** | ||
* @author Pavol Loffay | ||
* @author Jose Montoya | ||
*/ | ||
public class TracedCallable<V> implements Callable<V> { | ||
|
||
private final Callable<V> delegate; | ||
private final Span span; | ||
private final Tracer tracer; | ||
private final AutoFinishScope.Continuation cont; | ||
|
||
public TracedCallable(Callable<V> delegate, Tracer tracer) { | ||
this.delegate = delegate; | ||
this.tracer = tracer; | ||
this.span = tracer.activeSpan(); | ||
|
||
if (tracer.scopeManager() instanceof AutoFinishScopeManager && tracer.scopeManager().active() != null) | ||
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. Could you add braces in the |
||
cont = ((AutoFinishScope) tracer.scopeManager().active()).capture(); | ||
else | ||
cont = null; | ||
} | ||
|
||
@Override | ||
public V call() throws Exception { | ||
Scope scope = span == null ? null : tracer.scopeManager().activate(span, false); | ||
Scope scope = null; | ||
if (cont != null) | ||
scope = cont.activate(); | ||
else if (span != null) | ||
scope = tracer.scopeManager().activate(span, false); | ||
|
||
try { | ||
return delegate.call(); | ||
} finally { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,26 +3,40 @@ | |
import io.opentracing.Scope; | ||
import io.opentracing.Tracer; | ||
import io.opentracing.Span; | ||
import io.opentracing.util.AutoFinishScope; | ||
import io.opentracing.util.AutoFinishScopeManager; | ||
|
||
/** | ||
* @author Pavol Loffay | ||
* @author Jose Montoya | ||
*/ | ||
public class TracedRunnable implements Runnable { | ||
|
||
private final Runnable delegate; | ||
private final Span span; | ||
private final Tracer tracer; | ||
private final AutoFinishScope.Continuation cont; | ||
|
||
public TracedRunnable(Runnable delegate, Tracer tracer) { | ||
this.delegate = delegate; | ||
this.tracer = tracer; | ||
this.span = tracer.activeSpan(); | ||
|
||
if (tracer.scopeManager() instanceof AutoFinishScopeManager && tracer.scopeManager().active() != null) | ||
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. Indentation problem with this if/else construct. |
||
cont = ((AutoFinishScope) tracer.scopeManager().active()).capture(); | ||
else | ||
cont = null; | ||
} | ||
|
||
@Override | ||
public void run() { | ||
Scope scope = span == null ? null : tracer.scopeManager().activate(span, false); | ||
try { | ||
Scope scope = null; | ||
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. Indentation problem with this code block. |
||
if (cont != null) | ||
scope = cont.activate(); | ||
else if (span != null) | ||
scope = tracer.scopeManager().activate(span, false); | ||
|
||
try { | ||
delegate.run(); | ||
} finally { | ||
if (scope != null) { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
package io.opentracing.contrib.concurrent; | ||
|
||
import io.opentracing.Scope; | ||
import io.opentracing.mock.MockTracer; | ||
import io.opentracing.util.AutoFinishScopeManager; | ||
import org.junit.Before; | ||
import org.junit.Test; | ||
|
||
import java.util.concurrent.*; | ||
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. Can you expand the imports. |
||
|
||
import static org.awaitility.Awaitility.await; | ||
import static org.hamcrest.core.IsEqual.equalTo; | ||
import static org.junit.Assert.assertEquals; | ||
import static org.junit.Assert.assertNull; | ||
|
||
/** | ||
* @author Jose Montoya | ||
*/ | ||
public class TracedAutoFinishTest { | ||
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. You should derive from the 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. Was going to, but I needed a Thread.sleep within the runnable/callable to make sure that I could check the current thread's span and scope were close before the runnable returned. I didn't want to modify the existing TestRunnable, even though the original tests should still pass. If you're OK with me making those changes then I'll go ahead and do that. 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. You could introduce a semaphore in the abstract test runnable/callable impls to allow the test to block their execution. |
||
private static final int NUMBER_OF_THREADS = 4; | ||
protected MockTracer mockTracer = new MockTracer(new AutoFinishScopeManager()); | ||
|
||
@Before | ||
public void before() { | ||
mockTracer.reset(); | ||
} | ||
|
||
@Test | ||
public void autoFinishScopeExecuteTest() throws InterruptedException { | ||
Executor executor = new TracedExecutor(Executors.newFixedThreadPool(10), mockTracer); | ||
|
||
try (Scope scope = mockTracer.buildSpan("auto-finish").startActive(true)){ | ||
executor.execute(new TestRunnable()); | ||
} | ||
|
||
assertNull(mockTracer.scopeManager().active()); | ||
assertNull(mockTracer.activeSpan()); | ||
assertEquals(0, mockTracer.finishedSpans().size()); | ||
await().atMost(15, TimeUnit.SECONDS).until(finishedSpansSize(mockTracer), equalTo(1)); | ||
assertEquals(1, mockTracer.finishedSpans().size()); | ||
} | ||
|
||
|
||
@Test | ||
public void autoFinishScopeSubmitCallableTest() throws InterruptedException { | ||
ExecutorService executorService = | ||
new TracedExecutorService(Executors.newFixedThreadPool(NUMBER_OF_THREADS), mockTracer); | ||
|
||
try (Scope scope = mockTracer.buildSpan("auto-finish").startActive(true)) { | ||
executorService.submit(new TestCallable()); | ||
} | ||
|
||
assertNull(mockTracer.scopeManager().active()); | ||
assertNull(mockTracer.activeSpan()); | ||
assertEquals(0, mockTracer.finishedSpans().size()); | ||
await().atMost(15, TimeUnit.SECONDS).until(finishedSpansSize(mockTracer), equalTo(1)); | ||
assertEquals(1, mockTracer.finishedSpans().size()); | ||
} | ||
|
||
@Test | ||
public void autoFinishScopeScheduleAtFixedRateTest() throws InterruptedException { | ||
final CountDownLatch countDownLatch = new CountDownLatch(2); | ||
|
||
ScheduledExecutorService executorService = | ||
new TracedScheduledExecutorService(Executors.newScheduledThreadPool(NUMBER_OF_THREADS), mockTracer); | ||
|
||
try (Scope scope = mockTracer.buildSpan("auto-finish").startActive(true)){ | ||
executorService.scheduleAtFixedRate(new Runnable() { | ||
@Override | ||
public void run() { | ||
try { | ||
Thread.sleep(300); | ||
countDownLatch.countDown(); | ||
} catch (InterruptedException e) { | ||
e.printStackTrace(); | ||
} | ||
} | ||
}, 0, 200, TimeUnit.MILLISECONDS); | ||
} | ||
|
||
assertNull(mockTracer.scopeManager().active()); | ||
assertNull(mockTracer.activeSpan()); | ||
assertEquals(0, mockTracer.finishedSpans().size()); | ||
countDownLatch.await(); | ||
await().atMost(15, TimeUnit.SECONDS).until(finishedSpansSize(mockTracer), equalTo(1)); | ||
executorService.shutdown(); | ||
assertEquals(1, mockTracer.finishedSpans().size()); | ||
} | ||
|
||
public static Callable<Integer> finishedSpansSize(final MockTracer tracer) { | ||
return new Callable<Integer>() { | ||
@Override | ||
public Integer call() throws Exception { | ||
return tracer.finishedSpans().size(); | ||
} | ||
}; | ||
} | ||
|
||
class TestRunnable implements Runnable { | ||
@Override | ||
public void run() { | ||
try { | ||
Thread.sleep(300); | ||
} catch (InterruptedException e) { | ||
e.printStackTrace(); | ||
} | ||
} | ||
} | ||
|
||
class TestCallable implements Callable<Void> { | ||
@Override | ||
public Void call() throws Exception { | ||
try { | ||
Thread.sleep(300); | ||
} catch (InterruptedException e) { | ||
e.printStackTrace(); | ||
} | ||
return null; | ||
} | ||
} | ||
} |
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.
Why the java version bump?
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.
Try with resources in a test. I suppose that does not merit the change. I'll revert these.