diff --git a/src/fastcs/attributes/attr_r.py b/src/fastcs/attributes/attr_r.py index 37343c6ae..c6583252a 100644 --- a/src/fastcs/attributes/attr_r.py +++ b/src/fastcs/attributes/attr_r.py @@ -110,8 +110,8 @@ async def update_attribute(): try: self.log_event("Update attribute", topic=self) await update_callback(self) - except Exception as e: - logger.opt(exception=e).error("Update loop failed", attribute=self) + except Exception: + logger.error("Attribute update loop stopped", attribute=self) raise return update_attribute diff --git a/src/fastcs/attributes/attr_w.py b/src/fastcs/attributes/attr_w.py index bd5568387..a9b2cff72 100644 --- a/src/fastcs/attributes/attr_w.py +++ b/src/fastcs/attributes/attr_w.py @@ -68,6 +68,8 @@ async def put(self, setpoint: DType_T, sync_setpoint: bool = False) -> None: "Sync setpoint failed", attribute=self, setpoint=setpoint ) + self.log_event("Put complete", setpoint=setpoint, attribute=self) + async def _call_sync_setpoint_callbacks(self, setpoint: DType_T) -> None: if self._sync_setpoint_callbacks: await asyncio.gather( diff --git a/src/fastcs/control_system.py b/src/fastcs/control_system.py index 00e99c796..fcd13ada0 100644 --- a/src/fastcs/control_system.py +++ b/src/fastcs/control_system.py @@ -7,7 +7,6 @@ from IPython.terminal.embed import InteractiveShellEmbed from fastcs.controllers import BaseController, Controller -from fastcs.exceptions import FastCSError from fastcs.logging import bind_logger from fastcs.methods import Command, Scan, ScanCallback from fastcs.tracer import Tracer @@ -63,11 +62,8 @@ async def _start_scan_tasks(self): def _scan_done(self, task: asyncio.Task): try: task.result() - except Exception as e: - raise FastCSError( - "Exception raised in scan method of " - f"{self._controller.__class__.__name__}" - ) from e + except Exception: + logger.exception("Exception raised in scan task") def _stop_scan_tasks(self): for task in self._scan_tasks: diff --git a/src/fastcs/methods/scan.py b/src/fastcs/methods/scan.py index 39efd3cfc..c35850fe3 100644 --- a/src/fastcs/methods/scan.py +++ b/src/fastcs/methods/scan.py @@ -2,8 +2,11 @@ from types import MethodType from fastcs.controllers import BaseController +from fastcs.logging import bind_logger from fastcs.methods.method import Controller_T, Method +logger = bind_logger(logger_name=__name__) + UnboundScanCallback = Callable[[Controller_T], Coroutine[None, None, None]] """A Scan callback that is unbound and must be called with a `Controller` instance""" ScanCallback = Callable[[], Coroutine[None, None, None]] @@ -36,6 +39,17 @@ def _validate(self, fn: ScanCallback) -> None: async def __call__(self): return await self._fn() + @property + def fn(self): + async def scan(): + try: + return await self._fn() + except Exception: + logger.error("Scan update loop stopped", fn=self._fn) + raise + + return scan + class UnboundScan(Method[Controller_T]): """A wrapper of an unbound `Controller` method to be bound into a `Scan`. diff --git a/tests/test_control_system.py b/tests/test_control_system.py index ea9ed93bb..347e2ed35 100644 --- a/tests/test_control_system.py +++ b/tests/test_control_system.py @@ -7,7 +7,6 @@ from fastcs.control_system import FastCS, build_controller_api from fastcs.controllers import Controller from fastcs.datatypes import Int -from fastcs.exceptions import FastCSError from fastcs.methods import Command, command, scan from fastcs.util import ONCE @@ -152,8 +151,6 @@ async def raise_exception(self): task = asyncio.create_task(fastcs.serve(interactive=False)) # This allows scan time to run await asyncio.sleep(0.2) - # _scan_done should raise an exception - assert isinstance(exception_info["exception"], FastCSError) for task in fastcs._scan_tasks: internal_exception = task.exception() assert internal_exception