Move observation support classes to scheduling.support package
Avoids a package cycle between config and support (only config->support allowed). See gh-29883
This commit is contained in:
parent
8fb412ea74
commit
f0fe58f0ec
|
|
@ -91,7 +91,7 @@ This can be done by declaring a `SchedulingConfigurer` bean that sets the observ
|
||||||
|
|
||||||
include-code::./ObservationSchedulingConfigurer[]
|
include-code::./ObservationSchedulingConfigurer[]
|
||||||
|
|
||||||
It is using the `org.springframework.scheduling.config.DefaultScheduledTaskObservationConvention` by default, backed by the `ScheduledTaskObservationContext`.
|
It is using the `org.springframework.scheduling.support.DefaultScheduledTaskObservationConvention` by default, backed by the `ScheduledTaskObservationContext`.
|
||||||
You can configure a custom implementation on the `ObservationRegistry` directly.
|
You can configure a custom implementation on the `ObservationRegistry` directly.
|
||||||
During the execution of the scheduled method, the current observation is restored in the `ThreadLocal` context or the Reactor context (if the scheduled method returns a `Mono` or `Flux` type).
|
During the execution of the scheduled method, the current observation is restored in the `ThreadLocal` context or the Reactor context (if the scheduled method returns a `Mono` or `Flux` type).
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -38,15 +38,15 @@ import org.springframework.core.KotlinDetector;
|
||||||
import org.springframework.core.ReactiveAdapter;
|
import org.springframework.core.ReactiveAdapter;
|
||||||
import org.springframework.core.ReactiveAdapterRegistry;
|
import org.springframework.core.ReactiveAdapterRegistry;
|
||||||
import org.springframework.lang.Nullable;
|
import org.springframework.lang.Nullable;
|
||||||
import org.springframework.scheduling.config.DefaultScheduledTaskObservationConvention;
|
import org.springframework.scheduling.support.DefaultScheduledTaskObservationConvention;
|
||||||
import org.springframework.scheduling.config.ScheduledTaskObservationContext;
|
import org.springframework.scheduling.support.ScheduledTaskObservationContext;
|
||||||
import org.springframework.scheduling.config.ScheduledTaskObservationConvention;
|
import org.springframework.scheduling.support.ScheduledTaskObservationConvention;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
import org.springframework.util.ClassUtils;
|
import org.springframework.util.ClassUtils;
|
||||||
import org.springframework.util.ReflectionUtils;
|
import org.springframework.util.ReflectionUtils;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
import static org.springframework.scheduling.config.ScheduledTaskObservationDocumentation.TASKS_SCHEDULED_EXECUTION;
|
import static org.springframework.scheduling.support.ScheduledTaskObservationDocumentation.TASKS_SCHEDULED_EXECUTION;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper class for @{@link ScheduledAnnotationBeanPostProcessor} to support reactive
|
* Helper class for @{@link ScheduledAnnotationBeanPostProcessor} to support reactive
|
||||||
|
|
|
||||||
|
|
@ -14,14 +14,14 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.scheduling.config;
|
package org.springframework.scheduling.support;
|
||||||
|
|
||||||
import io.micrometer.common.KeyValue;
|
import io.micrometer.common.KeyValue;
|
||||||
import io.micrometer.common.KeyValues;
|
import io.micrometer.common.KeyValues;
|
||||||
|
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
import static org.springframework.scheduling.config.ScheduledTaskObservationDocumentation.LowCardinalityKeyNames;
|
import static org.springframework.scheduling.support.ScheduledTaskObservationDocumentation.LowCardinalityKeyNames;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default implementation for {@link ScheduledTaskObservationConvention}.
|
* Default implementation for {@link ScheduledTaskObservationConvention}.
|
||||||
|
|
@ -24,10 +24,6 @@ import java.util.function.Supplier;
|
||||||
import io.micrometer.observation.Observation;
|
import io.micrometer.observation.Observation;
|
||||||
import io.micrometer.observation.ObservationRegistry;
|
import io.micrometer.observation.ObservationRegistry;
|
||||||
|
|
||||||
import org.springframework.scheduling.config.DefaultScheduledTaskObservationConvention;
|
|
||||||
import org.springframework.scheduling.config.ScheduledTaskObservationContext;
|
|
||||||
import org.springframework.scheduling.config.ScheduledTaskObservationConvention;
|
|
||||||
import org.springframework.scheduling.config.ScheduledTaskObservationDocumentation;
|
|
||||||
import org.springframework.util.ReflectionUtils;
|
import org.springframework.util.ReflectionUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -42,7 +38,8 @@ import org.springframework.util.ReflectionUtils;
|
||||||
*/
|
*/
|
||||||
public class ScheduledMethodRunnable implements Runnable {
|
public class ScheduledMethodRunnable implements Runnable {
|
||||||
|
|
||||||
private static final ScheduledTaskObservationConvention DEFAULT_CONVENTION = new DefaultScheduledTaskObservationConvention();
|
private static final ScheduledTaskObservationConvention DEFAULT_CONVENTION =
|
||||||
|
new DefaultScheduledTaskObservationConvention();
|
||||||
|
|
||||||
private final Object target;
|
private final Object target;
|
||||||
|
|
||||||
|
|
@ -50,6 +47,7 @@ public class ScheduledMethodRunnable implements Runnable {
|
||||||
|
|
||||||
private final Supplier<ObservationRegistry> observationRegistrySupplier;
|
private final Supplier<ObservationRegistry> observationRegistrySupplier;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a {@code ScheduledMethodRunnable} for the given target instance,
|
* Create a {@code ScheduledMethodRunnable} for the given target instance,
|
||||||
* calling the specified method.
|
* calling the specified method.
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.scheduling.config;
|
package org.springframework.scheduling.support;
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
|
|
||||||
|
|
@ -23,8 +23,9 @@ import io.micrometer.observation.Observation;
|
||||||
import org.springframework.util.ClassUtils;
|
import org.springframework.util.ClassUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Context that holds information for observation metadata collection
|
* Context that holds information for observation metadata collection during the
|
||||||
* during the {@link ScheduledTaskObservationDocumentation#TASKS_SCHEDULED_EXECUTION execution of scheduled tasks}.
|
* {@link ScheduledTaskObservationDocumentation#TASKS_SCHEDULED_EXECUTION execution of scheduled tasks}.
|
||||||
|
*
|
||||||
* @author Brian Clozel
|
* @author Brian Clozel
|
||||||
* @since 6.1
|
* @since 6.1
|
||||||
*/
|
*/
|
||||||
|
|
@ -36,6 +37,7 @@ public class ScheduledTaskObservationContext extends Observation.Context {
|
||||||
|
|
||||||
private boolean complete;
|
private boolean complete;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new observation context for a task, given the target object
|
* Create a new observation context for a task, given the target object
|
||||||
* and the method to be called.
|
* and the method to be called.
|
||||||
|
|
@ -47,6 +49,7 @@ public class ScheduledTaskObservationContext extends Observation.Context {
|
||||||
this.method = method;
|
this.method = method;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the type of the target object.
|
* Return the type of the target object.
|
||||||
*/
|
*/
|
||||||
|
|
@ -77,4 +80,5 @@ public class ScheduledTaskObservationContext extends Observation.Context {
|
||||||
public void setComplete(boolean complete) {
|
public void setComplete(boolean complete) {
|
||||||
this.complete = complete;
|
this.complete = complete;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.scheduling.config;
|
package org.springframework.scheduling.support;
|
||||||
|
|
||||||
import io.micrometer.observation.Observation;
|
import io.micrometer.observation.Observation;
|
||||||
import io.micrometer.observation.ObservationConvention;
|
import io.micrometer.observation.ObservationConvention;
|
||||||
|
|
@ -22,6 +22,7 @@ import io.micrometer.observation.ObservationConvention;
|
||||||
/**
|
/**
|
||||||
* Interface for an {@link ObservationConvention} for
|
* Interface for an {@link ObservationConvention} for
|
||||||
* {@link ScheduledTaskObservationDocumentation#TASKS_SCHEDULED_EXECUTION scheduled task executions}.
|
* {@link ScheduledTaskObservationDocumentation#TASKS_SCHEDULED_EXECUTION scheduled task executions}.
|
||||||
|
*
|
||||||
* @author Brian Clozel
|
* @author Brian Clozel
|
||||||
* @since 6.1
|
* @since 6.1
|
||||||
*/
|
*/
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.scheduling.config;
|
package org.springframework.scheduling.support;
|
||||||
|
|
||||||
import io.micrometer.common.KeyValue;
|
import io.micrometer.common.KeyValue;
|
||||||
import io.micrometer.common.docs.KeyName;
|
import io.micrometer.common.docs.KeyName;
|
||||||
|
|
@ -24,8 +24,10 @@ import io.micrometer.observation.docs.ObservationDocumentation;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Documented {@link io.micrometer.common.KeyValue KeyValues} for the observations on
|
* Documented {@link io.micrometer.common.KeyValue KeyValues} for the observations on
|
||||||
* executions of {@link org.springframework.scheduling.annotation.Scheduled scheduled tasks}.
|
* executions of {@link org.springframework.scheduling.annotation.Scheduled scheduled tasks}
|
||||||
* <p>This class is used by automated tools to document KeyValues attached to the {@code @Scheduled} observations.
|
*
|
||||||
|
* <p>This class is used by automated tools to document KeyValues attached to the
|
||||||
|
* {@code @Scheduled} observations.
|
||||||
*
|
*
|
||||||
* @author Brian Clozel
|
* @author Brian Clozel
|
||||||
* @since 6.1
|
* @since 6.1
|
||||||
|
|
@ -40,19 +42,17 @@ public enum ScheduledTaskObservationDocumentation implements ObservationDocument
|
||||||
public Class<? extends ObservationConvention<? extends Observation.Context>> getDefaultConvention() {
|
public Class<? extends ObservationConvention<? extends Observation.Context>> getDefaultConvention() {
|
||||||
return DefaultScheduledTaskObservationConvention.class;
|
return DefaultScheduledTaskObservationConvention.class;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public KeyName[] getLowCardinalityKeyNames() {
|
public KeyName[] getLowCardinalityKeyNames() {
|
||||||
return LowCardinalityKeyNames.values();
|
return LowCardinalityKeyNames.values();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public KeyName[] getHighCardinalityKeyNames() {
|
public KeyName[] getHighCardinalityKeyNames() {
|
||||||
return new KeyName[] {};
|
return new KeyName[] {};
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
public enum LowCardinalityKeyNames implements KeyName {
|
public enum LowCardinalityKeyNames implements KeyName {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -36,8 +36,8 @@ import org.springframework.context.support.StaticApplicationContext;
|
||||||
import org.springframework.core.task.SimpleAsyncTaskExecutor;
|
import org.springframework.core.task.SimpleAsyncTaskExecutor;
|
||||||
import org.springframework.scheduling.config.ScheduledTask;
|
import org.springframework.scheduling.config.ScheduledTask;
|
||||||
import org.springframework.scheduling.config.ScheduledTaskHolder;
|
import org.springframework.scheduling.config.ScheduledTaskHolder;
|
||||||
import org.springframework.scheduling.config.ScheduledTaskObservationContext;
|
|
||||||
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
|
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
|
||||||
|
import org.springframework.scheduling.support.ScheduledTaskObservationContext;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
|
@ -55,11 +55,13 @@ class ScheduledAnnotationBeanPostProcessorObservabilityTests {
|
||||||
|
|
||||||
private final TestObservationRegistry observationRegistry = TestObservationRegistry.create();
|
private final TestObservationRegistry observationRegistry = TestObservationRegistry.create();
|
||||||
|
|
||||||
|
|
||||||
@AfterEach
|
@AfterEach
|
||||||
void closeContext() {
|
void closeContext() {
|
||||||
context.close();
|
context.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldRecordSuccessObservationsForTasks() throws Exception {
|
void shouldRecordSuccessObservationsForTasks() throws Exception {
|
||||||
registerScheduledBean(FixedDelayBean.class);
|
registerScheduledBean(FixedDelayBean.class);
|
||||||
|
|
@ -185,6 +187,7 @@ class ScheduledAnnotationBeanPostProcessorObservabilityTests {
|
||||||
.hasObservationWithNameEqualTo("tasks.scheduled.execution").that();
|
.hasObservationWithNameEqualTo("tasks.scheduled.execution").that();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static abstract class TaskTester {
|
static abstract class TaskTester {
|
||||||
|
|
||||||
ObservationRegistry observationRegistry;
|
ObservationRegistry observationRegistry;
|
||||||
|
|
@ -200,13 +203,13 @@ class ScheduledAnnotationBeanPostProcessorObservabilityTests {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static class FixedDelayBean extends TaskTester {
|
static class FixedDelayBean extends TaskTester {
|
||||||
|
|
||||||
@Scheduled(fixedDelay = 10_000, initialDelay = 5_000)
|
@Scheduled(fixedDelay = 10_000, initialDelay = 5_000)
|
||||||
public void fixedDelay() {
|
public void fixedDelay() {
|
||||||
this.latch.countDown();
|
this.latch.countDown();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -217,18 +220,18 @@ class ScheduledAnnotationBeanPostProcessorObservabilityTests {
|
||||||
this.latch.countDown();
|
this.latch.countDown();
|
||||||
throw new IllegalStateException("test error");
|
throw new IllegalStateException("test error");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static class FixedDelayReactiveBean extends TaskTester {
|
static class FixedDelayReactiveBean extends TaskTester {
|
||||||
|
|
||||||
@Scheduled(fixedDelay = 10_000, initialDelay = 5_000)
|
@Scheduled(fixedDelay = 10_000, initialDelay = 5_000)
|
||||||
public Mono<Object> fixedDelay() {
|
public Mono<Object> fixedDelay() {
|
||||||
return Mono.empty().doOnTerminate(() -> this.latch.countDown());
|
return Mono.empty().doOnTerminate(() -> this.latch.countDown());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static class FixedDelayReactiveErrorBean extends TaskTester {
|
static class FixedDelayReactiveErrorBean extends TaskTester {
|
||||||
|
|
||||||
@Scheduled(fixedDelay = 10_000, initialDelay = 5_000)
|
@Scheduled(fixedDelay = 10_000, initialDelay = 5_000)
|
||||||
|
|
@ -236,9 +239,9 @@ class ScheduledAnnotationBeanPostProcessorObservabilityTests {
|
||||||
return Mono.error(new IllegalStateException("test error"))
|
return Mono.error(new IllegalStateException("test error"))
|
||||||
.doOnTerminate(() -> this.latch.countDown());
|
.doOnTerminate(() -> this.latch.countDown());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static class CancelledTaskBean extends TaskTester {
|
static class CancelledTaskBean extends TaskTester {
|
||||||
|
|
||||||
@Scheduled(fixedDelay = 10_000, initialDelay = 5_000)
|
@Scheduled(fixedDelay = 10_000, initialDelay = 5_000)
|
||||||
|
|
@ -251,9 +254,9 @@ class ScheduledAnnotationBeanPostProcessorObservabilityTests {
|
||||||
// ignore cancelled task
|
// ignore cancelled task
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static class CancelledReactiveTaskBean extends TaskTester {
|
static class CancelledReactiveTaskBean extends TaskTester {
|
||||||
|
|
||||||
@Scheduled(fixedDelay = 10_000, initialDelay = 5_000)
|
@Scheduled(fixedDelay = 10_000, initialDelay = 5_000)
|
||||||
|
|
@ -261,9 +264,9 @@ class ScheduledAnnotationBeanPostProcessorObservabilityTests {
|
||||||
return Flux.interval(Duration.ZERO, Duration.ofSeconds(1))
|
return Flux.interval(Duration.ZERO, Duration.ofSeconds(1))
|
||||||
.doOnNext(el -> this.latch.countDown());
|
.doOnNext(el -> this.latch.countDown());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static class CurrentObservationBean extends TaskTester {
|
static class CurrentObservationBean extends TaskTester {
|
||||||
|
|
||||||
@Scheduled(fixedDelay = 10_000, initialDelay = 5_000)
|
@Scheduled(fixedDelay = 10_000, initialDelay = 5_000)
|
||||||
|
|
@ -272,9 +275,9 @@ class ScheduledAnnotationBeanPostProcessorObservabilityTests {
|
||||||
assertThat(this.observationRegistry.getCurrentObservation().getContext()).isInstanceOf(ScheduledTaskObservationContext.class);
|
assertThat(this.observationRegistry.getCurrentObservation().getContext()).isInstanceOf(ScheduledTaskObservationContext.class);
|
||||||
this.latch.countDown();
|
this.latch.countDown();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static class CurrentObservationReactiveBean extends TaskTester {
|
static class CurrentObservationReactiveBean extends TaskTester {
|
||||||
|
|
||||||
@Scheduled(fixedDelay = 10_000, initialDelay = 5_000)
|
@Scheduled(fixedDelay = 10_000, initialDelay = 5_000)
|
||||||
|
|
@ -290,7 +293,6 @@ class ScheduledAnnotationBeanPostProcessorObservabilityTests {
|
||||||
})
|
})
|
||||||
.doOnTerminate(() -> this.latch.countDown());
|
.doOnTerminate(() -> this.latch.countDown());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.scheduling.config;
|
package org.springframework.scheduling.support;
|
||||||
|
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
|
|
@ -37,6 +37,7 @@ class DefaultScheduledTaskObservationConventionTests {
|
||||||
|
|
||||||
private final ScheduledTaskObservationConvention convention = new DefaultScheduledTaskObservationConvention();
|
private final ScheduledTaskObservationConvention convention = new DefaultScheduledTaskObservationConvention();
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void observationShouldHaveDefaultName() {
|
void observationShouldHaveDefaultName() {
|
||||||
assertThat(convention.getName()).isEqualTo("tasks.scheduled.execution");
|
assertThat(convention.getName()).isEqualTo("tasks.scheduled.execution");
|
||||||
|
|
@ -92,17 +93,16 @@ class DefaultScheduledTaskObservationConventionTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static class BeanWithScheduledMethods implements TaskProcessor {
|
|
||||||
|
|
||||||
public void process() {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
interface TaskProcessor {
|
interface TaskProcessor {
|
||||||
|
|
||||||
void process();
|
void process();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static class BeanWithScheduledMethods implements TaskProcessor {
|
||||||
|
|
||||||
|
public void process() {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue