Improve warning prints for sensor statistics (#57605)

This commit is contained in:
Erik Montnemery 2021-10-13 17:15:04 +02:00 committed by GitHub
parent c97acf8713
commit a5603c0076
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 37 additions and 18 deletions

View File

@ -330,6 +330,7 @@ class EnergyCostSensor(SensorEntity):
cast(str, self._config[self._adapter.entity_energy_key]), cast(str, self._config[self._adapter.entity_energy_key]),
energy, energy,
float(self._last_energy_sensor_state.state), float(self._last_energy_sensor_state.state),
self._last_energy_sensor_state,
): ):
# Energy meter was reset, reset cost sensor too # Energy meter was reset, reset cost sensor too
energy_state_copy = copy.copy(energy_state) energy_state_copy = copy.copy(energy_state)

View File

@ -287,7 +287,7 @@ def _suggest_report_issue(hass: HomeAssistant, entity_id: str) -> str:
return report_issue return report_issue
def warn_dip(hass: HomeAssistant, entity_id: str) -> None: def warn_dip(hass: HomeAssistant, entity_id: str, state: State) -> None:
"""Log a warning once if a sensor with state_class_total has a decreasing value. """Log a warning once if a sensor with state_class_total has a decreasing value.
The log will be suppressed until two dips have been seen to prevent warning due to The log will be suppressed until two dips have been seen to prevent warning due to
@ -308,14 +308,17 @@ def warn_dip(hass: HomeAssistant, entity_id: str) -> None:
return return
_LOGGER.warning( _LOGGER.warning(
"Entity %s %shas state class total_increasing, but its state is " "Entity %s %shas state class total_increasing, but its state is "
"not strictly increasing. Please %s", "not strictly increasing. Triggered by state %s with last_updated set to %s. "
"Please %s",
entity_id, entity_id,
f"from integration {domain} " if domain else "", f"from integration {domain} " if domain else "",
state.state,
state.last_updated.isoformat(),
_suggest_report_issue(hass, entity_id), _suggest_report_issue(hass, entity_id),
) )
def warn_negative(hass: HomeAssistant, entity_id: str) -> None: def warn_negative(hass: HomeAssistant, entity_id: str, state: State) -> None:
"""Log a warning once if a sensor with state_class_total has a negative value.""" """Log a warning once if a sensor with state_class_total has a negative value."""
if WARN_NEGATIVE not in hass.data: if WARN_NEGATIVE not in hass.data:
hass.data[WARN_NEGATIVE] = set() hass.data[WARN_NEGATIVE] = set()
@ -324,28 +327,34 @@ def warn_negative(hass: HomeAssistant, entity_id: str) -> None:
domain = entity_sources(hass).get(entity_id, {}).get("domain") domain = entity_sources(hass).get(entity_id, {}).get("domain")
_LOGGER.warning( _LOGGER.warning(
"Entity %s %shas state class total_increasing, but its state is " "Entity %s %shas state class total_increasing, but its state is "
"negative. Please %s", "negative. Triggered by state %s with last_updated set to %s. Please %s",
entity_id, entity_id,
f"from integration {domain} " if domain else "", f"from integration {domain} " if domain else "",
state.state,
state.last_updated.isoformat(),
_suggest_report_issue(hass, entity_id), _suggest_report_issue(hass, entity_id),
) )
def reset_detected( def reset_detected(
hass: HomeAssistant, entity_id: str, state: float, previous_state: float | None hass: HomeAssistant,
entity_id: str,
fstate: float,
previous_fstate: float | None,
state: State,
) -> bool: ) -> bool:
"""Test if a total_increasing sensor has been reset.""" """Test if a total_increasing sensor has been reset."""
if previous_state is None: if previous_fstate is None:
return False return False
if 0.9 * previous_state <= state < previous_state: if 0.9 * previous_fstate <= fstate < previous_fstate:
warn_dip(hass, entity_id) warn_dip(hass, entity_id, state)
if state < 0: if fstate < 0:
warn_negative(hass, entity_id) warn_negative(hass, entity_id, state)
raise HomeAssistantError raise HomeAssistantError
return state < 0.9 * previous_state return fstate < 0.9 * previous_fstate
def _wanted_statistics(sensor_states: list[State]) -> dict[str, set[str]]: def _wanted_statistics(sensor_states: list[State]) -> dict[str, set[str]]:
@ -547,13 +556,15 @@ def _compile_statistics( # noqa: C901
elif state_class == STATE_CLASS_TOTAL_INCREASING: elif state_class == STATE_CLASS_TOTAL_INCREASING:
try: try:
if old_state is None or reset_detected( if old_state is None or reset_detected(
hass, entity_id, fstate, new_state hass, entity_id, fstate, new_state, state
): ):
reset = True reset = True
_LOGGER.info( _LOGGER.info(
"Detected new cycle for %s, value dropped from %s to %s", "Detected new cycle for %s, value dropped from %s to %s, "
"triggered by state with last_updated set to %s",
entity_id, entity_id,
new_state, new_state,
state.last_updated.isoformat(),
fstate, fstate,
) )
except HomeAssistantError: except HomeAssistantError:

View File

@ -707,8 +707,10 @@ def test_compile_hourly_sum_statistics_negative_state(
seq = [15, 16, 15, 16, 20, -20, 20, 10] seq = [15, 16, 15, 16, 20, -20, 20, 10]
states = {entity_id: []} states = {entity_id: []}
offending_state = 5
if state := hass.states.get(entity_id): if state := hass.states.get(entity_id):
states[entity_id].append(state) states[entity_id].append(state)
offending_state = 6
one = zero one = zero
for i in range(len(seq)): for i in range(len(seq)):
one = one + timedelta(seconds=5) one = one + timedelta(seconds=5)
@ -745,8 +747,11 @@ def test_compile_hourly_sum_statistics_negative_state(
}, },
] ]
assert "Error while processing event StatisticsTask" not in caplog.text assert "Error while processing event StatisticsTask" not in caplog.text
state = states[entity_id][offending_state].state
last_updated = states[entity_id][offending_state].last_updated.isoformat()
assert ( assert (
f"Entity {entity_id} {warning_1}has state class total_increasing, but its state is negative" f"Entity {entity_id} {warning_1}has state class total_increasing, but its state "
f"is negative. Triggered by state {state} with last_updated set to {last_updated}."
in caplog.text in caplog.text
) )
assert warning_2 in caplog.text assert warning_2 in caplog.text
@ -965,15 +970,17 @@ def test_compile_hourly_sum_statistics_total_increasing_small_dip(
wait_recording_done(hass) wait_recording_done(hass)
assert ( assert (
"Entity sensor.test1 has state class total_increasing, but its state is not " "Entity sensor.test1 has state class total_increasing, but its state is not "
"strictly increasing. Please create a bug report at https://github.com/" "strictly increasing."
"home-assistant/core/issues?q=is%3Aopen+is%3Aissue"
) not in caplog.text ) not in caplog.text
recorder.do_adhoc_statistics(start=period2) recorder.do_adhoc_statistics(start=period2)
wait_recording_done(hass) wait_recording_done(hass)
state = states["sensor.test1"][6].state
last_updated = states["sensor.test1"][6].last_updated.isoformat()
assert ( assert (
"Entity sensor.test1 has state class total_increasing, but its state is not " "Entity sensor.test1 has state class total_increasing, but its state is not "
"strictly increasing. Please create a bug report at https://github.com/" f"strictly increasing. Triggered by state {state} with last_updated set to "
"home-assistant/core/issues?q=is%3Aopen+is%3Aissue" f"{last_updated}. Please create a bug report at https://github.com/home-assistant"
"/core/issues?q=is%3Aopen+is%3Aissue"
) in caplog.text ) in caplog.text
statistic_ids = list_statistic_ids(hass) statistic_ids = list_statistic_ids(hass)
assert statistic_ids == [ assert statistic_ids == [