diff mbox series

[scarthgap] systemd-analyze: add SVG scaling and detailed timestamps

Message ID 20260424092433.3222272-1-zahir.basha@partner.bmwgroup.com
State Rejected, archived
Delegated to: Yoann Congal
Headers show
Series [scarthgap] systemd-analyze: add SVG scaling and detailed timestamps | expand

Commit Message

Zahir Hussain April 24, 2026, 9:24 a.m. UTC
From: Zahir Hussain <zahir.basha@kpit.com>

Enhance the `plot` command with two new options for better visualization:
 `--scale-svg=<FACTOR>`: Scales the x-axis to improve plot readability.
 `--detailed`: Adds activation timestamps to the SVG output.

This is a backport of the following upstream commit:
https://github.com/systemd/systemd/commit/1592d2f900c25251ece2670c71d957806f48216b

This improves the readability of boot analysis plots when dealing
with complex or high-density timing data.

Signed-off-by: Zahir Hussain <zahir.basha@kpit.com>
---
 ...temd-analyze-Add-svg-scaling-options.patch | 167 ++++++++++++++++++
 meta/recipes-core/systemd/systemd_255.21.bb   |   1 +
 2 files changed, 168 insertions(+)
 create mode 100644 meta/recipes-core/systemd/systemd/0023-systemd-analyze-Add-svg-scaling-options.patch

Comments

Yoann Congal April 24, 2026, 9:57 a.m. UTC | #1
On Fri Apr 24, 2026 at 11:24 AM CEST, aszh07 via lists.openembedded.org wrote:
> From: Zahir Hussain <zahir.basha@kpit.com>
>
> Enhance the `plot` command with two new options for better visualization:
>  `--scale-svg=<FACTOR>`: Scales the x-axis to improve plot readability.
>  `--detailed`: Adds activation timestamps to the SVG output.
>
> This is a backport of the following upstream commit:
> https://github.com/systemd/systemd/commit/1592d2f900c25251ece2670c71d957806f48216b
>
> This improves the readability of boot analysis plots when dealing
> with complex or high-density timing data.
>
> Signed-off-by: Zahir Hussain <zahir.basha@kpit.com>

Hello,

Sorry but this a new feature and is excluded by policy from stable
branches.

Regards,

> ---
>  ...temd-analyze-Add-svg-scaling-options.patch | 167 ++++++++++++++++++
>  meta/recipes-core/systemd/systemd_255.21.bb   |   1 +
>  2 files changed, 168 insertions(+)
>  create mode 100644 meta/recipes-core/systemd/systemd/0023-systemd-analyze-Add-svg-scaling-options.patch
>
> diff --git a/meta/recipes-core/systemd/systemd/0023-systemd-analyze-Add-svg-scaling-options.patch b/meta/recipes-core/systemd/systemd/0023-systemd-analyze-Add-svg-scaling-options.patch
> new file mode 100644
> index 0000000000..9bae1654d2
> --- /dev/null
> +++ b/meta/recipes-core/systemd/systemd/0023-systemd-analyze-Add-svg-scaling-options.patch
> @@ -0,0 +1,167 @@
> +From 6f1af79ed9515771113ea5b39ac7b267cac66dc7 Mon Sep 17 00:00:00 2001
> +From: rajmohan r <rajmohan.r@kpit.com>
> +Date: Thu, 8 Aug 2024 15:09:35 +0530
> +Subject: [PATCH] systemd-analyze: Add svg scaling options
> +
> ++ Scale the x-axis of the resulting plot by a factor (default 1.0)
> ++ Add activation timestamps to each bar
> +
> +Upstream-Status: Backport [https://github.com/systemd/systemd/commit/1592d2f900c25251ece2670c71d957806f48216b]
> +
> +comment: refresh the patch according to source code and Changes to 
> +test/units/TEST-65-ANALYZE.sh do not take effect because the file
> +is not available in the source code.
> +
> +Signed-off-by: rajmohan r <rajmohan.r@kpit.com>
> +Signed-off-by: Zahir Hussain <zahir.basha@kpit.com>
> +---
> + man/systemd-analyze.xml               | 18 ++++++++++++++++++
> + shell-completion/bash/systemd-analyze |  2 +-
> + src/analyze/analyze-plot.c            |  7 ++++++-
> + src/analyze/analyze.c                 | 17 +++++++++++++++++
> + src/analyze/analyze.h                 |  2 ++
> + 5 files changed, 42 insertions(+), 2 deletions(-)
> +
> +diff --git a/man/systemd-analyze.xml b/man/systemd-analyze.xml
> +index 35ad8435f4f..9a7998b3f6d 100644
> +--- a/man/systemd-analyze.xml
> ++++ b/man/systemd-analyze.xml
> +@@ -1499,6 +1499,24 @@ NR NAME                SHA256
> +         <xi:include href="version-info.xml" xpointer="v255"/></listitem>
> +       </varlistentry>
> + 
> ++      <varlistentry>
> ++        <term><option>--scale-svg=<replaceable>FACTOR</replaceable></option></term>
> ++
> ++        <listitem><para>When used with the <command>plot</command> command, the x-axis of the plot
> ++        can be stretched by FACTOR (default: 1.0).</para>
> ++
> ++        <xi:include href="version-info.xml" xpointer="v255"/></listitem>
> ++      </varlistentry>
> ++
> ++      <varlistentry>
> ++        <term><option>--detailed</option></term>
> ++
> ++        <listitem><para>When used with the <command>plot</command> command, activation timestamps
> ++        details can be seen in SVG plot.</para>
> ++
> ++        <xi:include href="version-info.xml" xpointer="v255"/></listitem>
> ++      </varlistentry>
> ++
> +       <xi:include href="standard-options.xml" xpointer="help" />
> +       <xi:include href="standard-options.xml" xpointer="version" />
> +       <xi:include href="standard-options.xml" xpointer="no-pager" />
> +diff --git a/shell-completion/bash/systemd-analyze b/shell-completion/bash/systemd-analyze
> +index 1fde67218b9..781cb1572e2 100644
> +--- a/shell-completion/bash/systemd-analyze
> ++++ b/shell-completion/bash/systemd-analyze
> +@@ -196,7 +196,7 @@ _systemd_analyze() {
> + 
> +     elif __contains_word "$verb" ${VERBS[PLOT]}; then
> +         if [[ $cur = -* ]]; then
> +-            comps='--help --version --system --user --global --no-pager --json=off --json=pretty --json=short --table --no-legend'
> ++            comps='--help --version --system --user --global --no-pager --json=off --json=pretty --json=short --table --no-legend --scale-svg --detailed'
> +         fi
> +     fi
> + 
> +diff --git a/src/analyze/analyze-plot.c b/src/analyze/analyze-plot.c
> +index 81fc25b31e0..70a903e0db1 100644
> +--- a/src/analyze/analyze-plot.c
> ++++ b/src/analyze/analyze-plot.c
> +@@ -12,7 +12,7 @@
> + #include "unit-def.h"
> + #include "version.h"
> + 
> +-#define SCALE_X (0.1 / 1000.0) /* pixels per us */
> ++#define SCALE_X (0.1 * arg_svg_timescale / 1000.0) /* pixels per us */
> + #define SCALE_Y (20.0)
> + 
> + #define svg(...) printf(__VA_ARGS__)
> +@@ -30,6 +30,9 @@
> +                 svg("</text>\n");                                       \
> +         } while (false)
> + 
> ++#define svg_timestamp(b, t, y) \
> ++        svg_text(b, t, y, "%u.%03us", (unsigned)((t) / USEC_PER_SEC), (unsigned)(((t) % USEC_PER_SEC) / USEC_PER_MSEC))
> ++
> + 
> + typedef struct HostInfo {
> +         char *hostname;
> +@@ -358,6 +361,8 @@ static int produce_plot_as_svg(
> +         svg_bar("generators", boot->generators_start_time, boot->generators_finish_time, y);
> +         svg_bar("unitsload", boot->unitsload_start_time, boot->unitsload_finish_time, y);
> +         svg_text(true, boot->userspace_time, y, "systemd");
> ++        if (arg_detailed_svg)
> ++                svg_timestamp(false, boot->userspace_time, y);
> +         y++;
> + 
> +         for (; u->has_data; u++)
> +diff --git a/src/analyze/analyze.c b/src/analyze/analyze.c
> +index 021de65bdbf..457f9e59cc8 100644
> +--- a/src/analyze/analyze.c
> ++++ b/src/analyze/analyze.c
> +@@ -99,6 +99,8 @@ RuntimeScope arg_runtime_scope = RUNTIME_SCOPE_SYSTEM;
> + RecursiveErrors arg_recursive_errors = _RECURSIVE_ERRORS_INVALID;
> + bool arg_man = true;
> + bool arg_generators = false;
> ++double arg_svg_timescale = 1.0;
> ++bool arg_detailed_svg = false;
> + char *arg_root = NULL;
> + static char *arg_image = NULL;
> + char *arg_security_policy = NULL;
> +@@ -271,6 +273,9 @@ static int help(int argc, char *argv[], void *userdata) {
> +                "     --profile=name|PATH     Include the specified profile in the\n"
> +                "                             security review of the unit(s)\n"
> +                "     --table                 Output plot's raw time data as a table\n"
> ++               "     --scale-svg=FACTOR      Stretch x-axis of plot by FACTOR (default: 1.0)\n"
> ++               "     --detailed              Add more details to SVG plot,\n"
> ++               "                             e.g. show activation timestamps\n"
> +                "  -h --help                  Show this help\n"
> +                "     --version               Show package version\n"
> +                "  -q --quiet                 Do not emit hints\n"
> +@@ -319,6 +324,8 @@ static int parse_argv(int argc, char *argv[]) {
> +                 ARG_TABLE,
> +                 ARG_NO_LEGEND,
> +                 ARG_TLDR,
> ++                ARG_SCALE_FACTOR_SVG,
> ++                ARG_DETAILED_SVG,
> +         };
> + 
> +         static const struct option options[] = {
> +@@ -353,6 +360,8 @@ static int parse_argv(int argc, char *argv[]) {
> +                 { "table",            optional_argument, NULL, ARG_TABLE            },
> +                 { "no-legend",        optional_argument, NULL, ARG_NO_LEGEND        },
> +                 { "tldr",             no_argument,       NULL, ARG_TLDR             },
> ++                { "scale-svg",        required_argument, NULL, ARG_SCALE_FACTOR_SVG },
> ++                { "detailed",         no_argument,       NULL, ARG_DETAILED_SVG     },
> +                 {}
> +         };
> + 
> +@@ -546,6 +555,14 @@ static int parse_argv(int argc, char *argv[]) {
> +                         arg_cat_flags = CAT_TLDR;
> +                         break;
> + 
> ++                case ARG_SCALE_FACTOR_SVG:
> ++                        arg_svg_timescale = strtod(optarg, NULL);
> ++                        break;
> ++
> ++                case ARG_DETAILED_SVG:
> ++                        arg_detailed_svg = true;
> ++                        break;
> ++
> +                 case '?':
> +                         return -EINVAL;
> + 
> +diff --git a/src/analyze/analyze.h b/src/analyze/analyze.h
> +index 8a9528c0d3b..ddd4ad547c7 100644
> +--- a/src/analyze/analyze.h
> ++++ b/src/analyze/analyze.h
> +@@ -28,6 +28,8 @@ extern RuntimeScope arg_runtime_scope;
> + extern RecursiveErrors arg_recursive_errors;
> + extern bool arg_man;
> + extern bool arg_generators;
> ++extern double arg_svg_timescale;
> ++extern bool arg_detailed_svg;
> + extern char *arg_root;
> + extern char *arg_security_policy;
> + extern bool arg_offline;
> diff --git a/meta/recipes-core/systemd/systemd_255.21.bb b/meta/recipes-core/systemd/systemd_255.21.bb
> index 87e186bbfa..2d5badb489 100644
> --- a/meta/recipes-core/systemd/systemd_255.21.bb
> +++ b/meta/recipes-core/systemd/systemd_255.21.bb
> @@ -29,6 +29,7 @@ SRC_URI += " \
>             file://0002-binfmt-Don-t-install-dependency-links-at-install-tim.patch \
>             file://0003-timedated-Respond-on-org.freedesktop.timedate1.SetNT.patch \
>             file://0008-implment-systemd-sysv-install-for-OE.patch \
> +           file://0023-systemd-analyze-Add-svg-scaling-options.patch \
>             "
>  
>  # patches needed by musl
diff mbox series

Patch

diff --git a/meta/recipes-core/systemd/systemd/0023-systemd-analyze-Add-svg-scaling-options.patch b/meta/recipes-core/systemd/systemd/0023-systemd-analyze-Add-svg-scaling-options.patch
new file mode 100644
index 0000000000..9bae1654d2
--- /dev/null
+++ b/meta/recipes-core/systemd/systemd/0023-systemd-analyze-Add-svg-scaling-options.patch
@@ -0,0 +1,167 @@ 
+From 6f1af79ed9515771113ea5b39ac7b267cac66dc7 Mon Sep 17 00:00:00 2001
+From: rajmohan r <rajmohan.r@kpit.com>
+Date: Thu, 8 Aug 2024 15:09:35 +0530
+Subject: [PATCH] systemd-analyze: Add svg scaling options
+
++ Scale the x-axis of the resulting plot by a factor (default 1.0)
++ Add activation timestamps to each bar
+
+Upstream-Status: Backport [https://github.com/systemd/systemd/commit/1592d2f900c25251ece2670c71d957806f48216b]
+
+comment: refresh the patch according to source code and Changes to 
+test/units/TEST-65-ANALYZE.sh do not take effect because the file
+is not available in the source code.
+
+Signed-off-by: rajmohan r <rajmohan.r@kpit.com>
+Signed-off-by: Zahir Hussain <zahir.basha@kpit.com>
+---
+ man/systemd-analyze.xml               | 18 ++++++++++++++++++
+ shell-completion/bash/systemd-analyze |  2 +-
+ src/analyze/analyze-plot.c            |  7 ++++++-
+ src/analyze/analyze.c                 | 17 +++++++++++++++++
+ src/analyze/analyze.h                 |  2 ++
+ 5 files changed, 42 insertions(+), 2 deletions(-)
+
+diff --git a/man/systemd-analyze.xml b/man/systemd-analyze.xml
+index 35ad8435f4f..9a7998b3f6d 100644
+--- a/man/systemd-analyze.xml
++++ b/man/systemd-analyze.xml
+@@ -1499,6 +1499,24 @@ NR NAME                SHA256
+         <xi:include href="version-info.xml" xpointer="v255"/></listitem>
+       </varlistentry>
+ 
++      <varlistentry>
++        <term><option>--scale-svg=<replaceable>FACTOR</replaceable></option></term>
++
++        <listitem><para>When used with the <command>plot</command> command, the x-axis of the plot
++        can be stretched by FACTOR (default: 1.0).</para>
++
++        <xi:include href="version-info.xml" xpointer="v255"/></listitem>
++      </varlistentry>
++
++      <varlistentry>
++        <term><option>--detailed</option></term>
++
++        <listitem><para>When used with the <command>plot</command> command, activation timestamps
++        details can be seen in SVG plot.</para>
++
++        <xi:include href="version-info.xml" xpointer="v255"/></listitem>
++      </varlistentry>
++
+       <xi:include href="standard-options.xml" xpointer="help" />
+       <xi:include href="standard-options.xml" xpointer="version" />
+       <xi:include href="standard-options.xml" xpointer="no-pager" />
+diff --git a/shell-completion/bash/systemd-analyze b/shell-completion/bash/systemd-analyze
+index 1fde67218b9..781cb1572e2 100644
+--- a/shell-completion/bash/systemd-analyze
++++ b/shell-completion/bash/systemd-analyze
+@@ -196,7 +196,7 @@ _systemd_analyze() {
+ 
+     elif __contains_word "$verb" ${VERBS[PLOT]}; then
+         if [[ $cur = -* ]]; then
+-            comps='--help --version --system --user --global --no-pager --json=off --json=pretty --json=short --table --no-legend'
++            comps='--help --version --system --user --global --no-pager --json=off --json=pretty --json=short --table --no-legend --scale-svg --detailed'
+         fi
+     fi
+ 
+diff --git a/src/analyze/analyze-plot.c b/src/analyze/analyze-plot.c
+index 81fc25b31e0..70a903e0db1 100644
+--- a/src/analyze/analyze-plot.c
++++ b/src/analyze/analyze-plot.c
+@@ -12,7 +12,7 @@
+ #include "unit-def.h"
+ #include "version.h"
+ 
+-#define SCALE_X (0.1 / 1000.0) /* pixels per us */
++#define SCALE_X (0.1 * arg_svg_timescale / 1000.0) /* pixels per us */
+ #define SCALE_Y (20.0)
+ 
+ #define svg(...) printf(__VA_ARGS__)
+@@ -30,6 +30,9 @@
+                 svg("</text>\n");                                       \
+         } while (false)
+ 
++#define svg_timestamp(b, t, y) \
++        svg_text(b, t, y, "%u.%03us", (unsigned)((t) / USEC_PER_SEC), (unsigned)(((t) % USEC_PER_SEC) / USEC_PER_MSEC))
++
+ 
+ typedef struct HostInfo {
+         char *hostname;
+@@ -358,6 +361,8 @@ static int produce_plot_as_svg(
+         svg_bar("generators", boot->generators_start_time, boot->generators_finish_time, y);
+         svg_bar("unitsload", boot->unitsload_start_time, boot->unitsload_finish_time, y);
+         svg_text(true, boot->userspace_time, y, "systemd");
++        if (arg_detailed_svg)
++                svg_timestamp(false, boot->userspace_time, y);
+         y++;
+ 
+         for (; u->has_data; u++)
+diff --git a/src/analyze/analyze.c b/src/analyze/analyze.c
+index 021de65bdbf..457f9e59cc8 100644
+--- a/src/analyze/analyze.c
++++ b/src/analyze/analyze.c
+@@ -99,6 +99,8 @@ RuntimeScope arg_runtime_scope = RUNTIME_SCOPE_SYSTEM;
+ RecursiveErrors arg_recursive_errors = _RECURSIVE_ERRORS_INVALID;
+ bool arg_man = true;
+ bool arg_generators = false;
++double arg_svg_timescale = 1.0;
++bool arg_detailed_svg = false;
+ char *arg_root = NULL;
+ static char *arg_image = NULL;
+ char *arg_security_policy = NULL;
+@@ -271,6 +273,9 @@ static int help(int argc, char *argv[], void *userdata) {
+                "     --profile=name|PATH     Include the specified profile in the\n"
+                "                             security review of the unit(s)\n"
+                "     --table                 Output plot's raw time data as a table\n"
++               "     --scale-svg=FACTOR      Stretch x-axis of plot by FACTOR (default: 1.0)\n"
++               "     --detailed              Add more details to SVG plot,\n"
++               "                             e.g. show activation timestamps\n"
+                "  -h --help                  Show this help\n"
+                "     --version               Show package version\n"
+                "  -q --quiet                 Do not emit hints\n"
+@@ -319,6 +324,8 @@ static int parse_argv(int argc, char *argv[]) {
+                 ARG_TABLE,
+                 ARG_NO_LEGEND,
+                 ARG_TLDR,
++                ARG_SCALE_FACTOR_SVG,
++                ARG_DETAILED_SVG,
+         };
+ 
+         static const struct option options[] = {
+@@ -353,6 +360,8 @@ static int parse_argv(int argc, char *argv[]) {
+                 { "table",            optional_argument, NULL, ARG_TABLE            },
+                 { "no-legend",        optional_argument, NULL, ARG_NO_LEGEND        },
+                 { "tldr",             no_argument,       NULL, ARG_TLDR             },
++                { "scale-svg",        required_argument, NULL, ARG_SCALE_FACTOR_SVG },
++                { "detailed",         no_argument,       NULL, ARG_DETAILED_SVG     },
+                 {}
+         };
+ 
+@@ -546,6 +555,14 @@ static int parse_argv(int argc, char *argv[]) {
+                         arg_cat_flags = CAT_TLDR;
+                         break;
+ 
++                case ARG_SCALE_FACTOR_SVG:
++                        arg_svg_timescale = strtod(optarg, NULL);
++                        break;
++
++                case ARG_DETAILED_SVG:
++                        arg_detailed_svg = true;
++                        break;
++
+                 case '?':
+                         return -EINVAL;
+ 
+diff --git a/src/analyze/analyze.h b/src/analyze/analyze.h
+index 8a9528c0d3b..ddd4ad547c7 100644
+--- a/src/analyze/analyze.h
++++ b/src/analyze/analyze.h
+@@ -28,6 +28,8 @@ extern RuntimeScope arg_runtime_scope;
+ extern RecursiveErrors arg_recursive_errors;
+ extern bool arg_man;
+ extern bool arg_generators;
++extern double arg_svg_timescale;
++extern bool arg_detailed_svg;
+ extern char *arg_root;
+ extern char *arg_security_policy;
+ extern bool arg_offline;
diff --git a/meta/recipes-core/systemd/systemd_255.21.bb b/meta/recipes-core/systemd/systemd_255.21.bb
index 87e186bbfa..2d5badb489 100644
--- a/meta/recipes-core/systemd/systemd_255.21.bb
+++ b/meta/recipes-core/systemd/systemd_255.21.bb
@@ -29,6 +29,7 @@  SRC_URI += " \
            file://0002-binfmt-Don-t-install-dependency-links-at-install-tim.patch \
            file://0003-timedated-Respond-on-org.freedesktop.timedate1.SetNT.patch \
            file://0008-implment-systemd-sysv-install-for-OE.patch \
+           file://0023-systemd-analyze-Add-svg-scaling-options.patch \
            "
 
 # patches needed by musl