From: Anton Mikanovich <amikan@ilbers.de>
To: isar-users@googlegroups.com
Cc: Anton Mikanovich <amikan@ilbers.de>
Subject: [PATCH] charter: Introduce build chart generation tool
Date: Mon, 22 Mar 2021 16:07:59 +0300 [thread overview]
Message-ID: <20210322130759.152562-1-amikan@ilbers.de> (raw)
This tool can generate Isar build charts from the logs prepend with
timestamps in format: %Y-%m-%d %H:%M:%S.
Signed-off-by: Anton Mikanovich <amikan@ilbers.de>
---
testsuite/charter/charter.py | 145 +++++++++++++++++++++++++++++++++++
1 file changed, 145 insertions(+)
create mode 100755 testsuite/charter/charter.py
diff --git a/testsuite/charter/charter.py b/testsuite/charter/charter.py
new file mode 100755
index 0000000..36ced98
--- /dev/null
+++ b/testsuite/charter/charter.py
@@ -0,0 +1,145 @@
+#!/usr/bin/python3
+
+import cairo
+import re
+import sys
+from datetime import datetime
+
+timestamp_format = '%Y-%m-%d %H:%M:%S'
+
+try:
+ isar_log = sys.argv[1];
+ output_filename = sys.argv[2];
+except:
+ print("Usage:", sys.argv[0], "isar.log output.svg")
+ print("Log time format:", timestamp_format)
+ print("Example: some_bitbake_command 2>&1 | gawk '{ print strftime(\""
+ + timestamp_format + "\"), $0 }' > isar.log")
+ sys.exit(1)
+
+class Buildtask:
+ def __init__(self, package, task, start, stop):
+ self.package = package
+ self.task = task
+ self.start = start
+ self.stop = stop
+
+class Color:
+ def __init__(self, r, g, b):
+ self.r = r
+ self.g = g
+ self.b = b
+
+timestamp_first = 0
+timestamp_last = 0
+tasks = dict()
+
+log = open(isar_log)
+for line in log:
+ line = line.rstrip()
+ if re.search('NOTE: recipe', line):
+ time = datetime.strptime(re.search('\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}',
+ line).group(0), timestamp_format).timestamp()
+ if timestamp_first == 0:
+ timestamp_first = time
+ timestamp_last = time
+ package = re.search('recipe\s(\S*):\stask\s\S*:\s\S*', line).group(1)
+ task = re.search('recipe\s\S*:\stask\s(\S*):\s\S*', line).group(1)
+ state = re.search('recipe\s\S*:\stask\s\S*:\s(\S*)', line).group(1)
+ key = package + ':' + task
+ if key in tasks and state == 'Succeeded':
+ tasks[key].stop = time - timestamp_first
+ elif state == 'Started':
+ tasks[key] = Buildtask(package, task, time - timestamp_first, -1)
+log.close()
+
+header_height = 40
+footer_height = 5
+spacer_left = 5
+spacer_right = 250
+line_height = 18
+width_coef = 6
+image_width = spacer_left + width_coef * int(timestamp_last -
+ timestamp_first) + spacer_right
+image_height = header_height + len(tasks) * line_height + footer_height
+
+def task_color(task):
+ return {
+ 'do_install_builddeps': Color(1.0, 0.9, 0.7),
+ 'do_dpkg_build': Color(0.9, 0.5, 0.4),
+ 'do_deploy_deb': Color(0.5, 0.9, 0.5),
+ 'do_rootfs_postprocess': Color(1.0, 0.4, 0.3)
+ }.get(task, Color(0.7, 0.8, 0.9))
+
+def fill_background(r, g, b):
+ c.save()
+ c.set_source_rgb(r, g, b)
+ c.paint()
+ c.restore()
+
+def draw_text(x, y, text, size, color=None):
+ c.save()
+ c.move_to(x, y)
+ c.set_font_size(size)
+ if color:
+ c.set_source_rgb(color.r, color.g, color.b)
+ c.show_text(text)
+ c.restore()
+
+def draw_line(x, y, x2, y2, color, width=0.2):
+ c.save()
+ c.move_to(x, y)
+ c.set_source_rgb(color.r, color.g, color.b)
+ c.set_line_width(width)
+ c.line_to(x2, y2)
+ c.stroke()
+ c.restore()
+
+def draw_rect(x, y, width, height, color=None):
+ c.save()
+ c.rectangle(x, y, width, height)
+ if color:
+ c.set_source_rgb(color.r, color.g, color.b)
+ c.fill_preserve()
+ c.set_line_width(0.2)
+ c.set_source_rgb(0.8, 0.8, 0.8)
+ c.stroke()
+ c.restore()
+
+s = cairo.SVGSurface(output_filename, image_width, image_height)
+c = cairo.Context(s)
+
+c.select_font_face("DejaVuSerif", cairo.FONT_SLANT_NORMAL,
+ cairo.FONT_WEIGHT_NORMAL)
+
+fill_background(1.0, 1.0, 1.0)
+draw_text(1, 24, "Isar build chart from " + datetime.fromtimestamp(
+ timestamp_first).strftime(timestamp_format), 24, Color(0.1, 0.1, 0.1))
+
+for n in range (int(timestamp_last - timestamp_first)):
+ if n % 5 == 0:
+ draw_text(spacer_left + n * width_coef, header_height - 1,
+ str(n) + "s", 10, Color(0.5, 0.5, 0.5))
+ draw_line(spacer_left + n * width_coef, header_height,
+ spacer_left + n * width_coef, image_height - footer_height,
+ Color(0.8, 0.8, 0.8), 0.4)
+ else:
+ draw_line(spacer_left + n * width_coef, header_height,
+ spacer_left + n * width_coef, image_height - footer_height,
+ Color(0.9, 0.9, 0.9))
+
+current_line = header_height
+for key in tasks:
+ if tasks[key].stop < 0:
+ tasks[key].stop = int(timestamp_last - timestamp_first)
+ x1 = spacer_left + width_coef * tasks[key].start
+ width = width_coef * (tasks[key].stop - tasks[key].start)
+ if width <= 0:
+ width = 1
+ draw_rect(x1, current_line, width, line_height, task_color(tasks[key].task))
+ draw_text(x1 + 1, current_line + 12, '%s : %s (%ds)' % (tasks[key].package,
+ tasks[key].task, tasks[key].stop - tasks[key].start), 12,
+ Color(0.4, 0.4, 0.4))
+ current_line += line_height
+
+s.finish()
--
2.20.1
next reply other threads:[~2021-03-22 13:08 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-03-22 13:07 Anton Mikanovich [this message]
2021-04-22 10:22 ` Anton Mikanovich
2021-04-22 11:17 ` Jan Kiszka
2021-04-27 11:13 ` Anton Mikanovich
2021-04-27 17:01 ` Henning Schild
2021-04-27 17:28 ` Anton Mikanovich
2021-04-27 18:07 ` Henning Schild
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20210322130759.152562-1-amikan@ilbers.de \
--to=amikan@ilbers.de \
--cc=isar-users@googlegroups.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox