From: Henning Schild <henning.schild@siemens.com>
To: Anton Mikanovich <amikan@ilbers.de>
Cc: isar-users@googlegroups.com
Subject: Re: [PATCH] charter: Introduce build chart generation tool
Date: Tue, 27 Apr 2021 19:01:11 +0200 [thread overview]
Message-ID: <20210427190111.4c3a1522@md1za8fc.ad001.siemens.net> (raw)
In-Reply-To: <20210322130759.152562-1-amikan@ilbers.de>
I think we should not parse those logs and do our own profiling.
bitbake has profiling support in several flavours. Last time i checked
isar was missing some library bits that are only in oe.
https://wiki.yoctoproject.org/wiki/Profiling
We should see what is the state of the art in yocto/OE and use that, no
own inventions. Then see how to get that into isar and possibly massage
it upstream to get it into isar without forking oe/bitbake bits.
Or we add "charter" to bitbake and take it from there, in case we fill
a gap that upstream might have.
Am i correct that this charter is something that oe/bitbake does not
have?
regards,
Henning
Am Mon, 22 Mar 2021 16:07:59 +0300
schrieb Anton Mikanovich <amikan@ilbers.de>:
> 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()
next prev parent reply other threads:[~2021-04-27 17:08 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-03-22 13:07 Anton Mikanovich
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 [this message]
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=20210427190111.4c3a1522@md1za8fc.ad001.siemens.net \
--to=henning.schild@siemens.com \
--cc=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