Add auto configuration for spring scheduling instrumentation using aop (#12438)
This commit is contained in:
parent
802e8789bd
commit
4497fbf968
|
@ -0,0 +1,90 @@
|
||||||
|
/*
|
||||||
|
* Copyright The OpenTelemetry Authors
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.scheduling;
|
||||||
|
|
||||||
|
import io.opentelemetry.api.OpenTelemetry;
|
||||||
|
import io.opentelemetry.api.common.AttributeKey;
|
||||||
|
import io.opentelemetry.context.Context;
|
||||||
|
import io.opentelemetry.context.Scope;
|
||||||
|
import io.opentelemetry.instrumentation.api.incubator.semconv.code.CodeAttributesExtractor;
|
||||||
|
import io.opentelemetry.instrumentation.api.incubator.semconv.code.CodeAttributesGetter;
|
||||||
|
import io.opentelemetry.instrumentation.api.incubator.semconv.code.CodeSpanNameExtractor;
|
||||||
|
import io.opentelemetry.instrumentation.api.incubator.semconv.util.ClassAndMethod;
|
||||||
|
import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor;
|
||||||
|
import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter;
|
||||||
|
import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder;
|
||||||
|
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
|
||||||
|
import org.aspectj.lang.ProceedingJoinPoint;
|
||||||
|
import org.aspectj.lang.annotation.Around;
|
||||||
|
import org.aspectj.lang.annotation.Aspect;
|
||||||
|
import org.aspectj.lang.annotation.Pointcut;
|
||||||
|
import org.aspectj.lang.reflect.MethodSignature;
|
||||||
|
import org.springframework.aop.framework.AopProxyUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Spring Scheduling instrumentation aop.
|
||||||
|
*
|
||||||
|
* <p>This aspect would intercept all methods annotated with {@link
|
||||||
|
* org.springframework.scheduling.annotation.Scheduled} and {@link
|
||||||
|
* org.springframework.scheduling.annotation.Schedules}.
|
||||||
|
*
|
||||||
|
* <p>Normally this would cover most of the Spring Scheduling use cases, but if you register jobs
|
||||||
|
* programmatically such as {@link
|
||||||
|
* org.springframework.scheduling.config.ScheduledTaskRegistrar#addCronTask}, this aspect would not
|
||||||
|
* cover them. You may use {@link io.opentelemetry.instrumentation.annotations.WithSpan} to trace
|
||||||
|
* these jobs manually.
|
||||||
|
*/
|
||||||
|
@Aspect
|
||||||
|
final class SpringSchedulingInstrumentationAspect {
|
||||||
|
public static final String INSTRUMENTATION_NAME = "io.opentelemetry.spring-scheduling-3.1";
|
||||||
|
private final Instrumenter<ClassAndMethod, Object> instrumenter;
|
||||||
|
|
||||||
|
public SpringSchedulingInstrumentationAspect(
|
||||||
|
OpenTelemetry openTelemetry, ConfigProperties configProperties) {
|
||||||
|
CodeAttributesGetter<ClassAndMethod> codedAttributesGetter =
|
||||||
|
ClassAndMethod.codeAttributesGetter();
|
||||||
|
InstrumenterBuilder<ClassAndMethod, Object> builder =
|
||||||
|
Instrumenter.builder(
|
||||||
|
openTelemetry,
|
||||||
|
INSTRUMENTATION_NAME,
|
||||||
|
CodeSpanNameExtractor.create(codedAttributesGetter))
|
||||||
|
.addAttributesExtractor(CodeAttributesExtractor.create(codedAttributesGetter));
|
||||||
|
if (configProperties.getBoolean(
|
||||||
|
"otel.instrumentation.spring-scheduling.experimental-span-attributes", false)) {
|
||||||
|
builder.addAttributesExtractor(
|
||||||
|
AttributesExtractor.constant(AttributeKey.stringKey("job.system"), "spring_scheduling"));
|
||||||
|
}
|
||||||
|
instrumenter = builder.buildInstrumenter();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Pointcut(
|
||||||
|
"@annotation(org.springframework.scheduling.annotation.Scheduled)"
|
||||||
|
+ "|| @annotation(org.springframework.scheduling.annotation.Schedules)")
|
||||||
|
public void pointcut() {
|
||||||
|
// ignored
|
||||||
|
}
|
||||||
|
|
||||||
|
@Around("pointcut()")
|
||||||
|
public Object execution(ProceedingJoinPoint joinPoint) throws Throwable {
|
||||||
|
Context parent = Context.current();
|
||||||
|
ClassAndMethod request =
|
||||||
|
ClassAndMethod.create(
|
||||||
|
AopProxyUtils.ultimateTargetClass(joinPoint.getTarget()),
|
||||||
|
((MethodSignature) joinPoint.getSignature()).getMethod().getName());
|
||||||
|
if (!instrumenter.shouldStart(parent, request)) {
|
||||||
|
return joinPoint.proceed();
|
||||||
|
}
|
||||||
|
Context context = instrumenter.start(parent, request);
|
||||||
|
try (Scope ignored = context.makeCurrent()) {
|
||||||
|
Object object = joinPoint.proceed();
|
||||||
|
instrumenter.end(context, request, object, null);
|
||||||
|
return object;
|
||||||
|
} catch (Throwable t) {
|
||||||
|
instrumenter.end(context, request, null, t);
|
||||||
|
throw t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
/*
|
||||||
|
* Copyright The OpenTelemetry Authors
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.scheduling;
|
||||||
|
|
||||||
|
import io.opentelemetry.api.OpenTelemetry;
|
||||||
|
import io.opentelemetry.instrumentation.spring.autoconfigure.internal.ConditionalOnEnabledInstrumentation;
|
||||||
|
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
|
||||||
|
import org.aspectj.lang.annotation.Aspect;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.scheduling.annotation.Scheduled;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configures an aspect for tracing.
|
||||||
|
*
|
||||||
|
* <p>This class is internal and is hence not for public use. Its APIs are unstable and can change
|
||||||
|
* at any time.
|
||||||
|
*/
|
||||||
|
@ConditionalOnBean(OpenTelemetry.class)
|
||||||
|
@ConditionalOnEnabledInstrumentation(module = "spring-scheduling")
|
||||||
|
@ConditionalOnClass({Scheduled.class, Aspect.class})
|
||||||
|
@Configuration
|
||||||
|
class SpringSchedulingInstrumentationAutoConfiguration {
|
||||||
|
@Bean
|
||||||
|
SpringSchedulingInstrumentationAspect springSchedulingInstrumentationAspect(
|
||||||
|
OpenTelemetry openTelemetry, ConfigProperties configProperties) {
|
||||||
|
return new SpringSchedulingInstrumentationAspect(openTelemetry, configProperties);
|
||||||
|
}
|
||||||
|
}
|
|
@ -19,6 +19,10 @@ class OpenTelemetryAnnotationsRuntimeHints implements RuntimeHintsRegistrar {
|
||||||
.registerType(
|
.registerType(
|
||||||
TypeReference.of(
|
TypeReference.of(
|
||||||
"io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.annotations.InstrumentationWithSpanAspect"),
|
"io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.annotations.InstrumentationWithSpanAspect"),
|
||||||
|
hint -> hint.withMembers(MemberCategory.INVOKE_PUBLIC_METHODS))
|
||||||
|
.registerType(
|
||||||
|
TypeReference.of(
|
||||||
|
"io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.scheduling.SpringSchedulingInstrumentationAspect"),
|
||||||
hint -> hint.withMembers(MemberCategory.INVOKE_PUBLIC_METHODS));
|
hint -> hint.withMembers(MemberCategory.INVOKE_PUBLIC_METHODS));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,8 @@ io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.m
|
||||||
io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.r2dbc.R2dbcInstrumentationAutoConfiguration,\
|
io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.r2dbc.R2dbcInstrumentationAutoConfiguration,\
|
||||||
io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.web.SpringWebInstrumentationAutoConfiguration,\
|
io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.web.SpringWebInstrumentationAutoConfiguration,\
|
||||||
io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.webflux.SpringWebfluxInstrumentationAutoConfiguration,\
|
io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.webflux.SpringWebfluxInstrumentationAutoConfiguration,\
|
||||||
io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.webmvc.SpringWebMvc5InstrumentationAutoConfiguration
|
io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.webmvc.SpringWebMvc5InstrumentationAutoConfiguration,\
|
||||||
|
io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.scheduling.SpringSchedulingInstrumentationAutoConfiguration
|
||||||
|
|
||||||
org.springframework.context.ApplicationListener=\
|
org.springframework.context.ApplicationListener=\
|
||||||
io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.logging.LogbackAppenderApplicationListener
|
io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.logging.LogbackAppenderApplicationListener
|
||||||
|
|
|
@ -10,3 +10,4 @@ io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.w
|
||||||
io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.webflux.SpringWebfluxInstrumentationAutoConfiguration
|
io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.webflux.SpringWebfluxInstrumentationAutoConfiguration
|
||||||
io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.web.RestClientInstrumentationAutoConfiguration
|
io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.web.RestClientInstrumentationAutoConfiguration
|
||||||
io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.webmvc.SpringWebMvc6InstrumentationAutoConfiguration
|
io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.webmvc.SpringWebMvc6InstrumentationAutoConfiguration
|
||||||
|
io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.scheduling.SpringSchedulingInstrumentationAutoConfiguration
|
||||||
|
|
|
@ -0,0 +1,210 @@
|
||||||
|
/*
|
||||||
|
* Copyright The OpenTelemetry Authors
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.scheduling;
|
||||||
|
|
||||||
|
import static io.opentelemetry.api.trace.SpanKind.INTERNAL;
|
||||||
|
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo;
|
||||||
|
import static io.opentelemetry.sdk.testing.assertj.TracesAssert.assertThat;
|
||||||
|
import static io.opentelemetry.semconv.incubating.CodeIncubatingAttributes.CODE_FUNCTION;
|
||||||
|
import static io.opentelemetry.semconv.incubating.CodeIncubatingAttributes.CODE_NAMESPACE;
|
||||||
|
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||||
|
|
||||||
|
import io.opentelemetry.api.OpenTelemetry;
|
||||||
|
import io.opentelemetry.api.trace.Span;
|
||||||
|
import io.opentelemetry.api.trace.Tracer;
|
||||||
|
import io.opentelemetry.context.Context;
|
||||||
|
import io.opentelemetry.context.Scope;
|
||||||
|
import io.opentelemetry.instrumentation.testing.junit.LibraryInstrumentationExtension;
|
||||||
|
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
|
||||||
|
import io.opentelemetry.sdk.autoconfigure.spi.internal.DefaultConfigProperties;
|
||||||
|
import io.opentelemetry.sdk.trace.data.SpanData;
|
||||||
|
import io.opentelemetry.sdk.trace.data.StatusData;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.DisplayName;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||||
|
import org.springframework.aop.aspectj.annotation.AspectJProxyFactory;
|
||||||
|
import org.springframework.scheduling.annotation.Scheduled;
|
||||||
|
import org.springframework.scheduling.annotation.Schedules;
|
||||||
|
|
||||||
|
class SchedulingInstrumentationAspectTest {
|
||||||
|
|
||||||
|
@RegisterExtension
|
||||||
|
static final LibraryInstrumentationExtension testing = LibraryInstrumentationExtension.create();
|
||||||
|
|
||||||
|
private InstrumentationSchedulingTester schedulingTester;
|
||||||
|
private String unproxiedTesterSimpleClassName;
|
||||||
|
private String unproxiedTesterClassName;
|
||||||
|
|
||||||
|
SpringSchedulingInstrumentationAspect newAspect(
|
||||||
|
OpenTelemetry openTelemetry, ConfigProperties configProperties) {
|
||||||
|
return new SpringSchedulingInstrumentationAspect(openTelemetry, configProperties);
|
||||||
|
}
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void setup() {
|
||||||
|
InstrumentationSchedulingTester unproxiedTester =
|
||||||
|
new InstrumentationSchedulingTester(testing.getOpenTelemetry());
|
||||||
|
unproxiedTesterSimpleClassName = unproxiedTester.getClass().getSimpleName();
|
||||||
|
unproxiedTesterClassName = unproxiedTester.getClass().getName();
|
||||||
|
|
||||||
|
AspectJProxyFactory factory = new AspectJProxyFactory();
|
||||||
|
factory.setTarget(unproxiedTester);
|
||||||
|
|
||||||
|
SpringSchedulingInstrumentationAspect aspect =
|
||||||
|
newAspect(
|
||||||
|
testing.getOpenTelemetry(),
|
||||||
|
DefaultConfigProperties.createFromMap(Collections.emptyMap()));
|
||||||
|
factory.addAspect(aspect);
|
||||||
|
|
||||||
|
schedulingTester = factory.getProxy();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("when method is annotated with @Scheduled should start a new span.")
|
||||||
|
void scheduled() {
|
||||||
|
// when
|
||||||
|
schedulingTester.testScheduled();
|
||||||
|
|
||||||
|
// then
|
||||||
|
List<List<SpanData>> traces = testing.waitForTraces(1);
|
||||||
|
assertThat(traces)
|
||||||
|
.hasTracesSatisfyingExactly(
|
||||||
|
trace ->
|
||||||
|
trace.hasSpansSatisfyingExactly(
|
||||||
|
span ->
|
||||||
|
span.hasName(unproxiedTesterSimpleClassName + ".testScheduled")
|
||||||
|
.hasKind(INTERNAL)
|
||||||
|
.hasAttributesSatisfyingExactly(
|
||||||
|
equalTo(CODE_NAMESPACE, unproxiedTesterClassName),
|
||||||
|
equalTo(CODE_FUNCTION, "testScheduled"))));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("when method is annotated with multiple @Scheduled should start a new span.")
|
||||||
|
void multiScheduled() {
|
||||||
|
// when
|
||||||
|
schedulingTester.testMultiScheduled();
|
||||||
|
|
||||||
|
// then
|
||||||
|
List<List<SpanData>> traces = testing.waitForTraces(1);
|
||||||
|
assertThat(traces)
|
||||||
|
.hasTracesSatisfyingExactly(
|
||||||
|
trace ->
|
||||||
|
trace.hasSpansSatisfyingExactly(
|
||||||
|
span ->
|
||||||
|
span.hasName(unproxiedTesterSimpleClassName + ".testMultiScheduled")
|
||||||
|
.hasKind(INTERNAL)
|
||||||
|
.hasAttributesSatisfyingExactly(
|
||||||
|
equalTo(CODE_NAMESPACE, unproxiedTesterClassName),
|
||||||
|
equalTo(CODE_FUNCTION, "testMultiScheduled"))));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("when method is annotated with @Schedules should start a new span.")
|
||||||
|
void schedules() {
|
||||||
|
// when
|
||||||
|
schedulingTester.testSchedules();
|
||||||
|
|
||||||
|
// then
|
||||||
|
List<List<SpanData>> traces = testing.waitForTraces(1);
|
||||||
|
assertThat(traces)
|
||||||
|
.hasTracesSatisfyingExactly(
|
||||||
|
trace ->
|
||||||
|
trace.hasSpansSatisfyingExactly(
|
||||||
|
span ->
|
||||||
|
span.hasName(unproxiedTesterSimpleClassName + ".testSchedules")
|
||||||
|
.hasKind(INTERNAL)
|
||||||
|
.hasAttributesSatisfyingExactly(
|
||||||
|
equalTo(CODE_NAMESPACE, unproxiedTesterClassName),
|
||||||
|
equalTo(CODE_FUNCTION, "testSchedules"))));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName(
|
||||||
|
"when method is annotated with @Scheduled and it starts nested span, spans should be nested.")
|
||||||
|
void nestedSpanInScheduled() {
|
||||||
|
// when
|
||||||
|
schedulingTester.testNestedSpan();
|
||||||
|
|
||||||
|
// then
|
||||||
|
List<List<SpanData>> traces = testing.waitForTraces(1);
|
||||||
|
assertThat(traces)
|
||||||
|
.hasTracesSatisfyingExactly(
|
||||||
|
trace ->
|
||||||
|
trace.hasSpansSatisfyingExactly(
|
||||||
|
span ->
|
||||||
|
span.hasName(unproxiedTesterSimpleClassName + ".testNestedSpan")
|
||||||
|
.hasKind(INTERNAL)
|
||||||
|
.hasAttributesSatisfyingExactly(
|
||||||
|
equalTo(CODE_NAMESPACE, unproxiedTesterClassName),
|
||||||
|
equalTo(CODE_FUNCTION, "testNestedSpan")),
|
||||||
|
nestedSpan ->
|
||||||
|
nestedSpan.hasParent(trace.getSpan(0)).hasKind(INTERNAL).hasName("test")));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName(
|
||||||
|
"when method is annotated with @Scheduled AND an exception is thrown span should record the exception")
|
||||||
|
void scheduledError() {
|
||||||
|
assertThatThrownBy(() -> schedulingTester.testScheduledWithException())
|
||||||
|
.isInstanceOf(Exception.class);
|
||||||
|
|
||||||
|
List<List<SpanData>> traces = testing.waitForTraces(1);
|
||||||
|
assertThat(traces)
|
||||||
|
.hasTracesSatisfyingExactly(
|
||||||
|
trace ->
|
||||||
|
trace.hasSpansSatisfyingExactly(
|
||||||
|
span ->
|
||||||
|
span.hasName(unproxiedTesterSimpleClassName + ".testScheduledWithException")
|
||||||
|
.hasKind(INTERNAL)
|
||||||
|
.hasStatus(StatusData.error())
|
||||||
|
.hasAttributesSatisfyingExactly(
|
||||||
|
equalTo(CODE_NAMESPACE, unproxiedTesterClassName),
|
||||||
|
equalTo(CODE_FUNCTION, "testScheduledWithException"))));
|
||||||
|
}
|
||||||
|
|
||||||
|
static class InstrumentationSchedulingTester {
|
||||||
|
private final OpenTelemetry openTelemetry;
|
||||||
|
|
||||||
|
InstrumentationSchedulingTester(OpenTelemetry openTelemetry) {
|
||||||
|
this.openTelemetry = openTelemetry;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Scheduled(fixedRate = 1L)
|
||||||
|
public void testScheduled() {
|
||||||
|
// no-op
|
||||||
|
}
|
||||||
|
|
||||||
|
@Scheduled(fixedRate = 1L)
|
||||||
|
@Scheduled(fixedRate = 2L)
|
||||||
|
public void testMultiScheduled() {
|
||||||
|
// no-op
|
||||||
|
}
|
||||||
|
|
||||||
|
@Schedules({@Scheduled(fixedRate = 1L), @Scheduled(fixedRate = 2L)})
|
||||||
|
public void testSchedules() {
|
||||||
|
// no-op
|
||||||
|
}
|
||||||
|
|
||||||
|
@Scheduled(fixedRate = 1L)
|
||||||
|
public void testNestedSpan() {
|
||||||
|
Context current = Context.current();
|
||||||
|
Tracer tracer = openTelemetry.getTracer("test");
|
||||||
|
try (Scope ignored = current.makeCurrent()) {
|
||||||
|
Span span = tracer.spanBuilder("test").startSpan();
|
||||||
|
span.end();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Scheduled(fixedRate = 1L)
|
||||||
|
public void testScheduledWithException() {
|
||||||
|
throw new IllegalStateException("something went wrong");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,46 @@
|
||||||
|
/*
|
||||||
|
* Copyright The OpenTelemetry Authors
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.scheduling;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
import io.opentelemetry.api.OpenTelemetry;
|
||||||
|
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
|
||||||
|
import io.opentelemetry.sdk.autoconfigure.spi.internal.DefaultConfigProperties;
|
||||||
|
import java.util.Collections;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||||
|
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||||
|
|
||||||
|
class SchedulingInstrumentationAutoConfigurationTest {
|
||||||
|
private final ApplicationContextRunner runner =
|
||||||
|
new ApplicationContextRunner()
|
||||||
|
.withBean(OpenTelemetry.class, OpenTelemetry::noop)
|
||||||
|
.withBean(
|
||||||
|
ConfigProperties.class,
|
||||||
|
() -> DefaultConfigProperties.createFromMap(Collections.emptyMap()))
|
||||||
|
.withConfiguration(
|
||||||
|
AutoConfigurations.of(SpringSchedulingInstrumentationAutoConfiguration.class));
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void instrumentationEnabled() {
|
||||||
|
runner
|
||||||
|
.withPropertyValues("otel.instrumentation.spring-scheduling.enabled=true")
|
||||||
|
.run(
|
||||||
|
context ->
|
||||||
|
assertThat(context.containsBean("springSchedulingInstrumentationAspect")).isTrue());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void instrumentationDisabled() {
|
||||||
|
runner
|
||||||
|
.withPropertyValues("otel.instrumentation.spring-scheduling.enabled=false")
|
||||||
|
.run(
|
||||||
|
context ->
|
||||||
|
assertThat(context.containsBean("springSchedulingInstrumentationAspect"))
|
||||||
|
.isFalse());
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue