-
Notifications
You must be signed in to change notification settings - Fork 845
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add auto configuration for spring scheduling instrumentation using aop
- Loading branch information
Showing
8 changed files
with
425 additions
and
1 deletion.
There are no files selected for viewing
37 changes: 37 additions & 0 deletions
37
.../autoconfigure/internal/instrumentation/scheduling/InternalThreadAttributesExtractor.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
/* | ||
* Copyright The OpenTelemetry Authors | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.scheduling; | ||
|
||
import io.opentelemetry.api.common.AttributesBuilder; | ||
import io.opentelemetry.context.Context; | ||
import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor; | ||
import io.opentelemetry.semconv.incubating.ThreadIncubatingAttributes; | ||
import javax.annotation.Nullable; | ||
import org.springframework.lang.NonNull; | ||
|
||
/** Expose current thread to attributes. */ | ||
class InternalThreadAttributesExtractor<REQUEST, RESPONSE> | ||
implements AttributesExtractor<REQUEST, RESPONSE> { | ||
@Override | ||
public void onStart( | ||
@NonNull AttributesBuilder attributes, | ||
@NonNull Context parentContext, | ||
@NonNull REQUEST classAndMethod) { | ||
attributes | ||
.put(ThreadIncubatingAttributes.THREAD_ID, Thread.currentThread().getId()) | ||
.put(ThreadIncubatingAttributes.THREAD_NAME, Thread.currentThread().getName()); | ||
} | ||
|
||
@Override | ||
public void onEnd( | ||
@NonNull AttributesBuilder attributes, | ||
@NonNull Context context, | ||
@NonNull REQUEST classAndMethod, | ||
@Nullable RESPONSE o, | ||
@Nullable Throwable error) { | ||
// ignored | ||
} | ||
} |
91 changes: 91 additions & 0 deletions
91
...oconfigure/internal/instrumentation/scheduling/SpringSchedulingInstrumentationAspect.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
/* | ||
* 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)) | ||
.addAttributesExtractor(new InternalThreadAttributesExtractor<>()); | ||
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; | ||
} | ||
} | ||
} |
34 changes: 34 additions & 0 deletions
34
...internal/instrumentation/scheduling/SpringSchedulingInstrumentationAutoConfiguration.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.