Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
abf69ee
Add HTTPXWrapper backed by httpx2 behind use_httpx flag
mwdd146980 May 29, 2026
a658ffd
Address Round 1 review findings
mwdd146980 Jun 4, 2026
978c64d
Tighten comments from human review
mwdd146980 Jun 4, 2026
559bd70
Use httpx2 directly instead of aliasing as httpx
mwdd146980 Jun 4, 2026
2caf190
Rename to httpx2
mwdd146980 Jun 4, 2026
cf7853d
Rename HTTPXWrapper symbols to HTTPX2Wrapper
mwdd146980 Jun 4, 2026
25fc456
Round 2 finding #3: move test_stream_connection_lines to OM scraper t…
mwdd146980 Jun 4, 2026
88c5cb8
Round 2 finding #7: drop unreachable __del__ AttributeError
mwdd146980 Jun 4, 2026
19afdec
Round 2 finding #4: drop dead DEFAULT_REMAPPED_FIELDS constant
mwdd146980 Jun 4, 2026
14eda49
Round 2 finding #9: simplify lifecycle import-failure test
mwdd146980 Jun 4, 2026
e1fefec
Round 2 finding #8: assert stream-kwarg drop log via caplog
mwdd146980 Jun 4, 2026
0a650ea
Round 2 finding #5: extract _build_http_client helper
mwdd146980 Jun 4, 2026
b7da55f
Round 2 finding #10: case-fold headers/extra_headers merge
mwdd146980 Jun 4, 2026
eb550b7
Round 2 finding #6: close response on adapter wrap failure
mwdd146980 Jun 4, 2026
b8eb171
Round 2 finding #1: map httpx2 exceptions in iter_lines/iter_content
mwdd146980 Jun 4, 2026
3e2c413
Round 3 fix #4: tighten ImportError assertion to exc.value.name
mwdd146980 Jun 5, 2026
dbadf00
Round 3 fix #2: iter_lines bytes-through fidelity
mwdd146980 Jun 5, 2026
9465553
Round 3 fix #3: derive passthrough from REQUEST_KWARGS
mwdd146980 Jun 5, 2026
2894e7e
Round 3 fix #1: timeout=None guard + scalar _make_timeout consistency
mwdd146980 Jun 5, 2026
d6429ff
Round 4 fix #1: map mid-stream httpx2 errors to HTTPConnectionError
mwdd146980 Jun 5, 2026
d6c83a0
Round 4 fix #4: document init header dict-shape parity with RequestsW…
mwdd146980 Jun 5, 2026
0961d59
Round 4 fix #3: add encoding/url/cookies/elapsed to HTTPResponseProtocol
mwdd146980 Jun 5, 2026
16d619d
Round 4 fix #2: replace bytes accumulator with bytearray in iter_lines
mwdd146980 Jun 5, 2026
e6b797b
Round 5 finding #5: tighten HTTPResponseProtocol.cookies to Mapping[s…
mwdd146980 Jun 5, 2026
8897f20
Round 5 finding #1: collapse _map_httpx2_exception branches via httpx…
mwdd146980 Jun 5, 2026
4a77e98
Round 5 finding #2: lock in iter_lines decode CRLF parity test
mwdd146980 Jun 5, 2026
3926cf1
Round 5 finding #4: lock in headers={} benign no-op behavior
mwdd146980 Jun 5, 2026
a6e0763
Round 5 finding #3: document options['headers'] mirror constraint
mwdd146980 Jun 5, 2026
d14b180
Round 5 finding #6: use getattr guard in test_lifecycle teardown
mwdd146980 Jun 5, 2026
56d9f7b
Round 5 finding #7: rename misleading iter_lines bytes-path test
mwdd146980 Jun 5, 2026
cf4980f
Round 5 finding #8: drop tautological protocol attrs test
mwdd146980 Jun 5, 2026
e1b5f28
Round 6 finding #1: collapse follow_redirects routing
mwdd146980 Jun 5, 2026
e0cb6ad
Round 6 finding #2: assert request kwargs invariant at import
mwdd146980 Jun 5, 2026
e42dd4f
Round 7 finding #1: http-response-protocol-encoding-setter
mwdd146980 Jun 5, 2026
6520a52
Round 7 finding #2: follow-redirects-positive-test-coverage
mwdd146980 Jun 5, 2026
3af6015
Round 8 finding #1: wrap-content-text-json-exceptions
mwdd146980 Jun 7, 2026
03f8345
Round 8 finding #4: parametrize-warning-path-tests
mwdd146980 Jun 7, 2026
bf93607
Map self.options['headers'] mutations to httpx2 requests
mwdd146980 Jun 8, 2026
5466116
Improve HTTPX2Wrapper TypeError with per-kwarg remediation hints
mwdd146980 Jun 8, 2026
a165f14
Merge branch 'mwdd146980/codex-finding-2-kwargs' into mwdd146980/phas…
mwdd146980 Jun 8, 2026
3eb1fd0
Tighten test_stream_kwarg_still_silently_dropped to assert response, …
mwdd146980 Jun 8, 2026
78b106c
Add allow_redirects hint to UNKNOWN_KWARG_HINTS
mwdd146980 Jun 8, 2026
476e2d5
Drop dead _client.headers writes from set_header
mwdd146980 Jun 8, 2026
0fa6415
Merge round10 finding 1: allow_redirects hint
mwdd146980 Jun 8, 2026
5f33a4e
Merge round10 finding 2: set_header cleanup
mwdd146980 Jun 8, 2026
ce35d7b
Accept per-request auth kwarg in HTTPX2Wrapper
mwdd146980 Jun 9, 2026
444d32f
Merge branch 'mwdd146980/httpx-migration-base' into mwdd146980/phase2…
mwdd146980 Jun 9, 2026
e54c89d
Type-hint _build_http_client instance parameter
mwdd146980 Jun 17, 2026
5d71fa6
Document SSL folds into HTTPConnectionError in _map_httpx2_exception
mwdd146980 Jun 17, 2026
5d2f97b
Merge branch 'mwdd146980/httpx-migration-base' into mwdd146980/phase2…
mwdd146980 Jun 24, 2026
9e932e7
Merge branch 'mwdd146980/httpx-migration-base' into mwdd146980/phase2…
mwdd146980 Jun 24, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion datadog_checks_base/changelog.d/22676.added
Original file line number Diff line number Diff line change
@@ -1 +1 @@
Add library-agnostic HTTP mocks/proto/exceptions and migrate intg tests.
Add library-agnostic HTTP mocks/proto/exceptions and migrate intg tests. Add ``HTTPX2Wrapper``, an httpx2-backed HTTP client opt-in via the ``use_httpx2`` instance config flag. The default remains the existing requests-based client.
15 changes: 11 additions & 4 deletions datadog_checks_base/datadog_checks/base/checks/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -400,6 +400,16 @@ def _get_metric_limit(self, instance=None):

return limit

def _build_http_client(self, instance: dict[str, Any]) -> HTTPClientProtocol:
if is_affirmative(instance.get('use_httpx2', False)):
from datadog_checks.base.utils.httpx2 import HTTPX2Wrapper

return HTTPX2Wrapper(instance, self.init_config, self.HTTP_CONFIG_REMAPPER, self.log)
# See Performance Optimizations in this package's README.md.
from datadog_checks.base.utils.http import RequestsWrapper

return RequestsWrapper(instance, self.init_config, self.HTTP_CONFIG_REMAPPER, self.log)

@property
def http(self) -> HTTPClientProtocol:
"""
Expand All @@ -408,10 +418,7 @@ def http(self) -> HTTPClientProtocol:
Only new checks or checks on Agent 6.13+ can and should use this for HTTP requests.
"""
if not hasattr(self, '_http'):
# See Performance Optimizations in this package's README.md.
from datadog_checks.base.utils.http import RequestsWrapper

self._http = RequestsWrapper(self.instance or {}, self.init_config, self.HTTP_CONFIG_REMAPPER, self.log)
self._http = self._build_http_client(self.instance or {})

return self._http

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
from prometheus_client import Metric
from prometheus_client.openmetrics.parser import text_fd_to_metric_families as parse_openmetrics
from prometheus_client.parser import text_fd_to_metric_families as parse_prometheus
from requests.exceptions import ConnectionError
from requests.exceptions import ConnectionError as RequestsConnectionError

from datadog_checks.base.agent import datadog_agent
from datadog_checks.base.checks.openmetrics.v2.first_scrape_handler import first_scrape_handler
Expand All @@ -23,6 +23,7 @@
from datadog_checks.base.constants import ServiceCheck
from datadog_checks.base.errors import ConfigurationError
from datadog_checks.base.utils.functions import no_op, return_true
from datadog_checks.base.utils.http_exceptions import HTTPConnectionError


class OpenMetricsScraper:
Expand Down Expand Up @@ -405,11 +406,11 @@ def stream_connection_lines(self):
self._content_type = connection.headers.get('Content-Type', '')
for line in connection.iter_lines(decode_unicode=True):
yield line
except ConnectionError as e:
except (RequestsConnectionError, HTTPConnectionError) as e:
if self.ignore_connection_errors:
self.log.warning("OpenMetrics endpoint %s is not accessible", self.endpoint)
self.log.warning("OpenMetrics endpoint %s is not accessible: %s", self.endpoint, e)
else:
raise e
raise

def filter_connection_lines(self, line_streamer):
"""
Expand Down
14 changes: 13 additions & 1 deletion datadog_checks_base/datadog_checks/base/utils/http_protocol.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@
from __future__ import annotations

from collections.abc import Mapping
from typing import Any, Iterator, Protocol
from datetime import timedelta
from typing import Any, Iterator, Protocol, runtime_checkable


@runtime_checkable
class HTTPResponseProtocol(Protocol):
status_code: int
content: bytes
Expand All @@ -17,6 +19,16 @@ class HTTPResponseProtocol(Protocol):
def ok(self) -> bool: ...
@property
def reason(self) -> str: ...
@property
def encoding(self) -> str | None: ...
@encoding.setter
def encoding(self, value: str | None) -> None: ...
@property
def url(self) -> str: ...
@property
def cookies(self) -> Mapping[str, str]: ...
@property
def elapsed(self) -> timedelta: ...

def json(self, **kwargs: Any) -> Any: ...
def raise_for_status(self) -> None: ...
Expand Down
Loading
Loading