-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Java agent insturmentation added for Failsafe 3.0 #15759
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
5706dc7
1fbe548
347fdbc
02c3c61
dafe3f5
5acf273
8f3e6fd
a36f1d5
9332768
c20d5be
b0a29f3
7095e91
c477ecd
e10b973
c1b4af6
9e7dd8e
47486f7
44e1f46
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| plugins { | ||
| id("otel.javaagent-instrumentation") | ||
| } | ||
|
|
||
| muzzle { | ||
| pass { | ||
| group.set("dev.failsafe") | ||
| module.set("failsafe") | ||
| versions.set("[3.0.0,)") | ||
| assertInverse.set(true) | ||
| } | ||
| } | ||
|
|
||
| dependencies { | ||
| library("dev.failsafe:failsafe:3.0.1") | ||
|
|
||
| implementation(project(":instrumentation:failsafe-3.0:library")) | ||
|
|
||
| testImplementation(project(":instrumentation:failsafe-3.0:testing")) | ||
| } | ||
|
|
||
| tasks { | ||
| withType<Test>().configureEach { | ||
| jvmArgs("-Dotel.instrumentation.failsafe.enabled=true") | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| /* | ||
| * Copyright The OpenTelemetry Authors | ||
| * SPDX-License-Identifier: Apache-2.0 | ||
| */ | ||
|
|
||
| package io.opentelemetry.javaagent.instrumentation.failsafe.v3_0; | ||
|
|
||
| import static java.util.Collections.singletonList; | ||
|
|
||
| import com.google.auto.service.AutoService; | ||
| import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule; | ||
| import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; | ||
| import io.opentelemetry.javaagent.extension.instrumentation.internal.ExperimentalInstrumentationModule; | ||
| import java.util.List; | ||
|
|
||
| @AutoService(InstrumentationModule.class) | ||
| public class FailsafeInstrumentationModule extends InstrumentationModule | ||
| implements ExperimentalInstrumentationModule { | ||
|
|
||
| public FailsafeInstrumentationModule() { | ||
| super("failsafe", "failsafe-3.0"); | ||
| } | ||
|
|
||
| @Override | ||
| public List<TypeInstrumentation> typeInstrumentations() { | ||
| return singletonList(new RetryPolicyInstrumentation()); | ||
| } | ||
|
|
||
| @Override | ||
| public boolean defaultEnabled() { | ||
| return false; | ||
| } | ||
|
|
||
| @Override | ||
| public boolean isIndyReady() { | ||
| return true; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,77 @@ | ||||||||||
| /* | ||||||||||
| * Copyright The OpenTelemetry Authors | ||||||||||
| * SPDX-License-Identifier: Apache-2.0 | ||||||||||
| */ | ||||||||||
|
|
||||||||||
| package io.opentelemetry.javaagent.instrumentation.failsafe.v3_0; | ||||||||||
|
|
||||||||||
| import static io.opentelemetry.instrumentation.failsafe.v3_0.internal.RetryPolicyEventListenerBuilders.buildInstrumentedFailureListener; | ||||||||||
| import static io.opentelemetry.instrumentation.failsafe.v3_0.internal.RetryPolicyEventListenerBuilders.buildInstrumentedSuccessListener; | ||||||||||
| import static net.bytebuddy.matcher.ElementMatchers.named; | ||||||||||
| import static net.bytebuddy.matcher.ElementMatchers.takesNoArguments; | ||||||||||
|
|
||||||||||
| import dev.failsafe.PolicyConfig; | ||||||||||
| import dev.failsafe.internal.RetryPolicyImpl; | ||||||||||
| import io.opentelemetry.api.GlobalOpenTelemetry; | ||||||||||
| import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; | ||||||||||
| import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer; | ||||||||||
| import java.lang.reflect.Field; | ||||||||||
| import javax.annotation.Nullable; | ||||||||||
| import net.bytebuddy.asm.Advice; | ||||||||||
| import net.bytebuddy.description.type.TypeDescription; | ||||||||||
| import net.bytebuddy.matcher.ElementMatcher; | ||||||||||
|
|
||||||||||
| public final class RetryPolicyInstrumentation implements TypeInstrumentation { | ||||||||||
| @Override | ||||||||||
| public ElementMatcher<TypeDescription> typeMatcher() { | ||||||||||
| return named("dev.failsafe.RetryPolicyBuilder"); | ||||||||||
| } | ||||||||||
|
|
||||||||||
| @Override | ||||||||||
| public void transform(TypeTransformer transformer) { | ||||||||||
| transformer.applyAdviceToMethod( | ||||||||||
| named("build").and(takesNoArguments()), this.getClass().getName() + "$BuildAdvice"); | ||||||||||
| } | ||||||||||
|
|
||||||||||
| public static final class BuildAdvice { | ||||||||||
| @Nullable public static final Field FAILURE_LISTENER_FIELD; | ||||||||||
| @Nullable public static final Field SUCCESS_LISTENER_FIELD; | ||||||||||
|
|
||||||||||
| static { | ||||||||||
| Field failureListenerField = null; | ||||||||||
| Field successListenerField = null; | ||||||||||
| try { | ||||||||||
| failureListenerField = PolicyConfig.class.getDeclaredField("failureListener"); | ||||||||||
| failureListenerField.setAccessible(true); | ||||||||||
|
|
||||||||||
| successListenerField = PolicyConfig.class.getDeclaredField("successListener"); | ||||||||||
| successListenerField.setAccessible(true); | ||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [Style] The caught exception is intentionally unused, so the preferred name is
Suggested change
|
||||||||||
| } catch (Exception e) { | ||||||||||
| // Ignored | ||||||||||
| } | ||||||||||
| FAILURE_LISTENER_FIELD = failureListenerField; | ||||||||||
| SUCCESS_LISTENER_FIELD = successListenerField; | ||||||||||
| } | ||||||||||
|
|
||||||||||
| @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) | ||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [Javaagent] Return-only exit advice should omit
Suggested change
|
||||||||||
| public static void onExit(@Advice.Return Object retryPolicyImpl) { | ||||||||||
| if (FAILURE_LISTENER_FIELD == null || SUCCESS_LISTENER_FIELD == null) { | ||||||||||
| return; | ||||||||||
| } | ||||||||||
|
|
||||||||||
| try { | ||||||||||
| RetryPolicyImpl<?> impl = (RetryPolicyImpl<?>) retryPolicyImpl; | ||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [Javaagent] This instrumentation mutates private fields of
|
||||||||||
| FAILURE_LISTENER_FIELD.set( | ||||||||||
| impl.getConfig(), | ||||||||||
| buildInstrumentedFailureListener( | ||||||||||
| GlobalOpenTelemetry.get(), impl.getConfig(), impl.toString())); | ||||||||||
| SUCCESS_LISTENER_FIELD.set( | ||||||||||
| impl.getConfig(), | ||||||||||
| buildInstrumentedSuccessListener( | ||||||||||
| GlobalOpenTelemetry.get(), impl.getConfig(), impl.toString())); | ||||||||||
|
Comment on lines
+67
to
+71
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [General] Using
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||||||||||
| } catch (IllegalAccessException ignored) { | ||||||||||
| // Ignored | ||||||||||
| } | ||||||||||
| } | ||||||||||
| } | ||||||||||
| } | ||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,46 @@ | ||
| /* | ||
| * Copyright The OpenTelemetry Authors | ||
| * SPDX-License-Identifier: Apache-2.0 | ||
| */ | ||
|
|
||
| package io.opentelemetry.javaagent.instrumentation.failsafe.v3_0; | ||
|
|
||
| import dev.failsafe.CircuitBreaker; | ||
| import dev.failsafe.RetryPolicy; | ||
| import io.opentelemetry.instrumentation.failsafe.AbstractFailsafeInstrumentationTest; | ||
| import io.opentelemetry.instrumentation.testing.junit.AgentInstrumentationExtension; | ||
| import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; | ||
| import org.junit.jupiter.api.Disabled; | ||
| import org.junit.jupiter.api.Test; | ||
| import org.junit.jupiter.api.extension.RegisterExtension; | ||
|
|
||
| class FailsafeInstrumentationTest extends AbstractFailsafeInstrumentationTest { | ||
| @RegisterExtension | ||
| static final InstrumentationExtension testing = AgentInstrumentationExtension.create(); | ||
|
|
||
| @Override | ||
| protected InstrumentationExtension testing() { | ||
| return testing; | ||
| } | ||
|
|
||
| @Override | ||
| protected CircuitBreaker<Object> configure(CircuitBreaker<Object> userCircuitBreaker) { | ||
| return userCircuitBreaker; | ||
| } | ||
|
|
||
| @Override | ||
| protected RetryPolicy<Object> configure(RetryPolicy<Object> userRetryPolicy) { | ||
| return userRetryPolicy; | ||
| } | ||
|
|
||
| @Override | ||
| @Disabled | ||
| public void captureCircuitBreakerMetrics() { | ||
| // TODO: Will be enabled once Java agent CircuitBreaker instrumentation is added. | ||
| } | ||
|
|
||
| @Test | ||
| void captureRetryPolicyMetrics() { | ||
| captureRetryPolicyMetrics(null); | ||
| } | ||
| } |
This file was deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we have a convention that instrumentations that don't follow any semantic conventions are disabled by default