Merge pull request #5 from Mirantis/bottleneck
sensors correction, postprocessing
diff --git a/scripts/postprocessing/bottleneck.py b/scripts/postprocessing/bottleneck.py
new file mode 100644
index 0000000..8b94f2f
--- /dev/null
+++ b/scripts/postprocessing/bottleneck.py
@@ -0,0 +1,111 @@
+""" Analize test results for finding bottlenecks """
+
+import sys
+import argparse
+
+import texttable as TT
+
+from collections import namedtuple
+
+
+Record = namedtuple("Record", ['name', 'max_value'])
+
+critical_values = [
+ Record("io_queue", 1),
+ Record("procs_blocked", 1),
+ Record("mem_usage_percent", 0.8)
+ ]
+
+def load_results(begin_time, end_time, rfile):
+ """ Read raw results from dir and return
+ data from provided period"""
+ results = {}
+
+ with open(rfile, "r") as f:
+ for line in f:
+
+ if len(line) <= 1:
+ continue
+ ttime, _, raw_data = line.partition(" : ")
+ raw_data = raw_data.strip('"\n\r')
+ itime = float(ttime)
+ if itime >= begin_time and itime <= end_time:
+ addr, data = eval(raw_data)
+ sid = data.pop("source_id")
+ data.pop("time")
+ serv = "{0}({1})".format(addr[0], sid)
+ serv_data = results.setdefault(serv, {})
+ for key, value in data.items():
+ # select device and metric names
+ dev, _, metric = key.partition(".")
+ # create dict for metric
+ metric_dict = serv_data.setdefault(metric, {})
+ # set value for metric on dev
+ cur_val = metric_dict.setdefault(dev, [])
+ cur_val.append(value)
+ print results
+ return results
+
+
+
+def print_bottlenecks(data, params):
+ """ Print bottlenecks in table format,
+ search in data by fields in params"""
+ tab = TT.Texttable()
+ tab.set_deco(tab.VLINES)
+
+ header = ["Server, device", "Critical value"]
+ tab.add_row(header)
+ tab.header = header
+
+ rows = []
+ val_format = "{0}: {1}, {2} times it was >= {3}"
+ for node, metrics in data.items():
+ node_rows = []
+ for metric, max_value in params:
+ if metric in metrics:
+ item = metrics[metric]
+ # find max val for dev
+ # count times it was > max_value
+ for dev, vals in item.items():
+ num_l = 0
+ max_v = -1
+ for val in vals:
+ if val >= max_value:
+ num_l += 1
+ if max_v < val:
+ max_v = val
+ if num_l > 0:
+ c_val = val_format.format(metric, max_v,
+ num_l, max_value)
+ node_rows.append([dev, c_val])
+ if len(node_rows) > 0:
+ rows.append([node, ""])
+ rows.extend(node_rows)
+
+ for row in rows:
+ tab.add_row(row)
+
+ print tab.draw()
+
+
+
+def parse_args(args):
+ parser = argparse.ArgumentParser()
+ parser.add_argument('-t', '--time_period', nargs=2,
+ type=float,
+ help="Begin and end time for tests")
+ parser.add_argument('sensors_result', type=str,
+ default=None, nargs='?')
+ return parser.parse_args(args[1:])
+
+
+def main(argv):
+ opts = parse_args(argv)
+
+ results = load_results(opts.time_period[0], opts.time_period[1], opts.sensors_result)
+
+ print_bottlenecks(results, critical_values)
+
+if __name__ == "__main__":
+ exit(main(sys.argv))
diff --git a/wally/sensors/sensors/psram_sensors.py b/wally/sensors/sensors/psram_sensors.py
index cbd85e6..7e4f8b9 100644
--- a/wally/sensors/sensors/psram_sensors.py
+++ b/wally/sensors/sensors/psram_sensors.py
@@ -56,7 +56,7 @@
sys_total = get_ram_size()
usage = float(total) / float(sys_total)
- sensor_name = "{0}.{1}".format(dev_name, pid)
+ sensor_name = "{0}({1})".format(dev_name, pid)
results[sensor_name + ".private_mem"] = SensorInfo(private, False)
results[sensor_name + ".shared_mem"] = SensorInfo(shared, False)
diff --git a/wally/sensors/sensors/syscpu_sensors.py b/wally/sensors/sensors/syscpu_sensors.py
index d3da02b..3324f67 100644
--- a/wally/sensors/sensors/syscpu_sensors.py
+++ b/wally/sensors/sensors/syscpu_sensors.py
@@ -17,10 +17,13 @@
(4, 'idle_time', True),
]
+# extended values, on 1 pos in line
+cpu_extvalues = ['procs_blocked']
+
@provides("system-cpu")
def syscpu_stat(disallowed_prefixes=('intr', 'ctxt', 'btime', 'processes',
- 'procs_running', 'procs_blocked', 'softirq'),
+ 'procs_running', 'softirq'),
allowed_prefixes=None):
results = {}
@@ -33,8 +36,13 @@
allowed_prefixes)
if dev_ok:
- for pos, name, accum_val in io_values_pos:
- sensor_name = "{0}.{1}".format(dev_name, name)
- results[sensor_name] = SensorInfo(int(vals[pos]), accum_val)
+ if dev_name in cpu_extvalues:
+ # for single values
+ sensor_name = "cpu.{0}".format(dev_name)
+ results[sensor_name] = SensorInfo(int(vals[1]), False)
+ else:
+ for pos, name, accum_val in io_values_pos:
+ sensor_name = "{0}.{1}".format(dev_name, name)
+ results[sensor_name] = SensorInfo(int(vals[pos]), accum_val)
return results
diff --git a/wally/sensors/sensors/sysram_sensors.py b/wally/sensors/sensors/sysram_sensors.py
index c78eddd..8df7acc 100644
--- a/wally/sensors/sensors/sysram_sensors.py
+++ b/wally/sensors/sensors/sysram_sensors.py
@@ -23,12 +23,21 @@
results = {}
for line in open('/proc/meminfo'):
vals = line.split()
- dev_name = vals[0]
+ dev_name = vals[0].rstrip(":")
dev_ok = is_dev_accepted(dev_name,
disallowed_prefixes,
allowed_prefixes)
+ title = "ram.{0}".format(dev_name)
+
if dev_ok:
- results[dev_name] = SensorInfo(int(vals[1]), False)
+ results[title] = SensorInfo(int(vals[1]), False)
+
+ if 'ram.MemFree' in results and 'ram.MemTotal' in results:
+ used = results['ram.MemTotal'].value - results['ram.MemFree'].value
+ usage = used / results['ram.MemTotal'].value
+ results["ram.usage_percent"] = SensorInfo(usage, False)
return results
+
+print sysram_stat()