Merge branch '2.2.x'

This commit is contained in:
Marcin Grzejszczak
2020-01-31 08:19:15 +01:00
12 changed files with 80 additions and 61 deletions

View File

@@ -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();
}
}

View File

@@ -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;
}
}

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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));
}

View File

@@ -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();
}
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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;
}

View File

@@ -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)));
}
}

View File

@@ -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;
}

View File

@@ -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;
}