Log the reason a config entry failed to setup (#48449)

If we pass a string to ConfigEntryNotReady or raise it from
another exception we now log the string passed or the
string generated by the original exception.

With #47201 this makes it easy for developers to still show
the reason why setup failed without having to worry about log
spam from additional attempts by rasing ConfigEntryNotReady
from the original exception.
This commit is contained in:
J. Nick Koston 2021-03-29 00:25:40 -10:00 committed by GitHub
parent dd538bd291
commit cb1b45d31a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 38 additions and 5 deletions

View file

@ -252,21 +252,27 @@ class ConfigEntry:
"%s.async_setup_entry did not return boolean", integration.domain
)
result = False
except ConfigEntryNotReady:
except ConfigEntryNotReady as ex:
self.state = ENTRY_STATE_SETUP_RETRY
wait_time = 2 ** min(tries, 4) * 5
tries += 1
message = str(ex)
if not message and ex.__cause__:
message = str(ex.__cause__)
ready_message = f"ready yet: {message}" if message else "ready yet"
if tries == 1:
_LOGGER.warning(
"Config entry '%s' for %s integration not ready yet. Retrying in background",
"Config entry '%s' for %s integration not %s; Retrying in background",
self.title,
self.domain,
ready_message,
)
else:
_LOGGER.debug(
"Config entry '%s' for %s integration not ready yet. Retrying in %d seconds",
"Config entry '%s' for %s integration not %s; Retrying in %d seconds",
self.title,
self.domain,
ready_message,
wait_time,
)

View file

@ -795,7 +795,9 @@ async def test_setup_raise_not_ready(hass, caplog):
"""Test a setup raising not ready."""
entry = MockConfigEntry(title="test_title", domain="test")
mock_setup_entry = AsyncMock(side_effect=ConfigEntryNotReady)
mock_setup_entry = AsyncMock(
side_effect=ConfigEntryNotReady("The internet connection is offline")
)
mock_integration(hass, MockModule("test", async_setup_entry=mock_setup_entry))
mock_entity_platform(hass, "config_flow.test", None)
@ -803,7 +805,10 @@ async def test_setup_raise_not_ready(hass, caplog):
await entry.async_setup(hass)
assert len(mock_call.mock_calls) == 1
assert "Config entry 'test_title' for test integration not ready yet" in caplog.text
assert (
"Config entry 'test_title' for test integration not ready yet: The internet connection is offline"
in caplog.text
)
p_hass, p_wait_time, p_setup = mock_call.mock_calls[0][1]
assert p_hass is hass
@ -817,6 +822,28 @@ async def test_setup_raise_not_ready(hass, caplog):
assert entry.state == config_entries.ENTRY_STATE_LOADED
async def test_setup_raise_not_ready_from_exception(hass, caplog):
"""Test a setup raising not ready from another exception."""
entry = MockConfigEntry(title="test_title", domain="test")
original_exception = HomeAssistantError("The device dropped the connection")
config_entry_exception = ConfigEntryNotReady()
config_entry_exception.__cause__ = original_exception
mock_setup_entry = AsyncMock(side_effect=config_entry_exception)
mock_integration(hass, MockModule("test", async_setup_entry=mock_setup_entry))
mock_entity_platform(hass, "config_flow.test", None)
with patch("homeassistant.helpers.event.async_call_later") as mock_call:
await entry.async_setup(hass)
assert len(mock_call.mock_calls) == 1
assert (
"Config entry 'test_title' for test integration not ready yet: The device dropped the connection"
in caplog.text
)
async def test_setup_retrying_during_unload(hass):
"""Test if we unload an entry that is in retry mode."""
entry = MockConfigEntry(domain="test")