Merge branch '2.2.x'
This commit is contained in:
@@ -36,8 +36,8 @@ import org.springframework.context.annotation.Configuration;
|
||||
public class AsyncAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
ContextRefreshedListener traceContextRefreshedListener() {
|
||||
return new ContextRefreshedListener(false);
|
||||
SleuthContextListener traceContextClosedListener() {
|
||||
return new SleuthContextListener();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -35,12 +35,14 @@ final class ContextUtil {
|
||||
|
||||
private static final Log log = LogFactory.getLog(ContextUtil.class);
|
||||
|
||||
static boolean isContextInCreation(BeanFactory beanFactory) {
|
||||
boolean contextRefreshed = ContextRefreshedListener.getBean(beanFactory).get();
|
||||
if (!contextRefreshed && log.isDebugEnabled()) {
|
||||
log.debug("Context is not ready yet");
|
||||
static boolean isContextUnusable(BeanFactory beanFactory) {
|
||||
SleuthContextListener listener = SleuthContextListener.getBean(beanFactory);
|
||||
boolean contextUnusable = listener.isUnusable();
|
||||
if (contextUnusable && log.isDebugEnabled()) {
|
||||
log.debug("Context [" + Integer.toHexString(beanFactory.hashCode())
|
||||
+ "] is either not refreshed or is closed");
|
||||
}
|
||||
return !contextRefreshed;
|
||||
return contextUnusable;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ public class LazyTraceAsyncTaskExecutor implements AsyncTaskExecutor {
|
||||
@Override
|
||||
public void execute(Runnable task) {
|
||||
Runnable taskToRun = task;
|
||||
if (!ContextUtil.isContextInCreation(this.beanFactory)) {
|
||||
if (!ContextUtil.isContextUnusable(this.beanFactory)) {
|
||||
taskToRun = new TraceRunnable(tracing(), spanNamer(), task);
|
||||
}
|
||||
this.delegate.execute(taskToRun);
|
||||
@@ -66,7 +66,7 @@ public class LazyTraceAsyncTaskExecutor implements AsyncTaskExecutor {
|
||||
@Override
|
||||
public void execute(Runnable task, long startTimeout) {
|
||||
Runnable taskToRun = task;
|
||||
if (!ContextUtil.isContextInCreation(this.beanFactory)) {
|
||||
if (!ContextUtil.isContextUnusable(this.beanFactory)) {
|
||||
taskToRun = new TraceRunnable(tracing(), spanNamer(), task);
|
||||
}
|
||||
this.delegate.execute(taskToRun, startTimeout);
|
||||
@@ -75,7 +75,7 @@ public class LazyTraceAsyncTaskExecutor implements AsyncTaskExecutor {
|
||||
@Override
|
||||
public Future<?> submit(Runnable task) {
|
||||
Runnable taskToRun = task;
|
||||
if (!ContextUtil.isContextInCreation(this.beanFactory)) {
|
||||
if (!ContextUtil.isContextUnusable(this.beanFactory)) {
|
||||
taskToRun = new TraceRunnable(tracing(), spanNamer(), task);
|
||||
}
|
||||
return this.delegate.submit(taskToRun);
|
||||
@@ -84,7 +84,7 @@ public class LazyTraceAsyncTaskExecutor implements AsyncTaskExecutor {
|
||||
@Override
|
||||
public <T> Future<T> submit(Callable<T> task) {
|
||||
Callable<T> taskToRun = task;
|
||||
if (!ContextUtil.isContextInCreation(this.beanFactory)) {
|
||||
if (!ContextUtil.isContextUnusable(this.beanFactory)) {
|
||||
taskToRun = new TraceCallable<>(tracing(), spanNamer(), task);
|
||||
}
|
||||
return this.delegate.submit(taskToRun);
|
||||
|
||||
@@ -52,7 +52,7 @@ public class LazyTraceExecutor implements Executor {
|
||||
|
||||
@Override
|
||||
public void execute(Runnable command) {
|
||||
if (ContextUtil.isContextInCreation(this.beanFactory)) {
|
||||
if (ContextUtil.isContextUnusable(this.beanFactory)) {
|
||||
this.delegate.execute(command);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -62,39 +62,39 @@ public class LazyTraceThreadPoolTaskExecutor extends ThreadPoolTaskExecutor {
|
||||
|
||||
@Override
|
||||
public void execute(Runnable task) {
|
||||
this.delegate.execute(ContextUtil.isContextInCreation(this.beanFactory) ? task
|
||||
this.delegate.execute(ContextUtil.isContextUnusable(this.beanFactory) ? task
|
||||
: new TraceRunnable(tracing(), spanNamer(), task));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Runnable task, long startTimeout) {
|
||||
this.delegate.execute(ContextUtil.isContextInCreation(this.beanFactory) ? task
|
||||
this.delegate.execute(ContextUtil.isContextUnusable(this.beanFactory) ? task
|
||||
: new TraceRunnable(tracing(), spanNamer(), task), startTimeout);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Future<?> submit(Runnable task) {
|
||||
return this.delegate.submit(ContextUtil.isContextInCreation(this.beanFactory)
|
||||
? task : new TraceRunnable(tracing(), spanNamer(), task));
|
||||
return this.delegate.submit(ContextUtil.isContextUnusable(this.beanFactory) ? task
|
||||
: new TraceRunnable(tracing(), spanNamer(), task));
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> Future<T> submit(Callable<T> task) {
|
||||
return this.delegate.submit(ContextUtil.isContextInCreation(this.beanFactory)
|
||||
? task : new TraceCallable<>(tracing(), spanNamer(), task));
|
||||
return this.delegate.submit(ContextUtil.isContextUnusable(this.beanFactory) ? task
|
||||
: new TraceCallable<>(tracing(), spanNamer(), task));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<?> submitListenable(Runnable task) {
|
||||
return this.delegate
|
||||
.submitListenable(ContextUtil.isContextInCreation(this.beanFactory) ? task
|
||||
.submitListenable(ContextUtil.isContextUnusable(this.beanFactory) ? task
|
||||
: new TraceRunnable(tracing(), spanNamer(), task));
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> ListenableFuture<T> submitListenable(Callable<T> task) {
|
||||
return this.delegate
|
||||
.submitListenable(ContextUtil.isContextInCreation(this.beanFactory) ? task
|
||||
.submitListenable(ContextUtil.isContextUnusable(this.beanFactory) ? task
|
||||
: new TraceCallable<>(tracing(), spanNamer(), task));
|
||||
}
|
||||
|
||||
|
||||
@@ -27,48 +27,64 @@ import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.event.ApplicationContextEvent;
|
||||
import org.springframework.context.event.ContextClosedEvent;
|
||||
import org.springframework.context.event.ContextRefreshedEvent;
|
||||
import org.springframework.context.event.SmartApplicationListener;
|
||||
|
||||
class ContextRefreshedListener extends AtomicBoolean implements SmartApplicationListener {
|
||||
class SleuthContextListener implements SmartApplicationListener {
|
||||
|
||||
static final Map<BeanFactory, ContextRefreshedListener> CACHE = new ConcurrentHashMap<>();
|
||||
static final Map<BeanFactory, SleuthContextListener> CACHE = new ConcurrentHashMap<>();
|
||||
|
||||
private static final Log log = LogFactory.getLog(ContextRefreshedListener.class);
|
||||
private static final Log log = LogFactory.getLog(SleuthContextListener.class);
|
||||
|
||||
ContextRefreshedListener(boolean initialValue) {
|
||||
super(initialValue);
|
||||
final AtomicBoolean refreshed;
|
||||
|
||||
final AtomicBoolean closed;
|
||||
|
||||
SleuthContextListener() {
|
||||
this.refreshed = new AtomicBoolean();
|
||||
this.closed = new AtomicBoolean();
|
||||
}
|
||||
|
||||
ContextRefreshedListener() {
|
||||
this(false);
|
||||
SleuthContextListener(AtomicBoolean refreshed, AtomicBoolean closed) {
|
||||
this.refreshed = refreshed;
|
||||
this.closed = closed;
|
||||
}
|
||||
|
||||
static ContextRefreshedListener getBean(BeanFactory beanFactory) {
|
||||
return CACHE.getOrDefault(beanFactory, new ContextRefreshedListener(false));
|
||||
static SleuthContextListener getBean(BeanFactory beanFactory) {
|
||||
return CACHE.getOrDefault(beanFactory, new SleuthContextListener());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsEventType(Class<? extends ApplicationEvent> eventType) {
|
||||
return ContextRefreshedEvent.class.isAssignableFrom(eventType);
|
||||
return ContextClosedEvent.class.isAssignableFrom(eventType)
|
||||
|| ContextRefreshedEvent.class.isAssignableFrom(eventType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onApplicationEvent(ApplicationEvent event) {
|
||||
if (event instanceof ContextRefreshedEvent) {
|
||||
if (event instanceof ContextRefreshedEvent
|
||||
|| event instanceof ContextClosedEvent) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Context successfully refreshed");
|
||||
log.debug("Context refreshed or closed [" + event + "]");
|
||||
}
|
||||
ContextRefreshedEvent contextRefreshedEvent = (ContextRefreshedEvent) event;
|
||||
ApplicationContext context = contextRefreshedEvent.getApplicationContext();
|
||||
ApplicationContextEvent contextEvent = (ApplicationContextEvent) event;
|
||||
ApplicationContext context = contextEvent.getApplicationContext();
|
||||
BeanFactory beanFactory = context;
|
||||
if (context instanceof ConfigurableApplicationContext) {
|
||||
beanFactory = ((ConfigurableApplicationContext) context).getBeanFactory();
|
||||
}
|
||||
ContextRefreshedListener listener = CACHE.getOrDefault(beanFactory, this);
|
||||
listener.set(true);
|
||||
SleuthContextListener listener = CACHE.getOrDefault(beanFactory, this);
|
||||
listener.refreshed.compareAndSet(false,
|
||||
event instanceof ContextRefreshedEvent);
|
||||
listener.closed.compareAndSet(false, event instanceof ContextClosedEvent);
|
||||
CACHE.put(beanFactory, listener);
|
||||
}
|
||||
}
|
||||
|
||||
boolean isUnusable() {
|
||||
return !this.refreshed.get() || this.closed.get();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -63,7 +63,7 @@ public class TraceableExecutorService implements ExecutorService {
|
||||
|
||||
@Override
|
||||
public void execute(Runnable command) {
|
||||
this.delegate.execute(ContextUtil.isContextInCreation(this.beanFactory) ? command
|
||||
this.delegate.execute(ContextUtil.isContextUnusable(this.beanFactory) ? command
|
||||
: new TraceRunnable(tracing(), spanNamer(), command, this.spanName));
|
||||
}
|
||||
|
||||
@@ -95,43 +95,42 @@ public class TraceableExecutorService implements ExecutorService {
|
||||
|
||||
@Override
|
||||
public <T> Future<T> submit(Callable<T> task) {
|
||||
return this.delegate.submit(ContextUtil.isContextInCreation(this.beanFactory)
|
||||
? task
|
||||
return this.delegate.submit(ContextUtil.isContextUnusable(this.beanFactory) ? task
|
||||
: new TraceCallable<>(tracing(), spanNamer(), task, this.spanName));
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> Future<T> submit(Runnable task, T result) {
|
||||
return this.delegate.submit(
|
||||
ContextUtil.isContextInCreation(this.beanFactory) ? task
|
||||
ContextUtil.isContextUnusable(this.beanFactory) ? task
|
||||
: new TraceRunnable(tracing(), spanNamer(), task, this.spanName),
|
||||
result);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Future<?> submit(Runnable task) {
|
||||
return this.delegate.submit(ContextUtil.isContextInCreation(this.beanFactory)
|
||||
? task : new TraceRunnable(tracing(), spanNamer(), task, this.spanName));
|
||||
return this.delegate.submit(ContextUtil.isContextUnusable(this.beanFactory) ? task
|
||||
: new TraceRunnable(tracing(), spanNamer(), task, this.spanName));
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
|
||||
throws InterruptedException {
|
||||
return this.delegate.invokeAll(ContextUtil.isContextInCreation(this.beanFactory)
|
||||
return this.delegate.invokeAll(ContextUtil.isContextUnusable(this.beanFactory)
|
||||
? tasks : wrapCallableCollection(tasks));
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,
|
||||
long timeout, TimeUnit unit) throws InterruptedException {
|
||||
return this.delegate.invokeAll(ContextUtil.isContextInCreation(this.beanFactory)
|
||||
return this.delegate.invokeAll(ContextUtil.isContextUnusable(this.beanFactory)
|
||||
? tasks : wrapCallableCollection(tasks), timeout, unit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T invokeAny(Collection<? extends Callable<T>> tasks)
|
||||
throws InterruptedException, ExecutionException {
|
||||
return this.delegate.invokeAny(ContextUtil.isContextInCreation(this.beanFactory)
|
||||
return this.delegate.invokeAny(ContextUtil.isContextUnusable(this.beanFactory)
|
||||
? tasks : wrapCallableCollection(tasks));
|
||||
}
|
||||
|
||||
@@ -139,7 +138,7 @@ public class TraceableExecutorService implements ExecutorService {
|
||||
public <T> T invokeAny(Collection<? extends Callable<T>> tasks, long timeout,
|
||||
TimeUnit unit)
|
||||
throws InterruptedException, ExecutionException, TimeoutException {
|
||||
return this.delegate.invokeAny(ContextUtil.isContextInCreation(this.beanFactory)
|
||||
return this.delegate.invokeAny(ContextUtil.isContextUnusable(this.beanFactory)
|
||||
? tasks : wrapCallableCollection(tasks), timeout, unit);
|
||||
}
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ public class TraceableScheduledExecutorService extends TraceableExecutorService
|
||||
@Override
|
||||
public ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit) {
|
||||
return getScheduledExecutorService().schedule(
|
||||
ContextUtil.isContextInCreation(this.beanFactory) ? command
|
||||
ContextUtil.isContextUnusable(this.beanFactory) ? command
|
||||
: new TraceRunnable(tracing(), spanNamer(), command),
|
||||
delay, unit);
|
||||
}
|
||||
@@ -54,7 +54,7 @@ public class TraceableScheduledExecutorService extends TraceableExecutorService
|
||||
public <V> ScheduledFuture<V> schedule(Callable<V> callable, long delay,
|
||||
TimeUnit unit) {
|
||||
return getScheduledExecutorService().schedule(
|
||||
ContextUtil.isContextInCreation(this.beanFactory) ? callable
|
||||
ContextUtil.isContextUnusable(this.beanFactory) ? callable
|
||||
: new TraceCallable<>(tracing(), spanNamer(), callable),
|
||||
delay, unit);
|
||||
}
|
||||
@@ -63,7 +63,7 @@ public class TraceableScheduledExecutorService extends TraceableExecutorService
|
||||
public ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay,
|
||||
long period, TimeUnit unit) {
|
||||
return getScheduledExecutorService().scheduleAtFixedRate(
|
||||
ContextUtil.isContextInCreation(this.beanFactory) ? command
|
||||
ContextUtil.isContextUnusable(this.beanFactory) ? command
|
||||
: new TraceRunnable(tracing(), spanNamer(), command),
|
||||
initialDelay, period, unit);
|
||||
}
|
||||
@@ -72,7 +72,7 @@ public class TraceableScheduledExecutorService extends TraceableExecutorService
|
||||
public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay,
|
||||
long delay, TimeUnit unit) {
|
||||
return getScheduledExecutorService().scheduleWithFixedDelay(
|
||||
ContextUtil.isContextInCreation(this.beanFactory) ? command
|
||||
ContextUtil.isContextUnusable(this.beanFactory) ? command
|
||||
: new TraceRunnable(tracing(), spanNamer(), command),
|
||||
initialDelay, delay, unit);
|
||||
}
|
||||
|
||||
@@ -67,7 +67,7 @@ public class LazyTraceThreadPoolTaskSchedulerTests {
|
||||
.willReturn(this.tracing);
|
||||
BDDMockito.given(this.beanFactory.getBean(SpanNamer.class))
|
||||
.willReturn(new DefaultSpanNamer());
|
||||
ContextRefreshedListenerAccessor.set(this.beanFactory, true);
|
||||
SleuthContextListenerAccessor.set(this.beanFactory, true);
|
||||
return this.beanFactory;
|
||||
}
|
||||
|
||||
|
||||
@@ -16,17 +16,19 @@
|
||||
|
||||
package org.springframework.cloud.sleuth.instrument.async;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
|
||||
public final class ContextRefreshedListenerAccessor {
|
||||
public final class SleuthContextListenerAccessor {
|
||||
|
||||
private ContextRefreshedListenerAccessor() {
|
||||
private SleuthContextListenerAccessor() {
|
||||
throw new IllegalStateException("Can't instantiate a utility class");
|
||||
}
|
||||
|
||||
public static void set(BeanFactory beanFactory, boolean refreshed) {
|
||||
ContextRefreshedListener.CACHE.put(beanFactory,
|
||||
new ContextRefreshedListener(refreshed));
|
||||
SleuthContextListener.CACHE.put(beanFactory, new SleuthContextListener(
|
||||
new AtomicBoolean(refreshed), new AtomicBoolean(false)));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -232,7 +232,7 @@ public class TraceableExecutorServiceTests {
|
||||
.willReturn(this.tracing);
|
||||
BDDMockito.given(this.beanFactory.getBean(SpanNamer.class))
|
||||
.willReturn(new DefaultSpanNamer());
|
||||
ContextRefreshedListenerAccessor.set(this.beanFactory, refreshed);
|
||||
SleuthContextListenerAccessor.set(this.beanFactory, refreshed);
|
||||
return this.beanFactory;
|
||||
}
|
||||
|
||||
|
||||
@@ -112,7 +112,7 @@ public class TraceableScheduledExecutorServiceTest {
|
||||
@Test
|
||||
public void should_not_schedule_a_trace_runnable_when_context_not_ready()
|
||||
throws Exception {
|
||||
ContextRefreshedListenerAccessor.set(this.beanFactory, false);
|
||||
SleuthContextListenerAccessor.set(this.beanFactory, false);
|
||||
this.traceableScheduledExecutorService.schedule(aRunnable(), 1L, TimeUnit.DAYS);
|
||||
|
||||
then(this.scheduledExecutorService).should(never()).schedule(
|
||||
@@ -124,7 +124,7 @@ public class TraceableScheduledExecutorServiceTest {
|
||||
@Test
|
||||
public void should_not_schedule_a_trace_callable_when_context_not_ready()
|
||||
throws Exception {
|
||||
ContextRefreshedListenerAccessor.set(this.beanFactory, false);
|
||||
SleuthContextListenerAccessor.set(this.beanFactory, false);
|
||||
this.traceableScheduledExecutorService.schedule(aCallable(), 1L, TimeUnit.DAYS);
|
||||
|
||||
then(this.scheduledExecutorService).should(never()).schedule(
|
||||
@@ -136,7 +136,7 @@ public class TraceableScheduledExecutorServiceTest {
|
||||
@Test
|
||||
public void should_not_schedule_at_fixed_rate_a_trace_runnable_when_context_not_ready()
|
||||
throws Exception {
|
||||
ContextRefreshedListenerAccessor.set(this.beanFactory, false);
|
||||
SleuthContextListenerAccessor.set(this.beanFactory, false);
|
||||
this.traceableScheduledExecutorService.scheduleAtFixedRate(aRunnable(), 1L, 1L,
|
||||
TimeUnit.DAYS);
|
||||
|
||||
@@ -149,7 +149,7 @@ public class TraceableScheduledExecutorServiceTest {
|
||||
@Test
|
||||
public void should_not_schedule_with_fixed_delay_a_trace_runnable_when_context_not_ready()
|
||||
throws Exception {
|
||||
ContextRefreshedListenerAccessor.set(this.beanFactory, false);
|
||||
SleuthContextListenerAccessor.set(this.beanFactory, false);
|
||||
this.traceableScheduledExecutorService.scheduleWithFixedDelay(aRunnable(), 1L, 1L,
|
||||
TimeUnit.DAYS);
|
||||
|
||||
@@ -181,7 +181,7 @@ public class TraceableScheduledExecutorServiceTest {
|
||||
.willReturn(this.tracing);
|
||||
BDDMockito.given(this.beanFactory.getBean(SpanNamer.class))
|
||||
.willReturn(new DefaultSpanNamer());
|
||||
ContextRefreshedListenerAccessor.set(this.beanFactory, true);
|
||||
SleuthContextListenerAccessor.set(this.beanFactory, true);
|
||||
return this.beanFactory;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user