Skip to content

Commit 678c5c8

Browse files
authored
feat: opt-in logging support for request / response (#1686)
* feat: opt-in logging support for request/response * add pragma no cover * add test coverage for request/response * add code coverage
1 parent 283748a commit 678c5c8

File tree

2 files changed

+87
-13
lines changed

2 files changed

+87
-13
lines changed

google/auth/_helpers.py

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,14 @@
2626

2727
from google.auth import exceptions
2828

29+
try:
30+
from google.api_core import client_logging
31+
CLIENT_LOGGING_SUPPORTED = True # pragma: NO COVER
32+
# TODO(https://github.com/googleapis/google-auth-library-python/issues/1690): Remove `pragma: NO COVER` once
33+
# logging is supported in minimum version of google-api-core.
34+
except ImportError: # pragma: NO COVER
35+
CLIENT_LOGGING_SUPPORTED = False
36+
2937
# The smallest MDS cache used by this library stores tokens until 4 minutes from
3038
# expiry.
3139
REFRESH_THRESHOLD = datetime.timedelta(minutes=3, seconds=45)
@@ -316,15 +324,22 @@ def _hash_value(value, field_name: str) -> str:
316324
return f"hashed_{field_name}-{hex_digest}"
317325

318326

319-
def request_log(
320-
logger: logging.Logger,
321-
method: str,
322-
url: str,
323-
body: Optional[Any],
324-
headers: Optional[Dict[str, str]],
325-
) -> None:
327+
def is_logging_enabled(logger: logging.Logger) -> bool:
328+
"""
329+
Checks if debug logging is enabled for the given logger.
330+
331+
Args:
332+
logger: The logging.Logger instance to check.
333+
334+
Returns:
335+
True if debug logging is enabled, False otherwise.
336+
"""
337+
return CLIENT_LOGGING_SUPPORTED and logger.isEnabledFor(logging.DEBUG)
338+
339+
340+
def request_log(logger: logging.Logger, method: str, url: str, body: Optional[Any], headers: Optional[Dict[str, str]]) -> None:
326341
"""
327-
Logs an HTTP request at the DEBUG level.
342+
Logs an HTTP request at the DEBUG level if logging is enabled.
328343
329344
Args:
330345
logger: The logging.Logger instance to use.
@@ -333,21 +348,21 @@ def request_log(
333348
body: The request body (can be None).
334349
headers: The request headers (can be None).
335350
"""
336-
# TODO(https://github.com/googleapis/google-auth-library-python/issues/1680): Log only if enabled.
337351
# TODO(https://github.com/googleapis/google-auth-library-python/issues/1682): Add httpRequest extra to log event.
338352
# TODO(https://github.com/googleapis/google-auth-library-python/issues/1681): Hash sensitive information.
339-
logger.debug("Making request: %s %s", method, url)
353+
if is_logging_enabled(logger):
354+
logger.debug("Making request: %s %s", method, url)
340355

341356

342357
def response_log(logger: logging.Logger, response: Any) -> None:
343358
"""
344-
Logs an HTTP response at the DEBUG level.
359+
Logs an HTTP response at the DEBUG level if logging is enabled.
345360
346361
Args:
347362
logger: The logging.Logger instance to use.
348363
response: The HTTP response object to log.
349364
"""
350-
# TODO(https://github.com/googleapis/google-auth-library-python/issues/1680): Log only if enabled.
351365
# TODO(https://github.com/googleapis/google-auth-library-python/issues/1683): Add httpResponse extra to log event.
352366
# TODO(https://github.com/googleapis/google-auth-library-python/issues/1681): Hash sensitive information.
353-
logger.debug("Response received...")
367+
if is_logging_enabled(logger):
368+
logger.debug("Response received...")

tests/test__helpers.py

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,20 @@
1414

1515
import datetime
1616
import urllib
17+
import logging
18+
from unittest import mock
1719

1820
import pytest # type: ignore
1921

2022
from google.auth import _helpers
2123

2224

25+
@pytest.fixture
26+
def logger():
27+
"""Provides a basic logger instance for testing."""
28+
return logging.getLogger(__name__)
29+
30+
2331
class SourceClass(object):
2432
def func(self): # pragma: NO COVER
2533
"""example docstring"""
@@ -263,3 +271,54 @@ def test_hash_value_different_hashing():
263271

264272
def test_hash_value_none():
265273
assert _helpers._hash_value(None, "test") is None
274+
275+
276+
def test_is_logging_enabled_with_no_level_set(logger):
277+
278+
with mock.patch("google.auth._helpers.CLIENT_LOGGING_SUPPORTED", True):
279+
assert _helpers.is_logging_enabled(logger) is False
280+
281+
282+
def test_is_logging_enabled_with_client_logging_not_supported(caplog, logger):
283+
284+
with mock.patch("google.auth._helpers.CLIENT_LOGGING_SUPPORTED", False):
285+
caplog.set_level(logging.DEBUG, logger=__name__)
286+
assert _helpers.is_logging_enabled(logger) is False
287+
288+
289+
def test_is_logging_enabled_with_debug_disabled(caplog, logger):
290+
291+
with mock.patch("google.auth._helpers.CLIENT_LOGGING_SUPPORTED", True):
292+
caplog.set_level(logging.INFO, logger=__name__)
293+
assert _helpers.is_logging_enabled(logger) is False
294+
295+
296+
def test_is_logging_enabled_with_debug_enabled(caplog, logger):
297+
with mock.patch("google.auth._helpers.CLIENT_LOGGING_SUPPORTED", True):
298+
caplog.set_level(logging.DEBUG, logger=__name__)
299+
assert _helpers.is_logging_enabled(logger)
300+
301+
302+
def test_request_log_debug_enabled(logger, caplog):
303+
logger.setLevel(logging.DEBUG)
304+
with mock.patch("google.auth._helpers.CLIENT_LOGGING_SUPPORTED", True):
305+
_helpers.request_log(logger, "GET", "http://example.com", {"key": "value"}, {"Authorization": "Bearer token"})
306+
assert "Making request: GET http://example.com" in caplog.text
307+
308+
def test_request_log_debug_disabled(logger, caplog):
309+
logger.setLevel(logging.INFO)
310+
with mock.patch("google.auth._helpers.CLIENT_LOGGING_SUPPORTED", True):
311+
_helpers.request_log(logger, "POST", "https://api.example.com", "data", {"Content-Type": "application/json"})
312+
assert "Making request: POST https://api.example.com" not in caplog.text
313+
314+
def test_response_log_debug_enabled(logger, caplog):
315+
logger.setLevel(logging.DEBUG)
316+
with mock.patch("google.auth._helpers.CLIENT_LOGGING_SUPPORTED", True):
317+
_helpers.response_log(logger, "response_object")
318+
assert "Response received..." in caplog.text
319+
320+
def test_response_log_debug_disabled(logger, caplog):
321+
logger.setLevel(logging.INFO)
322+
with mock.patch("google.auth._helpers.CLIENT_LOGGING_SUPPORTED", True):
323+
_helpers.response_log(logger, "another_response")
324+
assert "Response received..." not in caplog.text

0 commit comments

Comments
 (0)