From d41a369d0cab819cfb7b8f9739ba31d4b270bf97 Mon Sep 17 00:00:00 2001 From: Dinis Cruz Date: Wed, 9 Oct 2024 23:39:00 +0100 Subject: [PATCH 1/2] added support for capturing on_message events in Flows and Tasks --- osbot_utils/helpers/flows/Flow.py | 32 +++++++++++++------ osbot_utils/helpers/flows/Flow__Events.py | 13 ++++++++ osbot_utils/helpers/flows/Task.py | 11 +++++-- .../helpers/flows/models/Flow__Event_Type.py | 10 +++--- tests/unit/helpers/flows/test_Flow.py | 4 +-- .../helpers/flows/test_decorator__flow.py | 6 ++-- 6 files changed, 53 insertions(+), 23 deletions(-) diff --git a/osbot_utils/helpers/flows/Flow.py b/osbot_utils/helpers/flows/Flow.py index a220edad..28946e40 100644 --- a/osbot_utils/helpers/flows/Flow.py +++ b/osbot_utils/helpers/flows/Flow.py @@ -55,7 +55,7 @@ def execute_flow(self): if self.flow_config.log_to_memory: self.logger.add_memory_logger() # todo: move to method that does pre-execute tasks - self.log_debug(f"Executing flow run '{self.f__flow_id()}''") + self.log_debug(f"Executing flow run '{self.f__flow_id()}'") try: with Stdout() as stdout: self.invoke_flow_target() @@ -102,17 +102,29 @@ def log_captured_stdout(self, stdout): print() self.print_log_messages() - def log_debug(self, message): - if self.flow_config.logging_enabled: - self.logger.debug(message) - def log_error(self, message): - if self.flow_config.logging_enabled: - self.logger.error(message) + def log_debug(self, message, task_run_id=None): + self.logger_add_message(log_level=logging.DEBUG, message=message, task_run_id=task_run_id) + + def log_error(self, message, task_run_id=None): + self.logger_add_message(log_level=logging.ERROR, message=message, task_run_id=task_run_id) - def log_info(self, message): + def log_info(self, message, task_run_id=None): + self.logger_add_message(log_level=logging.INFO, message=message, task_run_id=task_run_id) + + def logger_add_message(self, log_level, message, task_run_id=None): if self.flow_config.logging_enabled: - self.logger.info(message) + kwargs = dict(log_level = log_level , + message = message , + flow_run_id = self.flow_id, + task_run_id = task_run_id ) + flow_events.on__flow_run__message(self, **kwargs) + if log_level == logging.DEBUG: + self.logger.debug(message) + elif log_level == logging.ERROR: + self.logger.error(message) + else: + self.logger.info(message) def log_messages(self): return ansis_to_texts(self.log_messages_with_colors()) @@ -135,7 +147,7 @@ def print_log_messages(self, use_colors=True): def print_flow_finished_message(self): if self.flow_config.print_finished_message: - self.log_debug(f"Finished flow run '{self.f__flow_id()}''") + self.log_debug(f"Finished flow run '{self.f__flow_id()}'") def print_flow_return_value(self): if self.flow_config.print_none_return_value is False and self.flow_return_value is None: diff --git a/osbot_utils/helpers/flows/Flow__Events.py b/osbot_utils/helpers/flows/Flow__Events.py index e3a18569..828958e9 100644 --- a/osbot_utils/helpers/flows/Flow__Events.py +++ b/osbot_utils/helpers/flows/Flow__Events.py @@ -1,3 +1,7 @@ +from osbot_utils.utils.Str import ansis_to_texts, ansi_to_text + +from osbot_utils.utils.Dev import pprint + from osbot_utils.base_classes.Type_Safe import Type_Safe from osbot_utils.helpers.flows.models.Flow__Event import Flow__Event from osbot_utils.helpers.flows.models.Flow__Event_Type import Flow__Event_Type @@ -14,6 +18,15 @@ def on__flow__stop(self, flow): flow_event = Flow__Event(event_type=Flow__Event_Type.FLOW_STOP , event_source=flow) self.raise_event(flow_event) + def on__flow_run__message(self, flow, log_level, flow_run_id, task_run_id, message): + event_data = dict(flow_run_id = flow_run_id , + log_level = log_level , + message = message , + message_text = ansi_to_text(message) , + task_run_id = task_run_id ) + flow_event = Flow__Event(event_type=Flow__Event_Type.FLOW_MESSAGE, event_source=flow, event_data=event_data) + self.raise_event(flow_event) + def on__task__start(self, task): flow_event = Flow__Event(event_type=Flow__Event_Type.TASK_START, event_source=task) self.raise_event(flow_event) diff --git a/osbot_utils/helpers/flows/Task.py b/osbot_utils/helpers/flows/Task.py index 5272dbda..45a621eb 100644 --- a/osbot_utils/helpers/flows/Task.py +++ b/osbot_utils/helpers/flows/Task.py @@ -27,11 +27,14 @@ class Task(Type_Safe): task_error : Exception = None raise_on_error : bool = True + def log_info(self, message): + self.task_flow.log_info(message, self.task_id) + def log_debug(self, message): - self.task_flow.log_debug(message) + self.task_flow.log_debug(message, self.task_id) def log_error(self, message): - self.task_flow.log_error(message) + self.task_flow.log_error(message, self.task_id) def execute__sync(self): self.execute__before() @@ -54,6 +57,8 @@ def execute__before(self): if not self.task_id: self.task_id = self.random_task_id() + flow_events.on__task__start(self) + self.task_flow.executed_tasks.append(self) self.log_debug(f"Executing task '{f_blue(self.task_name)}'") dependency_manager = Dependency_Manager() @@ -62,7 +67,7 @@ def execute__before(self): dependency_manager.add_dependency('task_data', self.data ) dependency_manager.add_dependency('flow_data', self.task_flow.data) self.resolved_args, self.resolved_kwargs = dependency_manager.resolve_dependencies(self.task_target, *self.task_args, **self.task_kwargs) - flow_events.on__task__start(self) + def execute__task_target__sync(self): try: diff --git a/osbot_utils/helpers/flows/models/Flow__Event_Type.py b/osbot_utils/helpers/flows/models/Flow__Event_Type.py index eb969bd7..076a85fb 100644 --- a/osbot_utils/helpers/flows/models/Flow__Event_Type.py +++ b/osbot_utils/helpers/flows/models/Flow__Event_Type.py @@ -1,8 +1,8 @@ from osbot_utils.base_classes.Type_Safe import Type_Safe - class Flow__Event_Type(Type_Safe): - FLOW_START : str = 'flow_start' - FLOW_STOP : str = 'flow_stop' - TASK_START : str = 'task_start' - TASK_STOP : str = 'task_stop' \ No newline at end of file + FLOW_MESSAGE: str = 'flow_message' + FLOW_START : str = 'flow_start' + FLOW_STOP : str = 'flow_stop' + TASK_START : str = 'task_start' + TASK_STOP : str = 'task_stop' \ No newline at end of file diff --git a/tests/unit/helpers/flows/test_Flow.py b/tests/unit/helpers/flows/test_Flow.py index 4495ce16..a95642b9 100644 --- a/tests/unit/helpers/flows/test_Flow.py +++ b/tests/unit/helpers/flows/test_Flow.py @@ -27,10 +27,10 @@ def just_print_a_message(): _.flow_config.print_none_return_value = True _.flow_config.print_finished_message = True _.execute_flow() - assert ansis_to_texts(_.captured_exec_logs) == ["Executing flow run 'AN-FLOW-ID''", + assert ansis_to_texts(_.captured_exec_logs) == ["Executing flow run 'AN-FLOW-ID'", 'this is inside the flow', 'Flow return value: None', - "Finished flow run 'AN-FLOW-ID''"] + "Finished flow run 'AN-FLOW-ID'"] diff --git a/tests/unit/helpers/flows/test_decorator__flow.py b/tests/unit/helpers/flows/test_decorator__flow.py index 7ed88b5c..2159406b 100644 --- a/tests/unit/helpers/flows/test_decorator__flow.py +++ b/tests/unit/helpers/flows/test_decorator__flow.py @@ -37,7 +37,7 @@ def an_method_with_flow(name): with disable_root_loggers(): flow_1 = an_method_with_flow('world').execute() - assert flow_1.flow_return_value == [ "Executing flow run 'THE-FLOW-ID''" , + assert flow_1.flow_return_value == [ "Executing flow run 'THE-FLOW-ID'" , 'hello world' , 'this is from an TASK that found the flow' ] @@ -73,7 +73,7 @@ def an_method_with_flow(self, value): assert flow_1.flow_return_value == 42 assert type(flow_1) is Flow flow_id = flow_1.flow_id - assert flow_1.captured_logs() == [ f"Executing flow run '{flow_id}''", + assert flow_1.captured_logs() == [ f"Executing flow run '{flow_id}'", "Executing task 'exec_task_1'", 'inside task 1 with 1', 'Task return value: 2', @@ -84,6 +84,6 @@ def an_method_with_flow(self, value): "Finished task 'exec_task_2'", 'inside the flow!', 'Flow return value: 42', - f"Finished flow run '{flow_id}''"] + f"Finished flow run '{flow_id}'"] From 60705c8f0c6fa72aaab3eaf23aebbde4821e1f71 Mon Sep 17 00:00:00 2001 From: GitHub Actions Date: Wed, 9 Oct 2024 22:40:54 +0000 Subject: [PATCH 2/2] Update release badge and version file --- README.md | 2 +- osbot_utils/version | 2 +- pyproject.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 9e69d3b5..8b1cb381 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ Powerful Python util methods and classes that simplify common apis and tasks. -![Current Release](https://img.shields.io/badge/release-v1.55.0-blue) +![Current Release](https://img.shields.io/badge/release-v1.55.1-blue) [![codecov](https://codecov.io/gh/owasp-sbot/OSBot-Utils/graph/badge.svg?token=GNVW0COX1N)](https://codecov.io/gh/owasp-sbot/OSBot-Utils) diff --git a/osbot_utils/version b/osbot_utils/version index 074a4871..9abf9ebd 100644 --- a/osbot_utils/version +++ b/osbot_utils/version @@ -1 +1 @@ -v1.55.0 +v1.55.1 diff --git a/pyproject.toml b/pyproject.toml index a5c000e3..8f75d0b6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "osbot_utils" -version = "v1.55.0" +version = "v1.55.1" description = "OWASP Security Bot - Utils" authors = ["Dinis Cruz "] license = "MIT"