Skip to content

oss_13_http_exporter_retry_after_backoff_cap#27

Open
ocelotl wants to merge 2 commits into
mainfrom
oss_13_http_exporter_retry_after_backoff_cap
Open

oss_13_http_exporter_retry_after_backoff_cap#27
ocelotl wants to merge 2 commits into
mainfrom
oss_13_http_exporter_retry_after_backoff_cap

Conversation

@ocelotl

@ocelotl ocelotl commented Jul 22, 2026

Copy link
Copy Markdown
Owner

Closes #18

OTLP HTTP exporter retry conformance (Linear OSS-13, findings X2/X3): make HTTP 429 retryable, parse and honor Retry-After (delay-seconds + HTTP-date), and clamp exponential backoff to a 32s ceiling across the three HTTP exporters and the gRPC exporter.

Validation: scope contained to the OTLP http+grpc exporter packages + changelog; HTTP suite 73 passed, gRPC suite 67 passed.

Linear issue: https://linear.app/dash0/issue/OSS-13/x2-x3-http-exporter-honor-429retry-after-add-max-backoff-cap

The OTLP HTTP exporters (trace, metric, logs) now treat HTTP 429 (Too Many
Requests) as retryable and parse the Retry-After response header, honoring both
the delay-seconds and HTTP-date forms as the delay before the next retry, as
required by the OTLP specification.

The exponential backoff in the HTTP exporters, as well as the gRPC exporter,
is now clamped to a maximum interval so it cannot grow without bound.
@ocelotl

ocelotl commented Jul 22, 2026

Copy link
Copy Markdown
Owner Author

🔒 Internal (dash0) — not for upstream.

@ocelotl

ocelotl commented Jul 22, 2026

Copy link
Copy Markdown
Owner Author

📣 Public-facing draft — to be used for the upstream PR in open-telemetry/opentelemetry-python. No internal references; copy verbatim.

Title: Retry OTLP HTTP exports on 429, honor Retry-After, and cap backoff

What changed

  • 429 is now retryable (HTTP): _is_retryable() in opentelemetry/exporter/otlp/proto/http/_common/__init__.py returns True for 429, in addition to 408 and 5xx.
  • Retry-After is honored (HTTP): a new _parse_retry_after_header() parses both supported forms — delay-seconds (Retry-After: 120) and HTTP-date (Retry-After: Wed, 21 Oct 2015 07:28:00 GMT). A past HTTP-date yields 0; a missing/malformed header yields None. When present, its value overrides the computed backoff as the next-retry delay in the trace, metric, and log HTTP exporters.
  • Backoff is capped: a _MAX_BACKOFF (32s) ceiling is applied via min(2**retry_num * random.uniform(0.8, 1.2), _MAX_BACKOFF) in the three HTTP exporters and in the gRPC exporter.

Why

The OTLP exporter specification requires retrying on 429 and honoring Retry-After, and both Go and Java cap their backoff. This brings the Python HTTP exporters into conformance and bounds retry delays.

Spec compliance

  • 429 retryable: matches the spec and the existing gRPC behavior.
  • Retry-After covers both RFC 9110 forms, matching Go/Java.
  • Backoff clamp matches Go/Java.

How tested

New unit tests: 429 triggers a retry; Retry-After (seconds and HTTP-date) is used as the delay; backoff is clamped at the cap; plus direct tests of _is_retryable and _parse_retry_after_header (missing / seconds / HTTP-date / past-date / invalid), across the trace, metric, and log HTTP test modules. Full OTLP HTTP suite passes (73); full gRPC suite passes (67).

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.

oss_13_http_exporter_retry_after_backoff_cap

1 participant