From 59882146fbd749c9b9b503bc1adf44d0dd138791 Mon Sep 17 00:00:00 2001 From: Jakub Rozek Date: Fri, 6 Oct 2023 04:19:55 +0200 Subject: [PATCH 1/3] JsonRunSummaryFormatter: Format all results --- .../JsonRunSummaryFormatter.py | 31 ++++++++++--------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/lnst/Controller/RunSummaryFormatters/JsonRunSummaryFormatter.py b/lnst/Controller/RunSummaryFormatters/JsonRunSummaryFormatter.py index 8b8422366..907c8e6b7 100644 --- a/lnst/Controller/RunSummaryFormatters/JsonRunSummaryFormatter.py +++ b/lnst/Controller/RunSummaryFormatters/JsonRunSummaryFormatter.py @@ -3,7 +3,13 @@ import json from lnst.Controller.Recipe import RecipeRun -from lnst.Controller.RecipeResults import DeviceMethodCallResult, JobResult, JobStartResult, MeasurementResult, Result +from lnst.Controller.RecipeResults import ( + DeviceMethodCallResult, + JobResult, + JobStartResult, + MeasurementResult, + BaseResult, +) from .RunSummaryFormatter import RunSummaryFormatter @@ -32,7 +38,7 @@ def format_run(self, run: RecipeRun) -> str: indent=4 if self.pretty else None, ) - def _transform_result(self, result: Result) -> Optional[dict]: + def _transform_result(self, result: BaseResult) -> Optional[dict]: ret = { "result": str(result.result), } @@ -85,23 +91,20 @@ def _transform_result(self, result: Result) -> Optional[dict]: } elif result.measurement_type == "linuxperf": # linuxperf measurement just generates files - return None + measurement_data = {} else: logging.warning(f"unhandled measurement result type: {result.measurement_type}") - return None + measurement_data = None return ret | { "type": "measurement", "measurement_type": result.measurement_type, "data": measurement_data, } - elif isinstance(result, Result): - if result.data is None: - return ret | { - "type": "unknown", - "description": result.description, - } - else: - logging.warning(f"unhandled recipe result type: {repr(result)} with data of type {type(result.data)}") else: - logging.warning(f"unhandled recipe result type: {repr(result)}") - return None + if result.data is not None: + logging.warning(f"unhandled recipe result type: {repr(result)}, can't format its data") + + return ret | { + "type": "unknown", + "description": result.description, + } From d60d1809f47c95dbcedc1545e40b0ed604dc9aa0 Mon Sep 17 00:00:00 2001 From: Jakub Rozek Date: Fri, 6 Oct 2023 04:41:16 +0200 Subject: [PATCH 2/3] JsonRunSummaryFormatter: Add unhandled device config results --- .../JsonRunSummaryFormatter.py | 44 +++++++++++++++---- 1 file changed, 36 insertions(+), 8 deletions(-) diff --git a/lnst/Controller/RunSummaryFormatters/JsonRunSummaryFormatter.py b/lnst/Controller/RunSummaryFormatters/JsonRunSummaryFormatter.py index 907c8e6b7..1b35b5616 100644 --- a/lnst/Controller/RunSummaryFormatters/JsonRunSummaryFormatter.py +++ b/lnst/Controller/RunSummaryFormatters/JsonRunSummaryFormatter.py @@ -4,6 +4,9 @@ from lnst.Controller.Recipe import RecipeRun from lnst.Controller.RecipeResults import ( + DeviceAttrSetResult, + DeviceConfigResult, + DeviceCreateResult, DeviceMethodCallResult, JobResult, JobStartResult, @@ -58,18 +61,43 @@ def _transform_result(self, result: BaseResult) -> Optional[dict]: "action": "start" if isinstance(result, JobStartResult) else "end", "job": job_info, } - elif isinstance(result, DeviceMethodCallResult): + elif isinstance(result, DeviceConfigResult): + if isinstance(result, DeviceCreateResult): + action_info = { + "action": "create", + "device": { + "cls_name": result.device._dev_cls.__name__, + "args": [repr(arg) for arg in result.device._dev_args], + "kwargs": [f"{k}={v!r}" for k, v in result.device._dev_kwargs.items()], + }, + } + elif isinstance(result, DeviceMethodCallResult): + action_info = { + "action": "method_call", + "method": { + "name": result.method_name, + "args": [repr(arg) for arg in result.args], + "kwargs": [f"{k}={v!r}" for k, v in result.kwargs.items()], + }, + } + elif isinstance(result, DeviceAttrSetResult): + action_info = { + "action": "attr_set", + "attr": { + "name": result.attr_name, + "value": result.value, + "old_value": result.old_value, + }, + } + else: + logging.warning(f"unhandled device config result: {result.__class__.__name__}") + action_info = {"action": "unknown"} return ret | { - "type": "device_method_call", + "type": "device_config", "host": result.device.host.hostid, "netns": result.device.netns.name if result.device.netns and result.device.netns.name else "", "dev_id": result.device._id, - "method": { - "name": result.method_name, - "args": [repr(arg) for arg in result.args], - "kwargs": [f"{k}={v!r}" for k, v in result.kwargs.items()], - }, - } + } | action_info elif isinstance(result, MeasurementResult): if result.measurement_type == "ping": measurement_data = result.data From e4937c1f3e0fe297b63494fc1a08a29d07526768 Mon Sep 17 00:00:00 2001 From: Jakub Rozek Date: Mon, 9 Oct 2023 12:59:16 +0200 Subject: [PATCH 3/3] BaselineEvaluator: Include measurement class name in comparison --- lnst/RecipeCommon/Perf/Evaluators/BaselineEvaluator.py | 1 + 1 file changed, 1 insertion(+) diff --git a/lnst/RecipeCommon/Perf/Evaluators/BaselineEvaluator.py b/lnst/RecipeCommon/Perf/Evaluators/BaselineEvaluator.py index 1dc900cff..6c072b55f 100644 --- a/lnst/RecipeCommon/Perf/Evaluators/BaselineEvaluator.py +++ b/lnst/RecipeCommon/Perf/Evaluators/BaselineEvaluator.py @@ -78,6 +78,7 @@ def evaluate_group_results( comparisons.extend( [ { + "measurement_type": result.measurement.__class__.__name__, "current_result": result, "baseline_result": baseline, "comparison_result": metric.result,