-
Notifications
You must be signed in to change notification settings - Fork 891
Retry on configurable exception #6991
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
Changes from 8 commits
a45ebdd
9296a67
15cf507
13c3b3c
aac988d
f3d04f4
25bbf4c
a367900
596a8bd
e029f61
993385f
d91412b
20e8aaa
ef509b8
8913b52
9fb06b9
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 |
---|---|---|
@@ -1,2 +1,13 @@ | ||
Comparing source compatibility of opentelemetry-sdk-common-1.47.0-SNAPSHOT.jar against opentelemetry-sdk-common-1.46.0.jar | ||
No changes. | ||
+++ NEW CLASS: PUBLIC(+) io.opentelemetry.sdk.common.export.DefaultRetryExceptionPredicate (not serializable) | ||
+++ CLASS FILE FORMAT VERSION: 52.0 <- n.a. | ||
+++ NEW INTERFACE: java.util.function.Predicate | ||
+++ NEW SUPERCLASS: java.lang.Object | ||
+++ NEW CONSTRUCTOR: PUBLIC(+) DefaultRetryExceptionPredicate() | ||
+++ NEW METHOD: PUBLIC(+) boolean test(java.io.IOException) | ||
**** MODIFIED CLASS: PUBLIC ABSTRACT io.opentelemetry.sdk.common.export.RetryPolicy (not serializable) | ||
=== CLASS FILE FORMAT VERSION: 52.0 <- 52.0 | ||
+++* NEW METHOD: PUBLIC(+) ABSTRACT(+) java.util.function.Predicate<java.io.IOException> getRetryExceptionPredicate() | ||
**** MODIFIED CLASS: PUBLIC ABSTRACT STATIC io.opentelemetry.sdk.common.export.RetryPolicy$RetryPolicyBuilder (not serializable) | ||
=== CLASS FILE FORMAT VERSION: 52.0 <- 52.0 | ||
+++* NEW METHOD: PUBLIC(+) ABSTRACT(+) io.opentelemetry.sdk.common.export.RetryPolicy$RetryPolicyBuilder setRetryExceptionPredicate(java.util.function.Predicate<java.io.IOException>) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
/* | ||
* Copyright The OpenTelemetry Authors | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package io.opentelemetry.sdk.common.export; | ||
|
||
import java.io.IOException; | ||
import java.net.ConnectException; | ||
import java.net.SocketTimeoutException; | ||
import java.util.Locale; | ||
import java.util.function.Predicate; | ||
|
||
public class DefaultRetryExceptionPredicate implements Predicate<IOException> { | ||
@Override | ||
public boolean test(IOException e) { | ||
if (e instanceof SocketTimeoutException) { | ||
String message = e.getMessage(); | ||
// Connect timeouts can produce SocketTimeoutExceptions with no message, or with "connect | ||
// timed out", or timeout | ||
if (message == null) { | ||
return true; | ||
} | ||
message = message.toLowerCase(Locale.ROOT); | ||
return message.contains("connect timed out") || message.contains("timeout"); | ||
} else if (e instanceof ConnectException) { | ||
// Exceptions resemble: java.net.ConnectException: Failed to connect to | ||
// localhost/[0:0:0:0:0:0:0:1]:62611 | ||
return true; | ||
} | ||
return false; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
@@ -8,7 +8,9 @@ | |||||||||
import static io.opentelemetry.api.internal.Utils.checkArgument; | ||||||||||
|
||||||||||
import com.google.auto.value.AutoValue; | ||||||||||
import java.io.IOException; | ||||||||||
import java.time.Duration; | ||||||||||
import java.util.function.Predicate; | ||||||||||
|
||||||||||
/** | ||||||||||
* Configuration for exporter exponential retry policy. | ||||||||||
|
@@ -28,6 +30,9 @@ public abstract class RetryPolicy { | |||||||||
|
||||||||||
private static final double DEFAULT_BACKOFF_MULTIPLIER = 1.5; | ||||||||||
|
||||||||||
private static final Predicate<IOException> DEFAULT_RETRY_PREDICATE = | ||||||||||
new DefaultRetryExceptionPredicate(); | ||||||||||
|
||||||||||
private static final RetryPolicy DEFAULT = RetryPolicy.builder().build(); | ||||||||||
|
||||||||||
RetryPolicy() {} | ||||||||||
|
@@ -43,7 +48,8 @@ public static RetryPolicyBuilder builder() { | |||||||||
.setMaxAttempts(DEFAULT_MAX_ATTEMPTS) | ||||||||||
.setInitialBackoff(Duration.ofSeconds(DEFAULT_INITIAL_BACKOFF_SECONDS)) | ||||||||||
.setMaxBackoff(Duration.ofSeconds(DEFAULT_MAX_BACKOFF_SECONDS)) | ||||||||||
.setBackoffMultiplier(DEFAULT_BACKOFF_MULTIPLIER); | ||||||||||
.setBackoffMultiplier(DEFAULT_BACKOFF_MULTIPLIER) | ||||||||||
.setRetryExceptionPredicate(DEFAULT_RETRY_PREDICATE); | ||||||||||
} | ||||||||||
|
||||||||||
/** | ||||||||||
|
@@ -66,6 +72,9 @@ public static RetryPolicyBuilder builder() { | |||||||||
/** Returns the backoff multiplier. */ | ||||||||||
public abstract double getBackoffMultiplier(); | ||||||||||
|
||||||||||
/** Returns the predicate if exception is retryable. */ | ||||||||||
public abstract Predicate<IOException> getRetryExceptionPredicate(); | ||||||||||
|
||||||||||
/** Builder for {@link RetryPolicy}. */ | ||||||||||
@AutoValue.Builder | ||||||||||
public abstract static class RetryPolicyBuilder { | ||||||||||
|
@@ -96,6 +105,13 @@ public abstract static class RetryPolicyBuilder { | |||||||||
*/ | ||||||||||
public abstract RetryPolicyBuilder setBackoffMultiplier(double backoffMultiplier); | ||||||||||
|
||||||||||
/** | ||||||||||
* Set the predicate to determine if retry should happen based on exception. No retry by | ||||||||||
* default. | ||||||||||
*/ | ||||||||||
public abstract RetryPolicyBuilder setRetryExceptionPredicate( | ||||||||||
Predicate<IOException> retryExceptionPredicate); | ||||||||||
Comment on lines
+110
to
+111
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. did you consider a customizer instead, to allow choice of either replacing or enhancing the default predicate? I realize it's not the friendliest API, but we've found the pattern really useful in AutoConfigurationCustomizer
Suggested change
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. and later use something like this
it depends how many users will want to extend it. I started the PR quickly with a thought that I need to extend rertry policy, but after some time I realized if a user wants to change the default policy it's ok just to override. but pls tell me if you think it's nice to have the enhance option for it and I will cover it in this PR and next PR. 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. The advantage of a predicate customizer is that you can do things like:
If you're just wholesale overwriting the default predicate, you don't get anything from having a customizer:
This benefit is somewhat diminished if we make the default retry predicates accessible as part of our stable API (related to #6970), in which case, the
This is the key bit to me. I'd say that API ergonomics feel really foreign to someone who hasn't written a 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.
good point |
||||||||||
|
||||||||||
abstract RetryPolicy autoBuild(); | ||||||||||
|
||||||||||
/** Build and return a {@link RetryPolicy} with the values of this builder. */ | ||||||||||
|
Uh oh!
There was an error while loading. Please reload this page.