8000 Include script script_execution in script and automation traces by emontnemery · Pull Request #48576 · home-assistant/core · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Include script script_execution in script and automation traces #48576

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Apr 1, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions homeassistant/components/automation/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
from homeassistant.helpers.service import async_register_admin_service
from homeassistant.helpers.trace import (
TraceElement,
script_execution_set,
trace_append_element,
trace_get,
trace_path,
Expand Down Expand Up @@ -471,6 +472,7 @@ async def async_trigger(self, run_variables, context=None, skip_condition=False)
"Conditions not met, aborting automation. Condition summary: %s",
trace_get(clear=False),
)
script_execution_set("failed_conditions")
return

self.async_set_context(trigger_context)
Expand Down
4 changes: 4 additions & 0 deletions homeassistant/components/trace/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from homeassistant.core import Context
from homeassistant.helpers.trace import (
TraceElement,
script_execution_get,
trace_id_get,
trace_id_set,
trace_set_child_id,
Expand Down Expand Up @@ -55,6 +56,7 @@ def __init__(
self.context: Context = context
self._error: Exception | None = None
self._state: str = "running"
self._script_execution: str | None = None
self.run_id: str = str(next(self._run_ids))
self._timestamp_finish: dt.datetime | None = None
self._timestamp_start: dt.datetime = dt_util.utcnow()
Expand All @@ -75,6 +77,7 @@ def finished(self) -> None:
"""Set finish time."""
self._timestamp_finish = dt_util.utcnow()
self._state = "stopped"
self._script_execution = script_execution_get()

def as_dict(self) -> dict[str, Any]:
"""Return dictionary version of this ActionTrace."""
Expand Down Expand Up @@ -109,6 +112,7 @@ def as_short_dict(self) -> dict[str, Any]:
"last_step": last_step,
"run_id": self.run_id,
"state": self._state,
"script_execution": self._script_execution,
"timestamp": {
"start": self._timestamp_start,
"finish": self._timestamp_finish,
Expand Down
13 changes: 10 additions & 3 deletions homeassistant/helpers/script.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@
)
from homeassistant.helpers.event import async_call_later, async_track_template
from homeassistant.helpers.script_variables import ScriptVariables
from homeassistant.helpers.trace import script_execution_set
from homeassistant.helpers.trigger import (
async_initialize_triggers,
async_validate_trigger_config,
Expand Down Expand Up @@ -332,15 +333,19 @@ def _step_log(self, default_message, timeout=None):
async def async_run(self) -> None:
"""Run script."""
try:
if self._stop.is_set():
return
self._log("Running %s", self._script.running_description)
for self._step, self._action in enumerate(self._script.sequence):
if self._stop.is_set():
script_execution_set("cancelled")
break
await self._async_step(log_exceptions=False)
else:
script_execution_set("finished")
except _StopScript:
pass
script_execution_set("aborted")
except Exception:
script_execution_set("error")
raise
finally:
self._finish()

Expand Down Expand Up @@ -1137,6 +1142,7 @@ async def async_run(
if self.script_mode == SCRIPT_MODE_SINGLE:
if self._max_exceeded != "SILENT":
self._log("Already running", level=LOGSEVERITY[self._max_exceeded])
script_execution_set("failed_single")
return
if self.script_mode == SCRIPT_MODE_RESTART:
self._log("Restarting")
Expand All @@ -1147,6 +1153,7 @@ async def async_run(
"Maximum number of runs exceeded",
level=LOGSEVERITY[self._max_exceeded],
)
script_execution_set("failed_max_runs")
return

# If this is a top level Script then make a copy of the variables in case they
Expand Down
27 changes: 27 additions & 0 deletions homeassistant/helpers/trace.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,10 @@ def as_dict(self) -> dict[str, Any]:
trace_id_cv: ContextVar[tuple[str, str] | None] = ContextVar(
"trace_id_cv", default=None
)
# Reason for stopped script execution
script_execution_cv: ContextVar[StopReason | None] = ContextVar(
"script_execution_cv", default=None
)


def trace_id_set(trace_id: tuple[str, str]) -> None:
Expand Down Expand Up @@ -172,6 +176,7 @@ def trace_clear() -> None:
trace_stack_cv.set(None)
trace_path_stack_cv.set(None)
variables_cv.set(None)
script_execution_cv.set(StopReason())


def trace_set_child_id(child_key: tuple[str, str], child_run_id: str) -> None:
Expand All @@ -187,6 +192,28 @@ def trace_set_result(**kwargs: Any) -> None:
node.set_result(**kwargs)


class StopReason:
"""Mutable container class for script_execution."""

script_execution: str | None = None


def script_execution_set(reason: str) -> None:
"""Set stop reason."""
data = script_execution_cv.get()
if data is None:
return
data.script_execution = reason


def script_execution_get() -> str | None:
"""Return the current trace."""
data = script_execution_cv.get()
if data is None:
return None
return data.script_execution


@contextmanager
def trace_path(suffix: str | list[str]) -> Generator:
"""Go deeper in the config tree.
Expand Down
Loading
0