Skip to content

Commit 84be10f

Browse files
CopilotnikhilNava
andcommitted
Move _parse_retry_after to exporters/utils.py as standalone parse_retry_after function
Co-authored-by: nikhilNava <211831449+nikhilNava@users.noreply.github.com>
1 parent 596cc6a commit 84be10f

2 files changed

Lines changed: 29 additions & 16 deletions

File tree

libraries/microsoft-agents-a365-observability-core/microsoft_agents_a365/observability/core/exporters/agent365_exporter.py

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
hex_span_id,
2424
hex_trace_id,
2525
kind_name,
26+
parse_retry_after,
2627
partition_by_identity,
2728
status_name,
2829
truncate_span,
@@ -162,21 +163,6 @@ def _truncate_text(text: str, max_length: int) -> str:
162163
return text[:max_length] + "..."
163164
return text
164165

165-
@staticmethod
166-
def _parse_retry_after(resp: requests.Response) -> float | None:
167-
"""Parse the Retry-After header from a response.
168-
169-
Returns:
170-
The number of seconds to wait, or None if the header is absent or invalid.
171-
"""
172-
retry_after = resp.headers.get("Retry-After")
173-
if retry_after is None:
174-
return None
175-
try:
176-
return float(retry_after)
177-
except (ValueError, TypeError):
178-
return None
179-
180166
def _post_with_retries(self, url: str, body: str, headers: dict[str, str]) -> bool:
181167
for attempt in range(DEFAULT_MAX_RETRIES + 1):
182168
try:
@@ -209,7 +195,7 @@ def _post_with_retries(self, url: str, body: str, headers: dict[str, str]) -> bo
209195
# Retry transient
210196
if resp.status_code in (408, 429) or 500 <= resp.status_code < 600:
211197
# Respect Retry-After header for 429 responses
212-
retry_after = self._parse_retry_after(resp)
198+
retry_after = parse_retry_after(resp.headers)
213199
if attempt < DEFAULT_MAX_RETRIES:
214200
if retry_after is not None:
215201
time.sleep(min(retry_after, 60.0))

libraries/microsoft-agents-a365-observability-core/microsoft_agents_a365/observability/core/exporters/utils.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
# Copyright (c) Microsoft Corporation.
22
# Licensed under the MIT License.
33

4+
from __future__ import annotations
5+
46
import json
57
import logging
68
import os
@@ -230,6 +232,31 @@ def build_export_url(
230232
return f"https://{endpoint}{endpoint_path}?api-version=1"
231233

232234

235+
def parse_retry_after(headers: dict[str, str]) -> float | None:
236+
"""Parse the ``Retry-After`` header value.
237+
238+
Only numeric (seconds) values are supported. HTTP-date values
239+
(e.g. ``Wed, 21 Oct 2025 07:28:00 GMT``) are intentionally ignored
240+
and treated as absent, falling back to exponential backoff.
241+
242+
Args:
243+
headers: Response headers mapping.
244+
245+
Returns:
246+
The number of seconds to wait, or ``None`` if the header is
247+
absent, non-numeric, or otherwise invalid.
248+
"""
249+
retry_after = headers.get("Retry-After")
250+
if retry_after is None:
251+
return None
252+
try:
253+
return float(retry_after)
254+
except (ValueError, TypeError):
255+
# Intentionally ignore HTTP-date formatted Retry-After values;
256+
# callers should fall back to exponential backoff.
257+
return None
258+
259+
233260
def is_agent365_exporter_enabled() -> bool:
234261
"""Check if Agent 365 exporter is enabled."""
235262
# Check environment variable

0 commit comments

Comments
 (0)