If internet/device/service is unavailable, log once when unavailable and once when back connected
Reasoning
When a device or service is not reachable, the entities will usually go to unavailable. To allow the user to find out why this is happening, the integration should log when this happens. Be sure to log only once in total to avoid spamming the logs.
When the device or service is reachable again, the integration should log that as well. This can prove useful for using the logs to find out when the device or service was unavailable and when it was back online.
Logging should happen at info
level.
Example implementation
Since there are many different ways this can be implemented, we will only provide the example for integrations using the coordinator and for entities updating via async_update
.
Example for integrations using the coordinator
In this example, we have an integration that uses a coordinator to fetch data.
The coordinator has the logic for logging once built in.
The only thing that you need to do in the coordinator is to raise UpdateFailed
when the device or service is unavailable.
coordinator.py
class MyCoordinator(DataUpdateCoordinator[MyData]):
"""Class to manage fetching data."""
def __init__(self, hass: HomeAssistant, client: MyClient) -> None:
"""Initialize coordinator."""
super().__init__(
hass,
logger=LOGGER,
name=DOMAIN,
update_interval=timedelta(minutes=1),
)
self.client = client
async def _async_update_data(self) -> MyData:
try:
return await self.client.get_data()
except MyException as ex:
raise UpdateFailed(f"The device is unavailable: {ex}")
Example for entities updating via async_update
In this example, we have a sensor that updates its value via async_update
.
The example will log when the sensor is unavailable and log when the sensor is back online.
Note that an instance attribute is used to track if the message has been logged to avoid spamming the logs.
sensor.py
class MySensor(SensorEntity):
_unavailable_logged: bool = False
async def async_update(self) -> None:
try:
data = await self.client.get_data()
except MyException as ex:
self._attr_available = False
if not self._unavailable_logged:
_LOGGER.info("The sensor is unavailable: %s", ex)
self._unavailable_logged = True
else:
self._attr_available = True
self._attr_native_value = data.value
if self._unavailable_logged:
_LOGGER.info("The sensor is back online")
self._unavailable_logged = False
Additional resources
For more information about managing integration state, see the documentation
Exceptions
There are no exceptions to this rule.
Related rules
- entity-unavailable: Mark entity unavailable if appropriate