many updates in report code and in storage structure, this commit is broken
diff --git a/wally/result_classes.py b/wally/result_classes.py
index 62e74f0..43ae721 100644
--- a/wally/result_classes.py
+++ b/wally/result_classes.py
@@ -1,16 +1,13 @@
import abc
-import array
from typing import Dict, List, Any, Optional, Tuple, cast, Type, Iterator
-from collections import OrderedDict
import numpy
from scipy.stats.mstats_basic import NormaltestResult
-
from .suits.job import JobConfig
from .node_interfaces import IRPCNode
-from .common_types import Storable, IStorable
+from .common_types import Storable
from .utils import round_digits, Number
@@ -32,14 +29,20 @@
run_uuid: str,
nodes: List[IRPCNode],
remote_dir: str,
- idx: int) -> None:
+ idx: int,
+ keep_raw_files: bool) -> None:
self.test_type = test_type
self.params = params
self.run_uuid = run_uuid
self.nodes = nodes
self.nodes_ids = [node.node_id for node in nodes]
self.remote_dir = remote_dir
- self.storage_id = "{}_{}".format(self.test_type, idx)
+ self.keep_raw_files = keep_raw_files
+
+ if 'load' in self.params:
+ self.storage_id = "{}_{}_{}".format(self.test_type, self.params['load'], idx)
+ else:
+ self.storage_id = "{}_{}".format(self.test_type, idx)
def __eq__(self, o: object) -> bool:
if type(o) is not self.__class__:
@@ -57,27 +60,45 @@
suite_id: str = None,
job_id: str = None,
node_id: str = None,
- dev: str = None,
sensor: str = None,
+ dev: str = None,
+ metric: str = None,
tag: str = None) -> None:
self.suite_id = suite_id
self.job_id = job_id
self.node_id = node_id
- self.dev = dev
self.sensor = sensor
+ self.dev = dev
+ self.metric = metric
self.tag = tag
+ @property
+ def metric_fqdn(self) -> str:
+ return "{0.sensor}.{0.dev}.{0.metric}".format(self)
+
def __call__(self, **kwargs) -> 'DataSource':
dct = self.__dict__.copy()
dct.update(kwargs)
return self.__class__(**dct)
def __str__(self) -> str:
- return "{0.suite_id}.{0.job_id}/{0.node_id}/{0.dev}.{0.sensor}.{0.tag}".format(self)
+ return ("suite={0.suite_id},job={0.job_id},node={0.node_id}," +
+ "path={0.sensor}.{0.dev}.{0.metric},tag={0.tag}").format(self)
def __repr__(self) -> str:
return str(self)
+ @property
+ def tpl(self) -> Tuple[Optional[str], Optional[str], Optional[str], Optional[str],
+ Optional[str], Optional[str], Optional[str]]:
+ return self.suite_id, self.job_id, self.node_id, self.sensor, self.dev, self.metric, self.tag
+
+ def __eq__(self, o: object) -> bool:
+ return self.tpl == cast(DataSource, o).tpl
+
+ def __hash__(self) -> int:
+ return hash(self.tpl)
+
class TimeSeries:
"""Data series from sensor - either system sensor or from load generator tool (e.g. fio)"""
@@ -88,9 +109,9 @@
data: numpy.array,
times: numpy.array,
units: str,
+ source: DataSource,
time_units: str = 'us',
- second_axis_size: int = 1,
- source: DataSource = None) -> None:
+ raw_tag: str = 'txt') -> None:
# Sensor name. Typically DEV_NAME.METRIC
self.name = name
@@ -105,20 +126,16 @@
self.times = times
self.data = data
- # Not equal to 1 in case of 2d sensors, like latency, when each measurement is a histogram.
- self.second_axis_size = second_axis_size
-
# Raw sensor data (is provided). Like log file for fio iops/bw/lat.
self.raw = raw
-
+ self.raw_tag = raw_tag
self.source = source
def __str__(self) -> str:
res = "TS({}):\n".format(self.name)
res += " source={}\n".format(self.source)
res += " times_size={}\n".format(len(self.times))
- res += " data_size={}\n".format(len(self.data))
- res += " data_shape={}x{}\n".format(len(self.data) // self.second_axis_size, self.second_axis_size)
+ res += " data_shape={}\n".format(*self.data.shape)
return res
def __repr__(self) -> str:
@@ -139,18 +156,25 @@
self.perc_95 = None # type: float
self.perc_90 = None # type: float
self.perc_50 = None # type: float
+ self.perc_10 = None # type: float
+ self.perc_5 = None # type: float
+ self.perc_1 = None # type: float
self.min = None # type: Number
self.max = None # type: Number
# bin_center: bin_count
+ self.log_bins = False
self.bins_populations = None # type: numpy.array
- self.bins_mids = None # type: numpy.array
+
+ # bin edges, one more element that in bins_populations
+ self.bins_edges = None # type: numpy.array
+
self.data = data
def __str__(self) -> str:
res = ["{}(size = {}):".format(self.__class__.__name__, len(self.data))]
- for name in ["perc_50", "perc_90", "perc_95", "perc_99"]:
+ for name in ["perc_1", "perc_5", "perc_10", "perc_50", "perc_90", "perc_95", "perc_99"]:
res.append(" {} = {}".format(name, round_digits(getattr(self, name))))
res.append(" range {} {}".format(round_digits(self.min), round_digits(self.max)))
return "\n".join(res)
@@ -174,8 +198,7 @@
class HistoStatProps(StatProps):
"""Statistic properties for 2D timeseries with unknown data distribution and histogram as input value.
Used for latency"""
- def __init__(self, data: numpy.array, second_axis_size: int) -> None:
- self.second_axis_size = second_axis_size
+ def __init__(self, data: numpy.array) -> None:
StatProps.__init__(self, data)
@@ -196,6 +219,9 @@
res = ["NormStatProps(size = {}):".format(len(self.data)),
" distr = {} ~ {}".format(round_digits(self.average), round_digits(self.deviation)),
" confidence({0.confidence_level}) = {1}".format(self, round_digits(self.confidence)),
+ " perc_1 = {}".format(round_digits(self.perc_1)),
+ " perc_5 = {}".format(round_digits(self.perc_5)),
+ " perc_10 = {}".format(round_digits(self.perc_10)),
" perc_50 = {}".format(round_digits(self.perc_50)),
" perc_90 = {}".format(round_digits(self.perc_90)),
" perc_95 = {}".format(round_digits(self.perc_95)),
@@ -240,6 +266,10 @@
pass
@abc.abstractmethod
+ def load_sensor(self, ds: DataSource) -> TimeSeries:
+ pass
+
+ @abc.abstractmethod
def put_or_check_suite(self, suite: SuiteConfig) -> None:
pass