Avoid matching entity_id/domain attributes in logbook when there is no entities_filter (#71825)

This commit is contained in:
J. Nick Koston 2022-05-13 16:16:33 -04:00 committed by GitHub
parent 08ee276277
commit 2a2a7a62c5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 45 additions and 31 deletions

View File

@ -426,7 +426,8 @@ def _humanify(
elif event_type == EVENT_LOGBOOK_ENTRY:
event = event_cache.get(row)
event_data = event.data
if not (event_data := event.data):
continue
domain = event_data.get(ATTR_DOMAIN)
entity_id = event_data.get(ATTR_ENTITY_ID)
if domain is None and entity_id is not None:
@ -474,6 +475,22 @@ def _get_events(
def yield_rows(query: Query) -> Generator[Row, None, None]:
"""Yield Events that are not filtered away."""
def _keep_row(row: Row, event_type: str) -> bool:
"""Check if the entity_filter rejects a row."""
assert entities_filter is not None
if entity_id := _row_event_data_extract(row, ENTITY_ID_JSON_EXTRACT):
return entities_filter(entity_id)
if event_type in external_events:
# If the entity_id isn't described, use the domain that describes
# the event for filtering.
domain: str | None = external_events[event_type][0]
else:
domain = _row_event_data_extract(row, DOMAIN_JSON_EXTRACT)
return domain is not None and entities_filter(f"{domain}._")
# end_day - start_day intentionally checks .days and not .total_seconds()
# since we don't want to switch over to buffered if they go
# over one day by a few hours since the UI makes it so easy to do that.
@ -490,16 +507,17 @@ def _get_events(
# so we don't switch over until we request > 1 day+ of data.
#
rows = query.yield_per(1024)
for row in rows:
context_lookup.setdefault(row.context_id, row)
if row.context_only:
continue
event_type = row.event_type
if event_type != EVENT_CALL_SERVICE and (
event_type == EVENT_STATE_CHANGED
or _keep_row(hass, event_type, row, entities_filter)
):
yield row
if not row.context_only:
event_type = row.event_type
if event_type != EVENT_CALL_SERVICE and (
entities_filter is None
or event_type == EVENT_STATE_CHANGED
or _keep_row(row, event_type)
):
yield row
if entity_ids is not None:
entities_filter = generate_filter([], entity_ids, [], [])
@ -526,27 +544,6 @@ def _get_events(
)
def _keep_row(
hass: HomeAssistant,
event_type: str,
row: Row,
entities_filter: EntityFilter | Callable[[str], bool] | None = None,
) -> bool:
if entity_id := _row_event_data_extract(row, ENTITY_ID_JSON_EXTRACT):
return entities_filter is None or entities_filter(entity_id)
if event_type in hass.data[DOMAIN]:
# If the entity_id isn't described, use the domain that describes
# the event for filtering.
domain = hass.data[DOMAIN][event_type][0]
else:
domain = _row_event_data_extract(row, DOMAIN_JSON_EXTRACT)
return domain is not None and (
entities_filter is None or entities_filter(f"{domain}._")
)
class ContextAugmenter:
"""Augment data with context trace."""

View File

@ -1761,13 +1761,21 @@ async def test_fire_logbook_entries(hass, hass_client, recorder_mock):
logbook.EVENT_LOGBOOK_ENTRY,
{},
)
hass.bus.async_fire(
logbook.EVENT_LOGBOOK_ENTRY,
{
logbook.ATTR_NAME: "Alarm",
logbook.ATTR_MESSAGE: "is triggered",
logbook.ATTR_DOMAIN: "switch",
},
)
await async_wait_recording_done(hass)
client = await hass_client()
response_json = await _async_fetch_logbook(client)
# The empty events should be skipped
assert len(response_json) == 10
assert len(response_json) == 11
async def test_exclude_events_domain(hass, hass_client, recorder_mock):
@ -1986,6 +1994,15 @@ async def test_include_events_domain_glob(hass, hass_client, recorder_mock):
)
await async_recorder_block_till_done(hass)
# Should get excluded by domain
hass.bus.async_fire(
logbook.EVENT_LOGBOOK_ENTRY,
{
logbook.ATTR_NAME: "Alarm",
logbook.ATTR_MESSAGE: "is triggered",
logbook.ATTR_DOMAIN: "switch",
},
)
hass.bus.async_fire(EVENT_HOMEASSISTANT_START)
hass.bus.async_fire(EVENT_HOMEASSISTANT_STARTED)
hass.bus.async_fire(