@@ -69,6 +69,11 @@ CPU_COLOR = (0.40, 0.55, 0.70, 1.0)
IO_COLOR = (0.76, 0.48, 0.48, 0.5)
# Disk throughput color.
DISK_TPUT_COLOR = (0.20, 0.71, 0.20, 1.0)
+
+BYTES_RECEIVED_COLOR = (0.0, 0.0, 1.0, 1.0)
+BYTES_TRANSMITTED_COLOR = (1.0, 0.0, 0.0, 1.0)
+BYTES_RECEIVE_DIFF_COLOR = (0.0, 0.0, 1.0, 0.3)
+BYTES_TRANSMIT_DIFF_COLOR = (1.0, 0.0, 0.0, 0.3)
# CPU load chart color.
FILE_OPEN_COLOR = (0.20, 0.71, 0.71, 1.0)
# Mem cached color
@@ -437,6 +442,49 @@ def render_charts(ctx, options, clip, trace, curr_y, w, h, sec_w):
curr_y = curr_y + 30 + bar_h
+ if trace.net_stats:
+ for iface, samples in trace.net_stats.items():
+ max_received_sample = max(samples, key=lambda s: s.received_bytes)
+ max_transmitted_sample = max(samples, key=lambda s: s.transmitted_bytes)
+ max_receive_diff_sample = max(samples, key=lambda s: s.receive_diff)
+ max_transmit_diff_sample = max(samples, key=lambda s: s.transmit_diff)
+
+ draw_text(ctx, "Iface: %s" % (iface), TEXT_COLOR, off_x, curr_y+20)
+ draw_legend_line(ctx, "Bytes received (max %d)" % (max_received_sample.received_bytes),
+ BYTES_RECEIVED_COLOR, off_x+150, curr_y+20, leg_s)
+ draw_legend_line(ctx, "Bytes transmitted (max %d)" % (max_transmitted_sample.transmitted_bytes),
+ BYTES_TRANSMITTED_COLOR, off_x+400, curr_y+20, leg_s)
+ draw_legend_box(ctx, "Bytes receive diff (max %d)" % (max_receive_diff_sample.receive_diff),
+ BYTES_RECEIVE_DIFF_COLOR, off_x+650, curr_y+20, leg_s)
+ draw_legend_box(ctx, "Bytes transmit diff (max %d)" % (max_transmit_diff_sample.transmit_diff),
+ BYTES_TRANSMIT_DIFF_COLOR, off_x+900, curr_y+20, leg_s)
+
+
+ chart_rect = (off_x, curr_y + 30, w, bar_h)
+ if clip_visible(clip, chart_rect):
+ draw_box_ticks(ctx, chart_rect, sec_w)
+ draw_annotations(ctx, proc_tree, trace.times, chart_rect)
+
+ if clip_visible (clip, chart_rect):
+ draw_chart (ctx, BYTES_RECEIVED_COLOR, False, chart_rect, \
+ [(sample.time, sample.received_bytes) for sample in samples], \
+ proc_tree, None)
+
+ draw_chart (ctx, BYTES_TRANSMITTED_COLOR, False, chart_rect, \
+ [(sample.time, sample.transmitted_bytes) for sample in samples], \
+ proc_tree, None)
+
+ if clip_visible (clip, chart_rect):
+ draw_chart (ctx, BYTES_RECEIVE_DIFF_COLOR, True, chart_rect, \
+ [(sample.time, sample.receive_diff) for sample in samples], \
+ proc_tree, None)
+
+ draw_chart (ctx, BYTES_TRANSMIT_DIFF_COLOR, True, chart_rect, \
+ [(sample.time, sample.transmit_diff) for sample in samples], \
+ proc_tree, None)
+
+ curr_y = curr_y + 30 + bar_h
+
# render CPU pressure chart
if trace.cpu_pressure:
max_sample_avg = max (trace.cpu_pressure, key = lambda s: s.avg10)
@@ -48,6 +48,7 @@ class Trace:
self.filename = None
self.parent_map = None
self.mem_stats = []
+ self.net_stats = []
self.monitor_disk = None
self.cpu_pressure = []
self.io_pressure = []
@@ -557,6 +558,21 @@ def _parse_monitor_disk_log(file):
return disk_stats
+
+def _parse_reduced_net_log(file):
+ net_stats = {}
+ for time, lines in _parse_timed_blocks(file):
+
+ for line in lines:
+ parts = line.split()
+ iface = parts[0][:-1]
+ if iface not in net_stats:
+ net_stats[iface] = [NetSample(time, iface, int(parts[1]), int(parts[2]), int(parts[3]), int(parts[4]))]
+ else:
+ net_stats[iface].append(NetSample(time, iface, int(parts[1]), int(parts[2]), int(parts[3]), int(parts[4])))
+ return net_stats
+
+
def _parse_pressure_logs(file, filename):
"""
Parse file for "some" pressure with 'avg10', 'avg60' 'avg300' and delta total values
@@ -767,6 +783,8 @@ def _do_parse(writer, state, filename, file):
state.cmdline = _parse_cmdline_log(writer, file)
elif name == "monitor_disk.log":
state.monitor_disk = _parse_monitor_disk_log(file)
+ elif name == "reduced_proc_net.log":
+ state.net_stats = _parse_reduced_net_log(file)
#pressure logs are in a subdirectory
elif name == "cpu.log":
state.cpu_pressure = _parse_pressure_logs(file, name)
@@ -37,6 +37,16 @@ class CPUSample:
return str(self.time) + "\t" + str(self.user) + "\t" + \
str(self.sys) + "\t" + str(self.io) + "\t" + str (self.swap)
+
+class NetSample:
+ def __init__(self, time, iface, received_bytes, transmitted_bytes, receive_diff, transmit_diff):
+ self.time = time
+ self.iface = iface
+ self.received_bytes = received_bytes
+ self.transmitted_bytes = transmitted_bytes
+ self.receive_diff = receive_diff
+ self.transmit_diff = transmit_diff
+
class CPUPressureSample:
def __init__(self, time, avg10, avg60, avg300, deltaTotal):
self.time = time