mirror of
https://github.com/home-assistant/core.git
synced 2025-07-24 13:47:35 +00:00
Add run_id to automation logbook event (#47980)
This commit is contained in:
parent
a4075d9e11
commit
f1c274b3dd
@ -281,6 +281,8 @@ class AutomationEntity(ToggleEntity, RestoreEntity):
|
||||
}
|
||||
if self.action_script.supports_max:
|
||||
attrs[ATTR_MAX] = self.action_script.max_runs
|
||||
if self._id is not None:
|
||||
attrs[CONF_ID] = self._id
|
||||
return attrs
|
||||
|
||||
@property
|
||||
@ -534,14 +536,6 @@ class AutomationEntity(ToggleEntity, RestoreEntity):
|
||||
variables,
|
||||
)
|
||||
|
||||
@property
|
||||
def extra_state_attributes(self):
|
||||
"""Return automation attributes."""
|
||||
if self._id is None:
|
||||
return None
|
||||
|
||||
return {CONF_ID: self._id}
|
||||
|
||||
|
||||
async def _async_process_config(
|
||||
hass: HomeAssistant,
|
||||
|
@ -1,26 +1,29 @@
|
||||
"""Describe logbook events."""
|
||||
from homeassistant.components.logbook import LazyEventPartialState
|
||||
from homeassistant.const import ATTR_ENTITY_ID, ATTR_NAME
|
||||
from homeassistant.core import callback
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
|
||||
from . import ATTR_SOURCE, DOMAIN, EVENT_AUTOMATION_TRIGGERED
|
||||
|
||||
|
||||
@callback
|
||||
def async_describe_events(hass, async_describe_event): # type: ignore
|
||||
def async_describe_events(hass: HomeAssistant, async_describe_event): # type: ignore
|
||||
"""Describe logbook events."""
|
||||
|
||||
@callback
|
||||
def async_describe_logbook_event(event): # type: ignore
|
||||
def async_describe_logbook_event(event: LazyEventPartialState): # type: ignore
|
||||
"""Describe a logbook event."""
|
||||
data = event.data
|
||||
message = "has been triggered"
|
||||
if ATTR_SOURCE in data:
|
||||
message = f"{message} by {data[ATTR_SOURCE]}"
|
||||
|
||||
return {
|
||||
"name": data.get(ATTR_NAME),
|
||||
"message": message,
|
||||
"source": data.get(ATTR_SOURCE),
|
||||
"entity_id": data.get(ATTR_ENTITY_ID),
|
||||
"context_id": event.context_id,
|
||||
}
|
||||
|
||||
async_describe_event(
|
||||
|
@ -38,7 +38,7 @@ class AutomationTrace:
|
||||
self._action_trace: Optional[Dict[str, Deque[TraceElement]]] = None
|
||||
self._condition_trace: Optional[Dict[str, Deque[TraceElement]]] = None
|
||||
self._config: Dict[str, Any] = config
|
||||
self._context: Context = context
|
||||
self.context: Context = context
|
||||
self._error: Optional[Exception] = None
|
||||
self._state: str = "running"
|
||||
self.run_id: str = str(next(self._run_ids))
|
||||
@ -88,7 +88,7 @@ class AutomationTrace:
|
||||
"action_trace": action_traces,
|
||||
"condition_trace": condition_traces,
|
||||
"config": self._config,
|
||||
"context": self._context,
|
||||
"context": self.context,
|
||||
"variables": self._variables,
|
||||
}
|
||||
)
|
||||
|
@ -24,6 +24,7 @@ from homeassistant.helpers.script import (
|
||||
)
|
||||
|
||||
from .trace import (
|
||||
DATA_AUTOMATION_TRACE,
|
||||
TraceJSONEncoder,
|
||||
get_debug_trace,
|
||||
get_debug_traces,
|
||||
@ -38,6 +39,7 @@ def async_setup(hass: HomeAssistant) -> None:
|
||||
"""Set up the websocket API."""
|
||||
websocket_api.async_register_command(hass, websocket_automation_trace_get)
|
||||
websocket_api.async_register_command(hass, websocket_automation_trace_list)
|
||||
websocket_api.async_register_command(hass, websocket_automation_trace_contexts)
|
||||
websocket_api.async_register_command(hass, websocket_automation_breakpoint_clear)
|
||||
websocket_api.async_register_command(hass, websocket_automation_breakpoint_list)
|
||||
websocket_api.async_register_command(hass, websocket_automation_breakpoint_set)
|
||||
@ -86,6 +88,34 @@ def websocket_automation_trace_list(hass, connection, msg):
|
||||
connection.send_result(msg["id"], automation_traces)
|
||||
|
||||
|
||||
@callback
|
||||
@websocket_api.require_admin
|
||||
@websocket_api.websocket_command(
|
||||
{
|
||||
vol.Required("type"): "automation/trace/contexts",
|
||||
vol.Optional("automation_id"): str,
|
||||
}
|
||||
)
|
||||
def websocket_automation_trace_contexts(hass, connection, msg):
|
||||
"""Retrieve contexts we have traces for."""
|
||||
automation_id = msg.get("automation_id")
|
||||
|
||||
if automation_id is not None:
|
||||
values = {
|
||||
automation_id: hass.data[DATA_AUTOMATION_TRACE].get(automation_id, {})
|
||||
}
|
||||
else:
|
||||
values = hass.data[DATA_AUTOMATION_TRACE]
|
||||
|
||||
contexts = {
|
||||
trace.context.id: {"run_id": trace.run_id, "automation_id": automation_id}
|
||||
for automation_id, traces in values.items()
|
||||
for trace in traces.values()
|
||||
}
|
||||
|
||||
connection.send_result(msg["id"], contexts)
|
||||
|
||||
|
||||
@callback
|
||||
@websocket_api.require_admin
|
||||
@websocket_api.websocket_command(
|
||||
|
54
tests/components/automation/test_logbook.py
Normal file
54
tests/components/automation/test_logbook.py
Normal file
@ -0,0 +1,54 @@
|
||||
"""Test automation logbook."""
|
||||
from homeassistant.components import automation, logbook
|
||||
from homeassistant.core import Context
|
||||
from homeassistant.setup import async_setup_component
|
||||
|
||||
from tests.components.logbook.test_init import MockLazyEventPartialState
|
||||
|
||||
|
||||
async def test_humanify_automation_trigger_event(hass):
|
||||
"""Test humanifying Shelly click event."""
|
||||
hass.config.components.add("recorder")
|
||||
assert await async_setup_component(hass, "automation", {})
|
||||
assert await async_setup_component(hass, "logbook", {})
|
||||
entity_attr_cache = logbook.EntityAttributeCache(hass)
|
||||
context = Context()
|
||||
|
||||
event1, event2 = list(
|
||||
logbook.humanify(
|
||||
hass,
|
||||
[
|
||||
MockLazyEventPartialState(
|
||||
automation.EVENT_AUTOMATION_TRIGGERED,
|
||||
{
|
||||
"name": "Bla",
|
||||
"entity_id": "automation.bla",
|
||||
"source": "state change of input_boolean.yo",
|
||||
},
|
||||
context=context,
|
||||
),
|
||||
MockLazyEventPartialState(
|
||||
automation.EVENT_AUTOMATION_TRIGGERED,
|
||||
{
|
||||
"name": "Bla",
|
||||
"entity_id": "automation.bla",
|
||||
},
|
||||
context=context,
|
||||
),
|
||||
],
|
||||
entity_attr_cache,
|
||||
{},
|
||||
)
|
||||
)
|
||||
|
||||
assert event1["name"] == "Bla"
|
||||
assert event1["message"] == "has been triggered by state change of input_boolean.yo"
|
||||
assert event1["source"] == "state change of input_boolean.yo"
|
||||
assert event1["context_id"] == context.id
|
||||
assert event1["entity_id"] == "automation.bla"
|
||||
|
||||
assert event2["name"] == "Bla"
|
||||
assert event2["message"] == "has been triggered"
|
||||
assert event2["source"] is None
|
||||
assert event2["context_id"] == context.id
|
||||
assert event2["entity_id"] == "automation.bla"
|
@ -65,6 +65,7 @@ async def test_get_automation_trace(hass, hass_ws_client):
|
||||
await async_setup_component(hass, "config", {})
|
||||
|
||||
client = await hass_ws_client()
|
||||
contexts = {}
|
||||
|
||||
# Trigger "sun" automation
|
||||
context = Context()
|
||||
@ -102,6 +103,10 @@ async def test_get_automation_trace(hass, hass_ws_client):
|
||||
assert trace["trigger"] == "event 'test_event'"
|
||||
assert trace["unique_id"] == "sun"
|
||||
assert trace["variables"]
|
||||
contexts[trace["context"]["id"]] = {
|
||||
"run_id": trace["run_id"],
|
||||
"automation_id": trace["automation_id"],
|
||||
}
|
||||
|
||||
# Trigger "moon" automation, with passing condition
|
||||
hass.bus.async_fire("test_event2")
|
||||
@ -139,6 +144,10 @@ async def test_get_automation_trace(hass, hass_ws_client):
|
||||
assert trace["trigger"] == "event 'test_event2'"
|
||||
assert trace["unique_id"] == "moon"
|
||||
assert trace["variables"]
|
||||
contexts[trace["context"]["id"]] = {
|
||||
"run_id": trace["run_id"],
|
||||
"automation_id": trace["automation_id"],
|
||||
}
|
||||
|
||||
# Trigger "moon" automation, with failing condition
|
||||
hass.bus.async_fire("test_event3")
|
||||
@ -173,6 +182,10 @@ async def test_get_automation_trace(hass, hass_ws_client):
|
||||
assert trace["trigger"] == "event 'test_event3'"
|
||||
assert trace["unique_id"] == "moon"
|
||||
assert trace["variables"]
|
||||
contexts[trace["context"]["id"]] = {
|
||||
"run_id": trace["run_id"],
|
||||
"automation_id": trace["automation_id"],
|
||||
}
|
||||
|
||||
# Trigger "moon" automation, with passing condition
|
||||
hass.bus.async_fire("test_event2")
|
||||
@ -210,6 +223,16 @@ async def test_get_automation_trace(hass, hass_ws_client):
|
||||
assert trace["trigger"] == "event 'test_event2'"
|
||||
assert trace["unique_id"] == "moon"
|
||||
assert trace["variables"]
|
||||
contexts[trace["context"]["id"]] = {
|
||||
"run_id": trace["run_id"],
|
||||
"automation_id": trace["automation_id"],
|
||||
}
|
||||
|
||||
# Check contexts
|
||||
await client.send_json({"id": next_id(), "type": "automation/trace/contexts"})
|
||||
response = await client.receive_json()
|
||||
assert response["success"]
|
||||
assert response["result"] == contexts
|
||||
|
||||
|
||||
async def test_automation_trace_overflow(hass, hass_ws_client):
|
||||
|
Loading…
x
Reference in New Issue
Block a user