Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 9 additions & 7 deletions pybootchartgui/draw.py
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ def draw_box_ticks(ctx, rect, sec_w):

ctx.set_line_cap(cairo.LINE_CAP_BUTT)

def draw_annotations(ctx, proc_tree, times, rect):
def draw_annotations(ctx, proc_tree, times, notes, rect):
ctx.set_line_cap(cairo.LINE_CAP_SQUARE)
ctx.set_source_rgba(*ANNOTATION_COLOR)
ctx.set_dash([4, 4])
Expand All @@ -214,6 +214,8 @@ def draw_annotations(ctx, proc_tree, times, rect):
ctx.move_to(rect[0] + x, rect[1] + 1)
ctx.line_to(rect[0] + x, rect[1] + rect[3] - 1)
ctx.stroke()
if notes is not None and time in notes:
draw_text(ctx, notes[time], ANNOTATION_COLOR, x, rect[1] - 15)

ctx.set_line_cap(cairo.LINE_CAP_BUTT)
ctx.set_dash([])
Expand Down Expand Up @@ -307,7 +309,7 @@ def render_charts(ctx, options, clip, trace, curr_y, w, h, sec_w):
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)
draw_annotations (ctx, proc_tree, trace.times, None, chart_rect)
draw_chart (ctx, IO_COLOR, True, chart_rect, \
[(sample.time, sample.user + sample.sys + sample.io) for sample in trace.cpu_stats], \
proc_tree, None)
Expand All @@ -326,7 +328,7 @@ def render_charts(ctx, options, clip, trace, curr_y, w, h, sec_w):
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)
draw_annotations (ctx, proc_tree, trace.times, None, chart_rect)
draw_chart (ctx, IO_COLOR, True, chart_rect, \
[(sample.time, sample.util) for sample in trace.disk_stats], \
proc_tree, None)
Expand Down Expand Up @@ -360,7 +362,7 @@ def render_charts(ctx, options, clip, trace, curr_y, w, h, sec_w):
draw_legend_line(ctx, "Swap (scale: %u MiB)" % max([(sample.records['SwapTotal'] - sample.records['SwapFree'])/1024 for sample in mem_stats]), \
MEM_SWAP_COLOR, off_x + 480, curr_y+20, leg_s)
draw_box_ticks(ctx, chart_rect, sec_w)
draw_annotations(ctx, proc_tree, trace.times, chart_rect)
draw_annotations(ctx, proc_tree, trace.times, None, chart_rect)
draw_chart(ctx, MEM_BUFFERS_COLOR, True, chart_rect, \
[(sample.time, sample.records['MemTotal'] - sample.records['MemFree']) for sample in trace.mem_stats], \
proc_tree, [0, mem_scale])
Expand Down Expand Up @@ -415,7 +417,7 @@ def render(ctx, options, xscale, trace):
if proc_tree.taskstats and options.cumulative:
proc_height -= CUML_HEIGHT

draw_process_bar_chart(ctx, clip, options, proc_tree, trace.times,
draw_process_bar_chart(ctx, clip, options, proc_tree, trace.times, trace.notes,
curr_y, w, proc_height, sec_w)

curr_y = proc_height
Expand All @@ -434,7 +436,7 @@ def render(ctx, options, xscale, trace):
if clip_visible (clip, cuml_rect):
draw_cuml_graph(ctx, proc_tree, cuml_rect, duration, sec_w, STAT_TYPE_IO)

def draw_process_bar_chart(ctx, clip, options, proc_tree, times, curr_y, w, h, sec_w):
def draw_process_bar_chart(ctx, clip, options, proc_tree, times, notes, curr_y, w, h, sec_w):
header_size = 0
if not options.kernel_only:
draw_legend_box (ctx, "Running (%cpu)",
Expand All @@ -457,7 +459,7 @@ def draw_process_bar_chart(ctx, clip, options, proc_tree, times, curr_y, w, h, s
else:
nsec = 5
draw_sec_labels (ctx, chart_rect, sec_w, nsec)
draw_annotations (ctx, proc_tree, times, chart_rect)
draw_annotations (ctx, proc_tree, times, notes, chart_rect)

y = curr_y + 60
for root in proc_tree.process_tree:
Expand Down
54 changes: 42 additions & 12 deletions pybootchartgui/parsing.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
from time import clock
from collections import defaultdict
from functools import reduce
from datetime import datetime

from .samples import *
from .process_tree import ProcessTree
Expand All @@ -48,6 +49,7 @@ def __init__(self, writer, paths, options):
self.filename = None
self.parent_map = None
self.mem_stats = None
self.notes = {}

parse_paths (writer, self, paths)
if not self.valid():
Expand All @@ -64,29 +66,57 @@ def __init__(self, writer, paths, options):
else:
idle = None

# Annotate other times as the first start point of given process lists
self.times = [ idle ]
if options.annotate:
for procnames in options.annotate:
names = [x[:15] for x in procnames.split(",")]
for proc in self.ps_stats.process_map.values():
if proc.cmd in names:
self.times.append(proc.start_time)
break
else:
self.times.append(None)

self.proc_tree = ProcessTree(writer, self.kernel, self.ps_stats,
self.ps_stats.sample_period,
self.headers.get("profile.process"),
options.prune, idle, self.taskstats,
self.parent_map is not None)

# Annotate other times as the first start point of given process lists
self.times = [ idle ]
if options.annotate:
if os.path.isfile(options.annotate[0]):
self.addAnnotationsFromFile(options)
else:
for procnames in options.annotate:
try:
self.times.append(self.convertTimeToCoord(procnames))
except ValueError:
names = [x[:15] for x in procnames.split(",")]
for proc in self.ps_stats.process_map.values():
if proc.cmd in names:
self.times.append(proc.start_time)
break
else:
self.times.append(None)

if self.kernel is not None:
self.kernel_tree = ProcessTree(writer, self.kernel, None, 0,
self.headers.get("profile.process"),
False, None, None, True)

def addAnnotationsFromFile(self, options):
labels = []
times = []
with open(options.annotate[0]) as f:
for line in f:
labels.append(line.split('\t')[0].strip())
times.append(line.split('\t')[1].strip())
for (l, t) in zip(labels, times):
time = self.convertTimeToCoord(t)
if time not in self.times:
self.times.append(time)
if time not in self.notes:
self.notes[time] = l
else:
self.notes[time] = self.notes[time] + '/' + l

def convertTimeToCoord(self, time):
title = re.search(r'\d{2}:\d{2}:\d{2}', self.headers.get("title")).group()
endCoord = datetime.strptime(title, '%H:%M:%S')
startCoord = datetime.strptime(time, '%H:%M:%S')
return self.proc_tree.duration - (endCoord - startCoord).seconds * 100

def valid(self):
return self.headers != None and self.disk_stats != None and \
self.ps_stats != None and self.cpu_stats != None
Expand Down