Skip to content

Respect Retry-After in OTLP HTTP senders#8633

Open
ADITYA-CODE-SOURCE wants to merge 1 commit into
open-telemetry:mainfrom
ADITYA-CODE-SOURCE:issue-8449-otlp-retry-after
Open

Respect Retry-After in OTLP HTTP senders#8633
ADITYA-CODE-SOURCE wants to merge 1 commit into
open-telemetry:mainfrom
ADITYA-CODE-SOURCE:issue-8449-otlp-retry-after

Conversation

@ADITYA-CODE-SOURCE

Copy link
Copy Markdown
Contributor

Summary:

  • honor OTLP/HTTP Retry-After headers in the OkHttp and JDK HTTP senders
  • support both delay-seconds and RFC1123 HTTP-date values, with existing exponential backoff as the fallback
  • add shared parser coverage plus sender and OTLP integration tests for seconds/date/malformed cases

Fixes #8449

Testing:

  • ./gradlew :exporters:common:test --tests "*RetryUtilTest"
  • ./gradlew :exporters:sender:okhttp:test --tests "*RetryInterceptorTest"
  • ./gradlew :exporters:sender:jdk:test --tests "*JdkHttpSenderTest"
  • ./gradlew :exporters:otlp:all:testOkHttpVersionLATEST --tests "OtlpHttp"
  • ./gradlew :exporters:otlp:all:testJdkHttpSender --tests "OtlpHttp"
  • ./gradlew :exporters:common:spotlessCheck :exporters:sender:okhttp:spotlessCheck :exporters:sender:jdk:spotlessCheck :exporters:otlp:testing-internal:spotlessCheck :exporters:otlp:all:spotlessCheck :exporters:otlp:all:checkstyleTestOkHttpVersionLATEST :exporters:otlp:all:checkstyleTestJdkHttpSender

@ADITYA-CODE-SOURCE
ADITYA-CODE-SOURCE requested a review from a team as a code owner July 17, 2026 04:21
@linux-foundation-easycla

linux-foundation-easycla Bot commented Jul 17, 2026

Copy link
Copy Markdown

CLA Signed
The committers listed above are authorized under a signed CLA.

  • ✅ login: ADITYA-CODE-SOURCE / name: Aditya Vishe (675f3c9)

@codecov

codecov Bot commented Jul 17, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 95.08197% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 91.64%. Comparing base (b86f040) to head (675f3c9).
⚠️ Report is 8 commits behind head on main.

Files with missing lines Patch % Lines
.../io/opentelemetry/exporter/internal/RetryUtil.java 86.66% 1 Missing and 1 partial ⚠️
...orter/sender/okhttp/internal/RetryInterceptor.java 93.33% 0 Missing and 1 partial ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##               main    #8633      +/-   ##
============================================
+ Coverage     91.60%   91.64%   +0.03%     
- Complexity    10343    10365      +22     
============================================
  Files          1013     1013              
  Lines         27352    27424      +72     
  Branches       3215     3222       +7     
============================================
+ Hits          25057    25133      +76     
+ Misses         1567     1559       -8     
- Partials        728      732       +4     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@ADITYA-CODE-SOURCE
ADITYA-CODE-SOURCE force-pushed the issue-8449-otlp-retry-after branch from 1249450 to 675f3c9 Compare July 18, 2026 13:26
@opentelemetry-pr-dashboard

opentelemetry-pr-dashboard Bot commented Jul 18, 2026

Copy link
Copy Markdown

Pull request dashboard status

Status last refreshed: 2026-07-25 03:14:14 UTC.

  • Waiting on: Author
  • Next step: Address or respond to 7 review feedback items:
    • Inline threads: 1, 2, 3, 4, 5, 6, 7
    • For each item, reply to move the discussion forward, e.g. link to the commit that addresses it, explain why no change is needed, or ask a follow-up question.

This automated status or its linked feedback items may be incorrect. If something looks wrong, please report it with the result you expected. If you believe this pull request is incorrectly routed as waiting on the author, comment /dashboard route:reviewers to route it from waiting on the author to waiting on reviewers. If the last refreshed time above predates your latest reply or push, the dashboard hasn't processed it yet.

retryDelayNanos = OptionalLong.empty();
try {
TimeUnit.NANOSECONDS.sleep(backoffNanos);
sleeper.sleep(backoffNanos);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can't blindly sleep for whatever time the server tells us. We need to clamp this to something like Math.min(backoffNanos, timeout-elapsed)

}

/** Returns whether the status code represents OTLP/HTTP throttling. */
public static boolean isOtlpHttpThrottleStatusCode(int statusCode) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this gates respecting Retry-After to only 429/503 status codes.

My read of the relevant section of the spec is that:

  • Servers should use 429 or 503 when overloaded, and may include Retry-After
  • Clients should honor Retry-After, so long as its a retryable status code.

* Returns the delay specified by a {@code Retry-After} header, or empty if the value is absent or
* malformed.
*/
public static OptionalLong retryAfterNanos(@Nullable String retryAfter) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unit test the edge cases of this, and keep the integration tests a higher level validation that Retry-After is being honored generally

}

@Test
void retryableThrottledError_retryAfterSeconds() {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we get away only with the coverage here and get rid of the JdkHttpSenderTest coverage?

Also, as mentioned in the other comment, if you unit test the retryAfterNanos method, you can reduce the coverage here to something more basic. I.e. the one positive case here + the malformedRetryAfterFallsBack negative case. Can delete retryAfterDate case since that would already be covered.

}

/** Constructs a new retrier with an optional server-provided retry delay override. */
public RetryInterceptor(

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Too many overloads for an internal class. Let's reduce to the just one or two.

}

// Visible for testing
JdkHttpSender(

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's get rid of this extra overload.


try {
Instant retryAfterInstant =
ZonedDateTime.parse(retryAfter, DateTimeFormatter.RFC_1123_DATE_TIME).toInstant();

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you evalutate what other otel languages are doing here and confirm we match?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

OTLP exporters should respect retry-after

2 participants