def add_output(self, additive=None, complete=None): """Add iteration's custom output data. This saves custom output data to task results. The main way to get this data processed is to find it in HTML report ("Scenario Data" tab), where it is displayed by tables or various charts (StackedArea, Lines, Pie). Take a look at "Processing Output Charts" section of Rally Plugins Reference to find explanations and examples about additive and complete output types and how to display this output data by specific widgets. Here is a simple example how to add both additive and complete data and display them by StackedArea widget in HTML report: .. code-block:: python self.add_output( additive={"title": "Additive data in StackedArea", "description": "Iterations trend for foo and bar", "chart_plugin": "StackedArea", "data": [["foo", 12], ["bar", 34]]}, complete={"title": "Complete data as stacked area", "description": "Data is shown as-is in StackedArea", "chart_plugin": "StackedArea", "data": [["foo", [[0, 5], [1, 42], [2, 15]]], ["bar", [[0, 2], [1, 1.3], [2, 5]]]], "label": "Y-axis label text", "axis_label": "X-axis label text"}) :param additive: dict with additive output :param complete: dict with complete output :raises RallyException: if output has wrong format """ for key, value in (("additive", additive), ("complete", complete)): if value: message = charts.validate_output(key, value) if message: raise exceptions.RallyException(message) self._output[key].append(value)
def add_output(self, additive=None, complete=None): """Add iteration values for additive output. :param additive: dict with additive output :param complete: dict with complete output :raises RallyException: When additive or complete has wrong format """ for key, value in (("additive", additive), ("complete", complete)): if value: message = charts.validate_output(key, value) if message: raise exceptions.RallyException(message) self._output[key].append(value)
def add_output(self, additive=None, complete=None): """Save custom output. :param additive: dict with additive output :param complete: dict with complete output :raises RallyException: if output has wrong format """ if "output" not in self._result: self._result["output"] = {"additive": [], "complete": []} for key, value in (("additive", additive), ("complete", complete)): if value: message = charts.validate_output(key, value) if message: raise exceptions.RallyException(message) self._result["output"][key].append(value)
def _result_has_valid_schema(self, result): """Check whatever result has valid schema or not.""" # NOTE(boris-42): We can't use here jsonschema, this method is called # to check every iteration result schema. And this # method works 200 times faster then jsonschema # which totally makes sense. for key, proper_type in self._RESULT_SCHEMA["fields"]: if key not in result: LOG.warning("'%s' is not result" % key) return False if not isinstance(result[key], proper_type): LOG.warning( "Task %(uuid)s | result['%(key)s'] has wrong type " "'%(actual_type)s', should be '%(proper_type)s'" % { "uuid": self.task["uuid"], "key": key, "actual_type": type(result[key]), "proper_type": proper_type.__name__ }) return False for action, value in result["atomic_actions"].items(): if not isinstance(value, float): LOG.warning( "Task %(uuid)s | Atomic action %(action)s has wrong type " "'%(type)s', should be 'float'" % { "uuid": self.task["uuid"], "action": action, "type": type(value) }) return False for e in result["error"]: if not isinstance(e, str): LOG.warning( "error value has wrong type '%s', should be 'str'" % type(e)) return False for key in ("additive", "complete"): if key not in result["output"]: LOG.warning("Task %(uuid)s | Output missing key '%(key)s'" % { "uuid": self.task["uuid"], "key": key }) return False type_ = type(result["output"][key]) if type_ != list: LOG.warning( "Task %(uuid)s | Value of result['output']['%(key)s'] " "has wrong type '%(type)s', must be 'list'" % { "uuid": self.task["uuid"], "key": key, "type": type_.__name__ }) return False for key in result["output"]: for output_data in result["output"][key]: message = charts.validate_output(key, output_data) if message: LOG.warning("Task %(uuid)s | %(message)s" % { "uuid": self.task["uuid"], "message": message }) return False return True
def _result_has_valid_schema(self, result): """Check whatever result has valid schema or not.""" # NOTE(boris-42): We can't use here jsonschema, this method is called # to check every iteration result schema. And this # method works 200 times faster then jsonschema # which totally makes sense. for key, proper_type in self._RESULT_SCHEMA["fields"]: if key not in result: LOG.warning("'%s' is not result" % key) return False if not isinstance(result[key], proper_type): LOG.warning( "Task %(uuid)s | result['%(key)s'] has wrong type " "'%(actual_type)s', should be '%(proper_type)s'" % {"uuid": self.task["uuid"], "key": key, "actual_type": type(result[key]), "proper_type": proper_type.__name__}) return False for action, value in result["atomic_actions"].items(): if not isinstance(value, float): LOG.warning( "Task %(uuid)s | Atomic action %(action)s has wrong type " "'%(type)s', should be 'float'" % {"uuid": self.task["uuid"], "action": action, "type": type(value)}) return False for e in result["error"]: if not isinstance(e, str): LOG.warning("error value has wrong type '%s', should be 'str'" % type(e)) return False for key in ("additive", "complete"): if key not in result["output"]: LOG.warning("Task %(uuid)s | Output missing key '%(key)s'" % {"uuid": self.task["uuid"], "key": key}) return False type_ = type(result["output"][key]) if type_ != list: LOG.warning( "Task %(uuid)s | Value of result['output']['%(key)s'] " "has wrong type '%(type)s', must be 'list'" % {"uuid": self.task["uuid"], "key": key, "type": type_.__name__}) return False for key in result["output"]: for output_data in result["output"][key]: message = charts.validate_output(key, output_data) if message: LOG.warning("Task %(uuid)s | %(message)s" % {"uuid": self.task["uuid"], "message": message}) return False return True
def result_has_valid_schema(self, result): """Check whatever result has valid schema or not.""" # NOTE(boris-42): We can't use here jsonschema, this method is called # to check every iteration result schema. And this # method works 200 times faster then jsonschema # which totally makes sense. _RESULT_SCHEMA = { "fields": [("duration", float), ("timestamp", float), ("idle_duration", float), ("output", dict), ("atomic_actions", list), ("error", list)] } for key, proper_type in _RESULT_SCHEMA["fields"]: if key not in result: LOG.warning("'%s' is not result" % key) return False if not isinstance(result[key], proper_type): LOG.warning( "Task %(uuid)s | result['%(key)s'] has wrong type " "'%(actual_type)s', should be '%(proper_type)s'" % { "uuid": self.task["uuid"], "key": key, "actual_type": type(result[key]), "proper_type": proper_type.__name__ }) return False actions_list = copy.deepcopy(result["atomic_actions"]) for action in actions_list: for key in ("name", "started_at", "finished_at", "children"): if key not in action: LOG.warning("Task %(uuid)s | Atomic action %(action)s " "missing key '%(key)s'" % { "uuid": self.task["uuid"], "action": action, "key": key }) return False for key in ("started_at", "finished_at"): if not isinstance(action[key], float): LOG.warning( "Task %(uuid)s | Atomic action %(action)s has " "wrong type '%(type)s', should be 'float'" % { "uuid": self.task["uuid"], "action": action, "type": type(action[key]) }) return False if action["children"]: actions_list.extend(action["children"]) for e in result["error"]: if not isinstance(e, (six.string_types, six.text_type)): LOG.warning( "error value has wrong type '%s', should be 'str'" % type(e)) return False for key in ("additive", "complete"): if key not in result["output"]: LOG.warning("Task %(uuid)s | Output missing key '%(key)s'" % { "uuid": self.task["uuid"], "key": key }) return False type_ = type(result["output"][key]) if type_ != list: LOG.warning( "Task %(uuid)s | Value of result['output']['%(key)s'] " "has wrong type '%(type)s', must be 'list'" % { "uuid": self.task["uuid"], "key": key, "type": type_.__name__ }) return False for key in result["output"]: for output_data in result["output"][key]: message = charts.validate_output(key, output_data) if message: LOG.warning("Task %(uuid)s | %(message)s" % { "uuid": self.task["uuid"], "message": message }) return False return True
def test_validate_output(self, args, expected=None): self.assertEqual(expected, charts.validate_output(*args))
def result_has_valid_schema(self, result): """Check whatever result has valid schema or not.""" # NOTE(boris-42): We can't use here jsonschema, this method is called # to check every iteration result schema. And this # method works 200 times faster then jsonschema # which totally makes sense. _RESULT_SCHEMA = { "fields": [("duration", float), ("timestamp", float), ("idle_duration", float), ("output", dict), ("atomic_actions", list), ("error", list)] } for key, proper_type in _RESULT_SCHEMA["fields"]: if key not in result: LOG.warning("'%s' is not result" % key) return False if not isinstance(result[key], proper_type): LOG.warning( "Task %(uuid)s | result['%(key)s'] has wrong type " "'%(actual_type)s', should be '%(proper_type)s'" % {"uuid": self.task["uuid"], "key": key, "actual_type": type(result[key]), "proper_type": proper_type.__name__}) return False actions_list = copy.deepcopy(result["atomic_actions"]) for action in actions_list: for key in ("name", "started_at", "finished_at", "children"): if key not in action: LOG.warning( "Task %(uuid)s | Atomic action %(action)s " "missing key '%(key)s'" % {"uuid": self.task["uuid"], "action": action, "key": key}) return False for key in ("started_at", "finished_at"): if not isinstance(action[key], float): LOG.warning( "Task %(uuid)s | Atomic action %(action)s has " "wrong type '%(type)s', should be 'float'" % {"uuid": self.task["uuid"], "action": action, "type": type(action[key])}) return False if action["children"]: actions_list.extend(action["children"]) for e in result["error"]: if not isinstance(e, (six.string_types, six.text_type)): LOG.warning("error value has wrong type '%s', should be 'str'" % type(e)) return False for key in ("additive", "complete"): if key not in result["output"]: LOG.warning("Task %(uuid)s | Output missing key '%(key)s'" % {"uuid": self.task["uuid"], "key": key}) return False type_ = type(result["output"][key]) if type_ != list: LOG.warning( "Task %(uuid)s | Value of result['output']['%(key)s'] " "has wrong type '%(type)s', must be 'list'" % {"uuid": self.task["uuid"], "key": key, "type": type_.__name__}) return False for key in result["output"]: for output_data in result["output"][key]: message = charts.validate_output(key, output_data) if message: LOG.warning("Task %(uuid)s | %(message)s" % {"uuid": self.task["uuid"], "message": message}) return False return True