Created
April 10, 2010 23:41
-
-
Save sesam/362374 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
import os | |
import sys | |
import cairo | |
SSD_HOST = "max" | |
HDD_HOST = "sam" | |
BOOTCHARTS = "public_html/daily-bootcharts" | |
INSTALLER = "public_html/daily-installer" | |
POINTS = ['boot', 'kernel', 'plumbing', 'xorg', 'desktop', 'kernelinit'] | |
CAPTIONS = { | |
'boot': 'Boot Time', | |
'kernel': 'Kernel', | |
'plumbing': 'Plumbing', | |
'xorg': 'X.org', | |
'desktop': 'Desktop', | |
'kernelinit': 'Kernel Init' | |
} | |
def main(dates): | |
start = min(int(float(date)) for date in dates) | |
end = max(int(float(date)) for date in dates) | |
all_dates = [] | |
for day in range(end, start-1, -1): | |
year = day / 10000 | |
month = day % 10000 / 100 | |
dom = day % 100 | |
if month > 12: | |
continue | |
elif month in (1, 3, 5, 7, 8, 10, 12): | |
if dom > 31: | |
continue | |
elif month in (2, 4, 6, 9, 11): | |
if dom > 30: | |
continue | |
elif (year % 4 == 0) and ((year % 100 != 0) or (year % 400 == 0)): | |
if dom > 29: | |
continue | |
else: | |
if dom > 28: | |
continue | |
today = [ date for date in dates if int(float(date))==day ] | |
if len(today): | |
today.reverse() | |
all_dates.extend(today) | |
else: | |
all_dates.append(str(day)) | |
f = open("%s/index.html" % BOOTCHARTS, "w") | |
try: | |
include(f, "header.html", {'title': "Daily bootcharts" }) | |
include(f, "bootcharts.html") | |
times = {} | |
for host in (SSD_HOST,HDD_HOST): | |
times[host] = {} | |
for point in POINTS: | |
times[host][point] = [] | |
for point in POINTS: | |
print >>f, "<img src=\"%s.svg\">" % point | |
print >>f, "<table>" | |
print >>f, "<tr>" | |
print >>f, "<th rowspan=\"2\"></th>" | |
print >>f, "<th colspan=\"6\" class=\"mast\">%s (SSD)</th>" % SSD_HOST | |
print >>f, "<th colspan=\"6\" class=\"mast\">%s (HDD)</th>" % HDD_HOST | |
print >>f, "</tr>" | |
print >>f, "<tr>" | |
for point in POINTS: | |
print >>f, "<th class=\"%s\">%s</th>" % (point, CAPTIONS[point]) | |
for point in POINTS: | |
print >>f, "<th class=\"%s\">%s</th>" % (point, CAPTIONS[point]) | |
print >>f, "</tr>" | |
for date in all_dates: | |
print >>f, "<tr>" | |
if date in dates: | |
print >>f, "<th rowspan=\"2\">%s</th>" % date | |
for host in (SSD_HOST, HDD_HOST): | |
if not os.path.isfile("%s/%s-%s.times" % (BOOTCHARTS, date, host)): | |
print >>f, "<td rowspan=\"2\" colspan=\"6\"></td>" | |
continue | |
t = open("%s/%s-%s.times" % (BOOTCHARTS, date, host)) | |
try: | |
try: | |
boot_time = float(t.readline()) / 100 | |
print >>f, "<td class=\"%s\">%.2fs</td>" % (POINTS[0],boot_time) | |
times[host][POINTS[0]].append((date, boot_time)) | |
except ValueError: | |
print >>f, "<td class=\"%s\"></td>" % point | |
boot_time = 0.0 | |
last = 0.0 | |
for point in POINTS[1:-2]: | |
try: | |
time = float(t.readline()) / 100 | |
times[host][point].append((date, time-last)) | |
print >>f, "<td class=\"%s\">%.2fs</td>" % (point, time-last) | |
last = time | |
except ValueError: | |
print >>f, "<td class=\"%s\"></td>" % point | |
times[host][POINTS[-2]].append((date, boot_time-last)) | |
print >>f, "<td class=\"%s\">%.2fs</td>" % (POINTS[-2],boot_time-last) | |
try: | |
kernel_time = float(t.readline()) / 100 | |
times[host][POINTS[-1]].append((date, kernel_time)) | |
print >>f, "<td class=\"%s\">%.2fs</td>" % (POINTS[-1],kernel_time) | |
except ValueError: | |
print >>f, "<td class=\"%s\"></td>" % point | |
finally: | |
t.close() | |
print >>f, "</tr>" | |
print >>f, "<tr>" | |
for host in (SSD_HOST, HDD_HOST): | |
if not os.path.isfile("%s/%s-%s.times" % (BOOTCHARTS, date, host)): | |
continue | |
print >>f, "<td colspan=\"6\">" | |
print >>f, "<a href=\"%s-%s.png\">bootchart</a>" % (date, host) | |
print >>f, "<a href=\"%s-%s-kernel.png\">kernel</a>" % (date, host) | |
print >>f, "<a href=\"%s-%s.dmesg\">dmesg</a>" % (date, host) | |
print >>f, "</td>" | |
else: | |
print >>f, "<th>%s</th>" % date | |
print >>f, "<td colspan=\"6\"></td>" | |
print >>f, "<td colspan=\"6\"></td>" | |
print >>f, "</tr>" | |
print >>f, "</table>" | |
include(f, "footer.html") | |
finally: | |
f.close() | |
for point in POINTS: | |
chart("%s/%s.svg" % (BOOTCHARTS, point), CAPTIONS[point], | |
SSD_HOST, HDD_HOST, | |
all_dates, | |
times[SSD_HOST][point], times[HDD_HOST][point]) | |
f = open("%s/index.html" % INSTALLER, "w") | |
try: | |
include(f, "header.html", {'title': "Daily installer testing" }) | |
include(f, "installer.html") | |
print >>f, "<table>" | |
print >>f, "<tr>" | |
print >>f, "<th class=\"mast\"></th>" | |
print >>f, "<th class=\"mast\">max (SSD)</th>" | |
print >>f, "<th class=\"mast\">sam (HDD)</th></tr>" | |
for date in all_dates: | |
print >>f, "<tr>" | |
print >>f, "<th class=\"mast\">%s</th>" % date | |
if date in dates: | |
for host in (SSD_HOST, HDD_HOST): | |
path = "%s/%s-%s" % (INSTALLER, date, host) | |
if os.path.isfile("%s/WIN" % path): | |
print >>f, "<td class=\"win\">" | |
elif os.path.isfile("%s/FAIL" % path): | |
print >>f, "<td class=\"fail\">" | |
else: | |
print >>f, "<td></td>" | |
continue | |
print >>f, "<a href=\"%s-%s/bootchart.png\">bootchart</a>" % (date, host) | |
print >>f, "<a href=\"%s-%s/debug\">debug log</a>" % (date, host) | |
print >>f, "<a href=\"%s-%s/\">data</a>" % (date, host) | |
print >>f, "</td>" | |
else: | |
print >>f, "<td colspan=\"2\"></td>" | |
print >>f, "</tr>" | |
print >>f, "</table>" | |
include(f, "footer.html") | |
finally: | |
f.close() | |
def include(f, filename, dict={}): | |
h = open(filename) | |
try: | |
text = h.read() | |
print >>f, text % dict | |
finally: | |
h.close() | |
def chart(filename, caption, ssd_host, hdd_host, all_dates, | |
ssd_times, hdd_times): | |
width = max(10 + len(all_dates) * 2, | |
100) | |
height = max(31 + max(int(time * 5) for date, time in ssd_times), | |
31 + max(int(time * 5) for date, time in hdd_times), | |
100) | |
surface = cairo.SVGSurface(filename, width, height) | |
ctx = cairo.Context(surface) | |
ctx.set_line_width(1.0) | |
ctx.set_line_cap(cairo.LINE_CAP_SQUARE) | |
ctx.set_source_rgba(0.0, 0.0, 0.0, 1.0) | |
ctx.move_to(10, 9) | |
ctx.line_to(10, height-20) | |
ctx.line_to(width-1, height-20) | |
ctx.stroke() | |
for tick in range(20, height-9, 5): | |
y = height-tick | |
if tick%10: | |
ctx.move_to(7, y) | |
else: | |
ctx.move_to(5, y) | |
ctx.line_to(9, y) | |
ctx.stroke() | |
ctx.select_font_face("Bitstream Vera Sans") | |
ctx.set_font_size(8) | |
text_width = ctx.text_extents(caption)[2] | |
ctx.move_to((width-text_width)/2, 6) | |
ctx.show_text(caption) | |
ctx.move_to(6, 6) | |
ctx.show_text("seconds") | |
caption_xaxis = "First: %s, Last: %s" % (all_dates[0], all_dates[-1]) | |
ctx.move_to((width - ctx.text_extents(caption_xaxis)[2])/2, height-12) | |
ctx.show_text( caption_xaxis ) | |
ctx.set_line_cap(cairo.LINE_CAP_BUTT) | |
draw(ctx, all_dates, height, hdd_times, (0.0, 1.0, 0.0, 1.0)) | |
draw(ctx, all_dates, height, ssd_times, (1.0, 0.0, 0.0, 1.0)) | |
ctx.set_font_size(6) | |
ctx.set_line_width(0.5) | |
ctx.set_source_rgba(1.0, 0.0, 0.0, 1.0) | |
ctx.rectangle(10, height-16, 4, 4) | |
ctx.fill() | |
ctx.set_source_rgba(0.0, 0.0, 0.0, 1.0) | |
ctx.rectangle(10, height-16, 4, 4) | |
ctx.stroke() | |
ctx.move_to(17, height-12) | |
ctx.show_text("%s (SSD)" % SSD_HOST) | |
ctx.set_source_rgba(0.0, 1.0, 0.0, 1.0) | |
ctx.rectangle(10, height-10, 4, 4) | |
ctx.fill() | |
ctx.set_source_rgba(0.0, 0.0, 0.0, 1.0) | |
ctx.rectangle(10, height-10, 4, 4) | |
ctx.stroke() | |
ctx.move_to(17, height-6) | |
ctx.show_text("%s (HDD)" % HDD_HOST) | |
def draw(ctx, all_dates, height, times, color): | |
ctx.set_source_rgba(*color) | |
first = True | |
for date, time in sorted(times): | |
idx = len(all_dates)-all_dates.index(date)-1 | |
x = 10 + 1 + idx * 2 | |
y = height - 20 - 1 - time * 5 | |
if first: | |
ctx.move_to(x,y) | |
first = False | |
else: | |
ctx.line_to(x,y) | |
ctx.stroke() | |
if __name__ == "__main__": | |
main(sys.argv[1:]) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment