Skip to content

Commit a65e853

Browse files
authored
Reduce redundant logging during ChainedTokenCredential.get_token() (#19283)
1 parent dfe260b commit a65e853

File tree

8 files changed

+81
-16
lines changed

8 files changed

+81
-16
lines changed

sdk/identity/azure-identity/CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@
99
### Bugs Fixed
1010

1111
### Other Changes
12+
- Reduced redundant `ChainedTokenCredential` and `DefaultAzureCredential`
13+
logging. On Python 3.7+, credentials invoked by these classes now log debug
14+
rather than info messages.
15+
([#18972](https://github.com/Azure/azure-sdk-for-python/issues/18972))
1216

1317
## 1.7.0b2 (2021-07-08)
1418
### Features Added

sdk/identity/azure-identity/azure/identity/_credentials/chained.py

+5-3
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from azure.core.exceptions import ClientAuthenticationError
88

99
from .. import CredentialUnavailableError
10+
from .._internal import within_credential_chain
1011

1112
try:
1213
from typing import TYPE_CHECKING
@@ -61,6 +62,7 @@ def get_token(self, *scopes, **kwargs): # pylint:disable=unused-argument
6162
:param str scopes: desired scopes for the access token. This method requires at least one scope.
6263
:raises ~azure.core.exceptions.ClientAuthenticationError: no credential in the chain provided a token
6364
"""
65+
within_credential_chain.set(True)
6466
history = []
6567
for credential in self.credentials:
6668
try:
@@ -71,19 +73,19 @@ def get_token(self, *scopes, **kwargs): # pylint:disable=unused-argument
7173
except CredentialUnavailableError as ex:
7274
# credential didn't attempt authentication because it lacks required data or state -> continue
7375
history.append((credential, ex.message))
74-
_LOGGER.info("%s - %s is unavailable", self.__class__.__name__, credential.__class__.__name__)
7576
except Exception as ex: # pylint: disable=broad-except
7677
# credential failed to authenticate, or something unexpectedly raised -> break
7778
history.append((credential, str(ex)))
78-
_LOGGER.warning(
79+
_LOGGER.debug(
7980
'%s.get_token failed: %s raised unexpected error "%s"',
8081
self.__class__.__name__,
8182
credential.__class__.__name__,
8283
ex,
83-
exc_info=_LOGGER.isEnabledFor(logging.DEBUG),
84+
exc_info=True,
8485
)
8586
break
8687

88+
within_credential_chain.set(False)
8789
attempts = _get_error_message(history)
8890
message = self.__class__.__name__ + " failed to retrieve a token from the included credentials." + attempts
8991
_LOGGER.warning(message)

sdk/identity/azure-identity/azure/identity/_internal/__init__.py

+17
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,23 @@
1414
if TYPE_CHECKING:
1515
from typing import Any, Optional
1616

17+
try:
18+
from contextvars import ContextVar
19+
20+
within_credential_chain = ContextVar("within_credential_chain", default=False)
21+
except ImportError:
22+
# No ContextVar on Python < 3.7. Credentials will behave as if they're never in a chain i.e. they will log fully.
23+
24+
class AlwaysFalse:
25+
# pylint:disable=no-self-use
26+
def get(self):
27+
return False
28+
29+
def set(self, _):
30+
pass
31+
32+
within_credential_chain = AlwaysFalse() # type: ignore
33+
1734

1835
def normalize_authority(authority):
1936
# type: (str) -> str

sdk/identity/azure-identity/azure/identity/_internal/decorators.py

+13-2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88
from six import raise_from
99
from azure.core.exceptions import ClientAuthenticationError
1010

11+
from . import within_credential_chain
12+
13+
1114
_LOGGER = logging.getLogger(__name__)
1215

1316

@@ -25,10 +28,18 @@ def decorator(fn):
2528
def wrapper(*args, **kwargs):
2629
try:
2730
token = fn(*args, **kwargs)
28-
_LOGGER.info("%s succeeded", qualified_name)
31+
_LOGGER.log(
32+
logging.DEBUG if within_credential_chain.get() else logging.INFO, "%s succeeded", qualified_name
33+
)
2934
return token
3035
except Exception as ex:
31-
_LOGGER.warning("%s failed: %s", qualified_name, ex, exc_info=_LOGGER.isEnabledFor(logging.DEBUG))
36+
_LOGGER.log(
37+
logging.DEBUG if within_credential_chain.get() else logging.WARNING,
38+
"%s failed: %s",
39+
qualified_name,
40+
ex,
41+
exc_info=_LOGGER.isEnabledFor(logging.DEBUG),
42+
)
3243
raise
3344

3445
return wrapper

sdk/identity/azure-identity/azure/identity/_internal/get_token_mixin.py

+12-3
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import time
88
from typing import TYPE_CHECKING
99

10+
from . import within_credential_chain
1011
from .._constants import DEFAULT_REFRESH_OFFSET, DEFAULT_TOKEN_REFRESH_RETRY_DELAY
1112

1213
try:
@@ -80,11 +81,19 @@ def get_token(self, *scopes, **kwargs):
8081
token = self._request_token(*scopes, **kwargs)
8182
except Exception: # pylint:disable=broad-except
8283
pass
83-
_LOGGER.info("%s.get_token succeeded", self.__class__.__name__)
84+
_LOGGER.log(
85+
logging.DEBUG if within_credential_chain.get() else logging.INFO,
86+
"%s.get_token succeeded",
87+
self.__class__.__name__,
88+
)
8489
return token
8590

8691
except Exception as ex:
87-
_LOGGER.warning(
88-
"%s.get_token failed: %s", self.__class__.__name__, ex, exc_info=_LOGGER.isEnabledFor(logging.DEBUG)
92+
_LOGGER.log(
93+
logging.DEBUG if within_credential_chain.get() else logging.WARNING,
94+
"%s.get_token failed: %s",
95+
self.__class__.__name__,
96+
ex,
97+
exc_info=_LOGGER.isEnabledFor(logging.DEBUG),
8998
)
9099
raise

sdk/identity/azure-identity/azure/identity/aio/_credentials/chained.py

+5-3
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
from .._internal import AsyncContextManager
1111
from ... import CredentialUnavailableError
1212
from ..._credentials.chained import _get_error_message
13+
from ..._internal import within_credential_chain
1314

1415
if TYPE_CHECKING:
1516
from typing import Any, Optional
@@ -52,6 +53,7 @@ async def get_token(self, *scopes: str, **kwargs: "Any") -> "AccessToken":
5253
:param str scopes: desired scopes for the access token. This method requires at least one scope.
5354
:raises ~azure.core.exceptions.ClientAuthenticationError: no credential in the chain provided a token
5455
"""
56+
within_credential_chain.set(True)
5557
history = []
5658
for credential in self.credentials:
5759
try:
@@ -62,19 +64,19 @@ async def get_token(self, *scopes: str, **kwargs: "Any") -> "AccessToken":
6264
except CredentialUnavailableError as ex:
6365
# credential didn't attempt authentication because it lacks required data or state -> continue
6466
history.append((credential, ex.message))
65-
_LOGGER.info("%s - %s is unavailable", self.__class__.__name__, credential.__class__.__name__)
6667
except Exception as ex: # pylint: disable=broad-except
6768
# credential failed to authenticate, or something unexpectedly raised -> break
6869
history.append((credential, str(ex)))
69-
_LOGGER.warning(
70+
_LOGGER.debug(
7071
'%s.get_token failed: %s raised unexpected error "%s"',
7172
self.__class__.__name__,
7273
credential.__class__.__name__,
7374
ex,
74-
exc_info=_LOGGER.isEnabledFor(logging.DEBUG),
75+
exc_info=True,
7576
)
7677
break
7778

79+
within_credential_chain.set(False)
7880
attempts = _get_error_message(history)
7981
message = self.__class__.__name__ + " failed to retrieve a token from the included credentials." + attempts
8082
raise ClientAuthenticationError(message=message)

sdk/identity/azure-identity/azure/identity/aio/_internal/decorators.py

+13-2
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77

88
from azure.core.exceptions import ClientAuthenticationError
99

10+
from ..._internal import within_credential_chain
11+
1012
_LOGGER = logging.getLogger(__name__)
1113

1214

@@ -15,11 +17,20 @@ def log_get_token_async(fn):
1517
async def wrapper(*args, **kwargs):
1618
try:
1719
token = await fn(*args, **kwargs)
18-
_LOGGER.info("%s succeeded", fn.__qualname__)
20+
_LOGGER.log(
21+
logging.DEBUG if within_credential_chain.get() else logging.INFO, "%s succeeded", fn.__qualname__
22+
)
1923
return token
2024
except Exception as ex:
21-
_LOGGER.warning("%s failed: %s", fn.__qualname__, ex, exc_info=_LOGGER.isEnabledFor(logging.DEBUG))
25+
_LOGGER.log(
26+
logging.DEBUG if within_credential_chain.get() else logging.WARNING,
27+
"%s failed: %s",
28+
fn.__qualname__,
29+
ex,
30+
exc_info=_LOGGER.isEnabledFor(logging.DEBUG),
31+
)
2232
raise
33+
2334
return wrapper
2435

2536

sdk/identity/azure-identity/azure/identity/aio/_internal/get_token_mixin.py

+12-3
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from typing import TYPE_CHECKING
99

1010
from ..._constants import DEFAULT_REFRESH_OFFSET, DEFAULT_TOKEN_REFRESH_RETRY_DELAY
11+
from ..._internal import within_credential_chain
1112

1213
if TYPE_CHECKING:
1314
# pylint:disable=ungrouped-imports,unused-import
@@ -70,11 +71,19 @@ async def get_token(self, *scopes: str, **kwargs: "Any") -> "AccessToken":
7071
token = await self._request_token(*scopes, **kwargs)
7172
except Exception: # pylint:disable=broad-except
7273
pass
73-
_LOGGER.info("%s.get_token succeeded", self.__class__.__name__)
74+
_LOGGER.log(
75+
logging.DEBUG if within_credential_chain.get() else logging.INFO,
76+
"%s.get_token succeeded",
77+
self.__class__.__name__,
78+
)
7479
return token
7580

7681
except Exception as ex:
77-
_LOGGER.warning(
78-
"%s.get_token failed: %s", self.__class__.__name__, ex, exc_info=_LOGGER.isEnabledFor(logging.DEBUG)
82+
_LOGGER.log(
83+
logging.DEBUG if within_credential_chain.get() else logging.WARNING,
84+
"%s.get_token failed: %s",
85+
self.__class__.__name__,
86+
ex,
87+
exc_info=_LOGGER.isEnabledFor(logging.DEBUG),
7988
)
8089
raise

0 commit comments

Comments
 (0)