5 def acquire_time_data():
7 manager = dbus.Interface(bus.get_object('org.freedesktop.systemd1', '/org/freedesktop/systemd1'), 'org.freedesktop.systemd1.Manager')
8 units = manager.ListUnits()
13 properties = dbus.Interface(bus.get_object('org.freedesktop.systemd1', i[6]), 'org.freedesktop.DBus.Properties')
15 ixt = int(properties.Get('org.freedesktop.systemd1.Unit', 'InactiveExitTimestamp'))
16 aet = int(properties.Get('org.freedesktop.systemd1.Unit', 'ActiveEnterTimestamp'))
17 axt = int(properties.Get('org.freedesktop.systemd1.Unit', 'ActiveExitTimestamp'))
18 iet = int(properties.Get('org.freedesktop.systemd1.Unit', 'InactiveEnterTimestamp'))
20 l.append((str(i[0]), ixt, aet, axt, iet))
24 def acquire_start_time():
25 properties = dbus.Interface(bus.get_object('org.freedesktop.systemd1', '/org/freedesktop/systemd1'), 'org.freedesktop.DBus.Properties')
27 startup_time = int(properties.Get('org.freedesktop.systemd1.Manager', 'StartupTimestamp'))
28 finish_time = int(properties.Get('org.freedesktop.systemd1.Manager', 'FinishTimestamp'))
30 assert startup_time <= finish_time
32 return startup_time, finish_time
34 def draw_box(context, j, k, l, m, r = 0, g = 0, b = 0):
36 context.set_source_rgb(r, g, b)
37 context.rectangle(j, k, l, m)
41 def draw_text(context, x, y, text, size = 12, r = 0, g = 0, b = 0, center = True):
44 context.set_source_rgb(r, g, b)
45 context.select_font_face("Sans", cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL)
46 context.set_font_size(size)
49 x_bearing, y_bearing, width, height = context.text_extents(text)[:4]
50 # context.move_to(x - width / 2 - x_bearing, y - height / 2 - y_bearing)
51 context.move_to(x, y - height / 2 - y_bearing)
54 context.show_text(text)
58 bus = dbus.SystemBus()
60 if len(sys.argv) <= 1 or sys.argv[1] == 'blame':
62 data = acquire_time_data()
63 s = sorted(data, key = lambda i: i[2] - i[1], reverse = True)
65 for name, ixt, aet, axt, iet in s:
67 if ixt <= 0 or aet <= 0:
73 sys.stdout.write("%6lums %s\n" % ((aet - ixt) / 1000, name))
75 elif sys.argv[1] == 'plot':
78 start_time, finish_time = acquire_start_time()
79 data = acquire_time_data()
80 s = sorted(data, key = lambda i: i[1])
82 # 1000px = 10s, 1px = 10ms
84 width = (finish_time - start_time)/10000 + border*2
88 bar_space = bar_height * 0.1
90 surface = cairo.SVGSurface(sys.stdout, width, height)
91 context = cairo.Context(surface)
93 draw_box(context, 0, 0, width, height, 1, 1, 1)
95 context.translate(border + 0.5, border + 0.5)
98 context.set_line_width(1)
99 context.set_source_rgb(0.7, 0.7, 0.7)
101 for x in range(0, (finish_time - start_time)/10000, 100):
102 context.move_to(x, 0)
103 context.line_to(x, height-border*2)
105 context.move_to(0, 0)
106 context.line_to(width-border*2, 0)
108 context.move_to(0, height-border*2)
109 context.line_to(width-border*2, height-border*2)
114 for x in range(0, (finish_time - start_time)/10000, 100):
115 draw_text(context, x, -5, "%lus" % (x/100), center = False)
119 for name, ixt, aet, axt, iet in s:
124 if ixt >= start_time and aet > ixt:
129 draw_box(context, a/10000, y, b/10000, bar_height, 1, 0, 0)
135 if aet >= start_time and axt > aet:
140 draw_box(context, a/10000, y, b/10000, bar_height, .7, .5, .5)
146 if axt >= start_time and iet > axt:
151 draw_box(context, a/10000, y, b/10000, bar_height, .6, .4, .4)
158 draw_text(context, left/10000 + 10, y + bar_height/2, name)
160 y += bar_height + bar_space
165 sys.stderr.write("Unknown verb '%s'.\n" % sys.argv[1])