Only process logbook timestamps for events we will keep (#36792)

* Only process logbook timestamps for events we will keep

Since we group by minute we were previously processing
every timestamp. We can avoid this by making all the
minute checks use the unprocessed datetime since
the groupings will be the same regardless of timezone.

This reduces the number of datetime object recreations
by at least an order of magnitude.
This commit is contained in:
J. Nick Koston 2020-06-15 14:54:20 -05:00 committed by GitHub
parent b0163b65c6
commit 0a219081ea
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 76 additions and 34 deletions

View File

@ -205,7 +205,7 @@ def humanify(hass, events, prev_states=None):
# Group events in batches of GROUP_BY_MINUTES
for _, g_events in groupby(
events, lambda event: event.time_fired.minute // GROUP_BY_MINUTES
events, lambda event: event.time_fired_minute // GROUP_BY_MINUTES
):
events_batch = list(g_events)
@ -224,16 +224,16 @@ def humanify(hass, events, prev_states=None):
last_sensor_event[event.entity_id] = event
elif event.event_type == EVENT_HOMEASSISTANT_STOP:
if event.time_fired.minute in start_stop_events:
if event.time_fired_minute in start_stop_events:
continue
start_stop_events[event.time_fired.minute] = 1
start_stop_events[event.time_fired_minute] = 1
elif event.event_type == EVENT_HOMEASSISTANT_START:
if event.time_fired.minute not in start_stop_events:
if event.time_fired_minute not in start_stop_events:
continue
start_stop_events[event.time_fired.minute] = 2
start_stop_events[event.time_fired_minute] = 2
# Yield entries
external_events = hass.data.get(DOMAIN, {})
@ -283,7 +283,7 @@ def humanify(hass, events, prev_states=None):
}
elif event.event_type == EVENT_HOMEASSISTANT_START:
if start_stop_events.get(event.time_fired.minute) == 2:
if start_stop_events.get(event.time_fired_minute) == 2:
continue
yield {
@ -296,7 +296,7 @@ def humanify(hass, events, prev_states=None):
}
elif event.event_type == EVENT_HOMEASSISTANT_STOP:
if start_stop_events.get(event.time_fired.minute) == 2:
if start_stop_events.get(event.time_fired_minute) == 2:
action = "restarted"
else:
action = "stopped"
@ -597,6 +597,11 @@ class LazyEventPartialState:
self._event_data = json.loads(self._row.event_data)
return self._event_data
@property
def time_fired_minute(self):
"""Minute the event was fired not converted."""
return self._row.time_fired.minute
@property
def time_fired(self):
"""Time event was fired in utc."""

View File

@ -1,9 +1,10 @@
"""Tests for alexa."""
from homeassistant.components import logbook
from homeassistant.components.alexa.const import EVENT_ALEXA_SMART_HOME
import homeassistant.core as ha
from homeassistant.setup import async_setup_component
from tests.components.logbook.test_init import MockLazyEventPartialState
async def test_humanify_alexa_event(hass):
"""Test humanifying Alexa event."""
@ -14,11 +15,11 @@ async def test_humanify_alexa_event(hass):
logbook.humanify(
hass,
[
ha.Event(
MockLazyEventPartialState(
EVENT_ALEXA_SMART_HOME,
{"request": {"namespace": "Alexa.Discovery", "name": "Discover"}},
),
ha.Event(
MockLazyEventPartialState(
EVENT_ALEXA_SMART_HOME,
{
"request": {
@ -28,7 +29,7 @@ async def test_humanify_alexa_event(hass):
}
},
),
ha.Event(
MockLazyEventPartialState(
EVENT_ALEXA_SMART_HOME,
{
"request": {

View File

@ -17,7 +17,7 @@ from homeassistant.const import (
STATE_OFF,
STATE_ON,
)
from homeassistant.core import Context, CoreState, Event, State
from homeassistant.core import Context, CoreState, State
from homeassistant.exceptions import HomeAssistantError, Unauthorized
from homeassistant.setup import async_setup_component
import homeassistant.util.dt as dt_util
@ -30,6 +30,7 @@ from tests.common import (
mock_restore_cache,
)
from tests.components.automation import common
from tests.components.logbook.test_init import MockLazyEventPartialState
@pytest.fixture
@ -1044,11 +1045,11 @@ async def test_logbook_humanify_automation_triggered_event(hass):
logbook.humanify(
hass,
[
Event(
MockLazyEventPartialState(
EVENT_AUTOMATION_TRIGGERED,
{ATTR_ENTITY_ID: "automation.hello", ATTR_NAME: "Hello Automation"},
),
Event(
MockLazyEventPartialState(
EVENT_AUTOMATION_TRIGGERED,
{ATTR_ENTITY_ID: "automation.bye", ATTR_NAME: "Bye Automation"},
),

View File

@ -1,5 +1,4 @@
"""Test HomeKit initialization."""
from homeassistant import core as ha
from homeassistant.components import logbook
from homeassistant.components.homekit.const import (
ATTR_DISPLAY_NAME,
@ -11,6 +10,7 @@ from homeassistant.const import ATTR_ENTITY_ID, ATTR_SERVICE
from homeassistant.setup import async_setup_component
from tests.async_mock import patch
from tests.components.logbook.test_init import MockLazyEventPartialState
async def test_humanify_homekit_changed_event(hass, hk_driver):
@ -22,7 +22,7 @@ async def test_humanify_homekit_changed_event(hass, hk_driver):
logbook.humanify(
hass,
[
ha.Event(
MockLazyEventPartialState(
EVENT_HOMEKIT_CHANGED,
{
ATTR_ENTITY_ID: "lock.front_door",
@ -30,7 +30,7 @@ async def test_humanify_homekit_changed_event(hass, hk_driver):
ATTR_SERVICE: "lock",
},
),
ha.Event(
MockLazyEventPartialState(
EVENT_HOMEKIT_CHANGED,
{
ATTR_ENTITY_ID: "cover.window",

View File

@ -167,7 +167,11 @@ class TestComponentLogbook(unittest.TestCase):
entities_filter = logbook._generate_filter_from_config({})
events = [
e
for e in (ha.Event(EVENT_HOMEASSISTANT_STOP), eventA, eventB)
for e in (
MockLazyEventPartialState(EVENT_HOMEASSISTANT_STOP),
eventA,
eventB,
)
if logbook._keep_event(self.hass, e, entities_filter)
]
entries = list(logbook.humanify(self.hass, events))
@ -198,7 +202,11 @@ class TestComponentLogbook(unittest.TestCase):
entities_filter = logbook._generate_filter_from_config({})
events = [
e
for e in (ha.Event(EVENT_HOMEASSISTANT_STOP), eventA, eventB)
for e in (
MockLazyEventPartialState(EVENT_HOMEASSISTANT_STOP),
eventA,
eventB,
)
if logbook._keep_event(self.hass, e, entities_filter)
]
entries = list(logbook.humanify(self.hass, events))
@ -226,7 +234,11 @@ class TestComponentLogbook(unittest.TestCase):
entities_filter = logbook._generate_filter_from_config({})
events = [
e
for e in (ha.Event(EVENT_HOMEASSISTANT_STOP), eventA, eventB)
for e in (
MockLazyEventPartialState(EVENT_HOMEASSISTANT_STOP),
eventA,
eventB,
)
if logbook._keep_event(self.hass, e, entities_filter)
]
entries = list(logbook.humanify(self.hass, events))
@ -260,7 +272,11 @@ class TestComponentLogbook(unittest.TestCase):
entities_filter = logbook._generate_filter_from_config(config[logbook.DOMAIN])
events = [
e
for e in (ha.Event(EVENT_HOMEASSISTANT_STOP), eventA, eventB)
for e in (
MockLazyEventPartialState(EVENT_HOMEASSISTANT_STOP),
eventA,
eventB,
)
if logbook._keep_event(self.hass, e, entities_filter)
]
entries = list(logbook.humanify(self.hass, events))
@ -295,8 +311,8 @@ class TestComponentLogbook(unittest.TestCase):
events = [
e
for e in (
ha.Event(EVENT_HOMEASSISTANT_START),
ha.Event(EVENT_ALEXA_SMART_HOME),
MockLazyEventPartialState(EVENT_HOMEASSISTANT_START),
MockLazyEventPartialState(EVENT_ALEXA_SMART_HOME),
eventA,
eventB,
)
@ -333,7 +349,11 @@ class TestComponentLogbook(unittest.TestCase):
entities_filter = logbook._generate_filter_from_config(config[logbook.DOMAIN])
events = [
e
for e in (ha.Event(EVENT_HOMEASSISTANT_STOP), eventA, eventB)
for e in (
MockLazyEventPartialState(EVENT_HOMEASSISTANT_STOP),
eventA,
eventB,
)
if logbook._keep_event(self.hass, e, entities_filter)
]
entries = list(logbook.humanify(self.hass, events))
@ -354,7 +374,7 @@ class TestComponentLogbook(unittest.TestCase):
pointA = dt_util.utcnow()
pointB = pointA + timedelta(minutes=logbook.GROUP_BY_MINUTES)
event_alexa = ha.Event(
event_alexa = MockLazyEventPartialState(
EVENT_ALEXA_SMART_HOME,
{"request": {"namespace": "Alexa.Discovery", "name": "Discover"}},
)
@ -373,7 +393,12 @@ class TestComponentLogbook(unittest.TestCase):
entities_filter = logbook._generate_filter_from_config(config[logbook.DOMAIN])
events = [
e
for e in (ha.Event(EVENT_HOMEASSISTANT_START), event_alexa, eventA, eventB,)
for e in (
MockLazyEventPartialState(EVENT_HOMEASSISTANT_START),
event_alexa,
eventA,
eventB,
)
if logbook._keep_event(self.hass, e, entities_filter)
]
entries = list(logbook.humanify(self.hass, events))
@ -420,7 +445,7 @@ class TestComponentLogbook(unittest.TestCase):
events = [
e
for e in (
ha.Event(EVENT_HOMEASSISTANT_START),
MockLazyEventPartialState(EVENT_HOMEASSISTANT_START),
eventA1,
eventA2,
eventA3,
@ -491,8 +516,8 @@ class TestComponentLogbook(unittest.TestCase):
logbook.humanify(
self.hass,
(
ha.Event(EVENT_HOMEASSISTANT_STOP),
ha.Event(EVENT_HOMEASSISTANT_START),
MockLazyEventPartialState(EVENT_HOMEASSISTANT_STOP),
MockLazyEventPartialState(EVENT_HOMEASSISTANT_START),
),
)
)
@ -511,7 +536,7 @@ class TestComponentLogbook(unittest.TestCase):
logbook.humanify(
self.hass,
(
ha.Event(EVENT_HOMEASSISTANT_START),
MockLazyEventPartialState(EVENT_HOMEASSISTANT_START),
self.create_state_changed_event(pointA, entity_id, 10),
),
)
@ -1129,7 +1154,7 @@ class TestComponentLogbook(unittest.TestCase):
logbook.humanify(
self.hass,
(
ha.Event(
MockLazyEventPartialState(
logbook.EVENT_LOGBOOK_ENTRY,
{
logbook.ATTR_NAME: name,
@ -1465,3 +1490,12 @@ async def test_logbook_view_end_time_entity(hass, hass_client):
json = await response.json()
assert len(json) == 1
assert json[0]["entity_id"] == entity_id_test
class MockLazyEventPartialState(ha.Event):
"""Minimal mock of a Lazy event."""
@property
def time_fired_minute(self):
"""Minute the event was fired."""
return self.time_fired.minute

View File

@ -14,7 +14,7 @@ from homeassistant.const import (
SERVICE_TURN_OFF,
SERVICE_TURN_ON,
)
from homeassistant.core import Context, Event, callback, split_entity_id
from homeassistant.core import Context, callback, split_entity_id
from homeassistant.exceptions import ServiceNotFound
from homeassistant.helpers.service import async_get_all_descriptions
from homeassistant.loader import bind_hass
@ -22,6 +22,7 @@ from homeassistant.setup import async_setup_component, setup_component
from tests.async_mock import Mock, patch
from tests.common import get_test_home_assistant
from tests.components.logbook.test_init import MockLazyEventPartialState
ENTITY_ID = "script.test"
@ -477,11 +478,11 @@ async def test_logbook_humanify_script_started_event(hass):
logbook.humanify(
hass,
[
Event(
MockLazyEventPartialState(
EVENT_SCRIPT_STARTED,
{ATTR_ENTITY_ID: "script.hello", ATTR_NAME: "Hello Script"},
),
Event(
MockLazyEventPartialState(
EVENT_SCRIPT_STARTED,
{ATTR_ENTITY_ID: "script.bye", ATTR_NAME: "Bye Script"},
),