analyze.c revision d3eba116d14b8775eed02e433f7ec5f62cde4957
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering This file is part of systemd.
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering Copyright 2010-2013 Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering Copyright 2013 Simon Peeters
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering systemd is free software; you can redistribute it and/or modify it
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering under the terms of the GNU Lesser General Public License as published by
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering (at your option) any later version.
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering systemd is distributed in the hope that it will be useful, but
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering Lesser General Public License for more details.
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering You should have received a copy of the GNU Lesser General Public License
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#define SCALE_X (0.1 / 1000.0) /* pixels per us */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#define compare(a, b) (((a) > (b))? 1 : (((b) > (a))? -1 : 0))
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering svg(" <rect class=\"%s\" x=\"%.03f\" y=\"%.03f\" width=\"%.03f\" height=\"%.03f\" />\n", \
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering svg(" <text class=\"%s\" x=\"%.03f\" y=\"%.03f\">", (b) ? "left" : "right", SCALE_X * (x) + (b ? 5.0 : -5.0), SCALE_Y * (y) + 14.0); \
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering } while(false)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic UnitFileScope arg_scope = UNIT_FILE_SYSTEM;
9bf3b53533cdc9b95c921b71da755401f223f765Lennart Poetteringstatic char** arg_dot_from_patterns = NULL;
9bf3b53533cdc9b95c921b71da755401f223f765Lennart Poetteringstatic bool arg_no_pager = false;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic void pager_open_if_enabled(void) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic int bus_get_uint64_property(sd_bus *bus, const char *path, const char *interface, const char *property, uint64_t *val) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
e3b9d9c8027a7c4c55cf1614e0fe9423fad69e8fZbigniew Jędrzejewski-Szmek log_error("Failed to parse reply: %s", bus_error_message(&error, -r));
e3b9d9c8027a7c4c55cf1614e0fe9423fad69e8fZbigniew Jędrzejewski-Szmekstatic int compare_unit_time(const void *a, const void *b) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return compare(((struct unit_times *)b)->time,
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmekstatic int compare_unit_start(const void *a, const void *b) {
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek return compare(((struct unit_times *)a)->activating,
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek ((struct unit_times *)b)->activating);
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmekstatic int get_os_name(char **_n) {
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek r = parse_env_file("/etc/os-release", NEWLINE, "PRETTY_NAME", &n, NULL);
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmekstatic void free_unit_times(struct unit_times *t, unsigned n) {
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek for (p = t; p < t + n; p++)
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmekstatic int bus_parse_unit_info(sd_bus_message *message, struct unit_info *u) {
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek r = sd_bus_message_read(message, "(ssssssouso)", &u->id,
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek log_error("Failed to parse message as unit_info.");
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic int bus_get_unit_property_strv(sd_bus *bus, const char *unit_path, const char *prop, char ***strv) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_error("Failed to get unit property: %s %s", prop, bus_error_message(&error, -r));
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "s");
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering while ((r = sd_bus_message_read(reply, "s", &s)) > 0) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic int acquire_time_data(sd_bus *bus, struct unit_times **out) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering int r, c = 0, n_units = 0;
d3b6d0c21ea5a0d15ec6dbd8b8d179138b7463bcZbigniew Jędrzejewski-Szmek "org.freedesktop.systemd1.Manager",
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_error("Failed to parse reply: %s", bus_error_message(&error, -r));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssssouso)");
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering while ((r = bus_parse_unit_info(reply, &u)) > 0) {
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek w = realloc(unit_times, sizeof(struct unit_times) * n_units);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert_cc(sizeof(usec_t) == sizeof(uint64_t));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (bus_get_uint64_property(bus, u.unit_path,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "InactiveExitTimestampMonotonic",
18cd5fe99f70a55a2d6f2303d6ee0624942695b1Zbigniew Jędrzejewski-Szmek bus_get_uint64_property(bus, u.unit_path,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "ActiveEnterTimestampMonotonic",
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering bus_get_uint64_property(bus, u.unit_path,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "ActiveExitTimestampMonotonic",
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering bus_get_uint64_property(bus, u.unit_path,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "InactiveEnterTimestampMonotonic",
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering else if (t->deactivated >= t->activating)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering t->time = t->deactivated - t->activating;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering free_unit_times(unit_times, (unsigned) c);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic int acquire_boot_times(sd_bus *bus, struct boot_times **bt) {
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek static bool cached = false;
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek if (bus_get_uint64_property(bus,
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek "org.freedesktop.systemd1.Manager",
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek "FirmwareTimestampMonotonic",
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek "org.freedesktop.systemd1.Manager",
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek "LoaderTimestampMonotonic",
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek "org.freedesktop.systemd1.Manager",
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek "KernelTimestamp",
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek "org.freedesktop.systemd1.Manager",
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek "InitRDTimestampMonotonic",
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek "org.freedesktop.systemd1.Manager",
80343dc19a9bcd703275ad2ad88f43e5310559d6Zbigniew Jędrzejewski-Szmek "UserspaceTimestampMonotonic",
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek "org.freedesktop.systemd1.Manager",
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek "FinishTimestampMonotonic",
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek "org.freedesktop.systemd1.Manager",
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek "GeneratorsStartTimestampMonotonic",
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew JÄ™drzejewski-Szmek ×.generators_start_time) < 0 ||
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek "org.freedesktop.systemd1.Manager",
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek "GeneratorsFinishTimestampMonotonic",
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew JÄ™drzejewski-Szmek ×.generators_finish_time) < 0 ||
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek "org.freedesktop.systemd1.Manager",
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek "UnitsLoadStartTimestampMonotonic",
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew JÄ™drzejewski-Szmek ×.unitsload_start_time) < 0 ||
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek "org.freedesktop.systemd1.Manager",
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek "UnitsLoadFinishTimestampMonotonic",
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew JÄ™drzejewski-Szmek ×.unitsload_finish_time) < 0)
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek log_error("Bootup is not yet finished. Please try again later.");
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek times.kernel_done_time = times.initrd_time;
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek times.kernel_done_time = times.userspace_time;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic int pretty_boot_time(sd_bus *bus, char **_buf) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering size = strpcpyf(&ptr, size, "Startup finished in ");
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering size = strpcpyf(&ptr, size, "%s (firmware) + ", format_timespan(ts, sizeof(ts), t->firmware_time - t->loader_time, USEC_PER_MSEC));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering size = strpcpyf(&ptr, size, "%s (loader) + ", format_timespan(ts, sizeof(ts), t->loader_time, USEC_PER_MSEC));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering size = strpcpyf(&ptr, size, "%s (kernel) + ", format_timespan(ts, sizeof(ts), t->kernel_done_time, USEC_PER_MSEC));
e3b9d9c8027a7c4c55cf1614e0fe9423fad69e8fZbigniew Jędrzejewski-Szmek size = strpcpyf(&ptr, size, "%s (initrd) + ", format_timespan(ts, sizeof(ts), t->userspace_time - t->initrd_time, USEC_PER_MSEC));
e3b9d9c8027a7c4c55cf1614e0fe9423fad69e8fZbigniew Jędrzejewski-Szmek size = strpcpyf(&ptr, size, "%s (userspace) ", format_timespan(ts, sizeof(ts), t->finish_time - t->userspace_time, USEC_PER_MSEC));
e3b9d9c8027a7c4c55cf1614e0fe9423fad69e8fZbigniew Jędrzejewski-Szmek strpcpyf(&ptr, size, "= %s", format_timespan(ts, sizeof(ts), t->firmware_time + t->finish_time, USEC_PER_MSEC));
e3b9d9c8027a7c4c55cf1614e0fe9423fad69e8fZbigniew Jędrzejewski-Szmek strpcpyf(&ptr, size, "= %s", format_timespan(ts, sizeof(ts), t->finish_time - t->userspace_time, USEC_PER_MSEC));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic void svg_graph_box(double height, double begin, double end) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* outside box, fill */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering svg("<rect class=\"box\" x=\"0\" y=\"0\" width=\"%.03f\" height=\"%.03f\" />\n",
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering SCALE_X * (end - begin), SCALE_Y * height);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering for (i = ((long long) (begin / 100000)) * 100000; i <= end; i+=100000) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* lines for each second */
18cd5fe99f70a55a2d6f2303d6ee0624942695b1Zbigniew Jędrzejewski-Szmek if (i % 5000000 == 0)
18cd5fe99f70a55a2d6f2303d6ee0624942695b1Zbigniew Jędrzejewski-Szmek svg(" <line class=\"sec5\" x1=\"%.03f\" y1=\"0\" x2=\"%.03f\" y2=\"%.03f\" />\n"
18cd5fe99f70a55a2d6f2303d6ee0624942695b1Zbigniew Jędrzejewski-Szmek " <text class=\"sec\" x=\"%.03f\" y=\"%.03f\" >%.01fs</text>\n",
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering SCALE_X * i, SCALE_X * i, SCALE_Y * height, SCALE_X * i, -5.0, 0.000001 * i);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering else if (i % 1000000 == 0)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering svg(" <line class=\"sec1\" x1=\"%.03f\" y1=\"0\" x2=\"%.03f\" y2=\"%.03f\" />\n"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering " <text class=\"sec\" x=\"%.03f\" y=\"%.03f\" >%.01fs</text>\n",
7ff7394d9e4e9189c30fd018235e6b1728c6f2d0Zbigniew Jędrzejewski-Szmek SCALE_X * i, SCALE_X * i, SCALE_Y * height, SCALE_X * i, -5.0, 0.000001 * i);
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek svg(" <line class=\"sec01\" x1=\"%.03f\" y1=\"0\" x2=\"%.03f\" y2=\"%.03f\" />\n",
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek SCALE_X * i, SCALE_X * i, SCALE_Y * height);
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmekstatic int analyze_plot(sd_bus *bus) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering int n, m = 1, y=0;
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek _cleanup_free_ char *pretty_times = NULL, *osname = NULL;
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek n = acquire_boot_times(bus, &boot);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering n = pretty_boot_time(bus, &pretty_times);
03e334a1c7dc8c20c38902aa039440763acc9b17Lennart Poettering qsort(times, n, sizeof(struct unit_times), compare_unit_start);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering width = SCALE_X * (boot->firmware_time + boot->finish_time);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (boot->firmware_time > boot->loader_time)
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering if (u->activating < boot->userspace_time ||
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* If the text cannot fit on the left side then
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering * increase the svg width so it fits on the right.
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering * TODO: calculate the text width more accurately */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering text_start = (boot->firmware_time + u->activating) * SCALE_X;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (text_width > text_start && text_width + text_start > width)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (u->deactivated > u->activating && u->deactivated <= boot->finish_time
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering && u->activated == 0 && u->deactivating == 0)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering u->activated = u->deactivating = u->deactivated;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (u->activated < u->activating || u->activated > boot->finish_time)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (u->deactivating < u->activated || u->activated > boot->finish_time)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (u->deactivated < u->deactivating || u->deactivated > boot->finish_time)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering svg("<?xml version=\"1.0\" standalone=\"no\"?>\n"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" "
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "\"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n");
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering svg("<svg width=\"%.0fpx\" height=\"%.0fpx\" version=\"1.1\" "
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "xmlns=\"http://www.w3.org/2000/svg\">\n\n",
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* write some basic info as a comment, including some help */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering svg("<!-- This file is a systemd-analyze SVG file. It is best rendered in a -->\n"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "<!-- browser such as Chrome, Chromium or Firefox. Other applications -->\n"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "<!-- that render these files properly but much slower are ImageMagick, -->\n"
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering "<!-- gimp, inkscape, etc. To display the files on your system, just -->\n"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "<!-- point your browser to this file. -->\n\n"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "<!-- This plot was generated by systemd-analyze version %-16.16s -->\n\n", VERSION);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* style sheet */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering svg("<defs>\n <style type=\"text/css\">\n <![CDATA[\n"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering " rect { stroke-width: 1; stroke-opacity: 0; }\n"
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering " rect.background { fill: rgb(255,255,255); }\n"
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering " rect.activating { fill: rgb(255,0,0); fill-opacity: 0.7; }\n"
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering " rect.active { fill: rgb(200,150,150); fill-opacity: 0.7; }\n"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering " rect.deactivating { fill: rgb(150,100,100); fill-opacity: 0.7; }\n"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering " rect.kernel { fill: rgb(150,150,150); fill-opacity: 0.7; }\n"
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek " rect.initrd { fill: rgb(150,150,150); fill-opacity: 0.7; }\n"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering " rect.firmware { fill: rgb(150,150,150); fill-opacity: 0.7; }\n"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering " rect.loader { fill: rgb(150,150,150); fill-opacity: 0.7; }\n"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering " rect.userspace { fill: rgb(150,150,150); fill-opacity: 0.7; }\n"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering " rect.generators { fill: rgb(102,204,255); fill-opacity: 0.7; }\n"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering " rect.unitsload { fill: rgb( 82,184,255); fill-opacity: 0.7; }\n"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering " rect.box { fill: rgb(240,240,240); stroke: rgb(192,192,192); }\n"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering " line { stroke: rgb(64,64,64); stroke-width: 1; }\n"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering " line.sec5 { stroke-width: 2; }\n"
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek " line.sec01 { stroke: rgb(224,224,224); stroke-width: 1; }\n"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering " text { font-family: Verdana, Helvetica; font-size: 14px; }\n"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering " text.left { font-family: Verdana, Helvetica; font-size: 14px; text-anchor: start; }\n"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering " text.right { font-family: Verdana, Helvetica; font-size: 14px; text-anchor: end; }\n"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering " text.sec { font-size: 10px; }\n"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering " ]]>\n </style>\n</defs>\n\n");
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering svg("<rect class=\"background\" width=\"100%%\" height=\"100%%\" />\n");
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering svg("<text x=\"20\" y=\"50\">%s</text>", pretty_times);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering svg("<text x=\"20\" y=\"30\">%s %s (%s %s) %s</text>",
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering name.nodename, name.release, name.version, name.machine);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering svg("<g transform=\"translate(%.3f,100)\">\n", 20.0 + (SCALE_X * boot->firmware_time));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering svg_graph_box(m, -boot->firmware_time, boot->finish_time);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering svg_bar("firmware", -(double) boot->firmware_time, -(double) boot->loader_time, y);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering svg_text(true, -(double) boot->firmware_time, y, "firmware");
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering svg_bar("loader", -(double) boot->loader_time, 0, y);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering svg_text(true, -(double) boot->loader_time, y, "loader");
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering svg_bar("kernel", 0, boot->kernel_done_time, y);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering svg_bar("initrd", boot->initrd_time, boot->userspace_time, y);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering svg_text(true, boot->initrd_time, y, "initrd");
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering svg_bar("active", boot->userspace_time, boot->finish_time, y);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering svg_bar("generators", boot->generators_start_time, boot->generators_finish_time, y);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering svg_bar("unitsload", boot->unitsload_start_time, boot->unitsload_finish_time, y);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering svg_text(true, boot->userspace_time, y, "systemd");
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering svg_bar("activating", u->activating, u->activated, y);
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek svg_bar("active", u->activated, u->deactivating, y);
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek svg_bar("deactivating", u->deactivating, u->deactivated, y);
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek /* place the text on the left if we have passed the half of the svg width */
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek b = u->activating * SCALE_X < width / 2;
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek svg_text(b, u->activating, y, "%s (%s)",
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek u->name, format_timespan(ts, sizeof(ts), u->time, USEC_PER_MSEC));
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek svg_text(b, u->activating, y, "%s", u->name);
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek svg_bar("activating", 0, 300000, y);
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek svg_text(true, 400000, y, "Activating");
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering svg_text(true, 400000, y, "Deactivating");
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek svg_bar("unitsload", 0, 300000, y);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering svg_text(true, 400000, y, "Loading unit files");
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic int list_dependencies_print(const char *name, unsigned int level, unsigned int branches,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering bool last, struct unit_times *times, struct boot_times *boot) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering char ts[FORMAT_TIMESPAN_MAX], ts2[FORMAT_TIMESPAN_MAX];
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering for (i = level; i != 0; i--)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering printf("%s", draw_special_char(branches & (1 << (i-1)) ? DRAW_TREE_VERT : DRAW_TREE_SPACE));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering printf("%s", draw_special_char(last ? DRAW_TREE_RIGHT : DRAW_TREE_BRANCH));
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek printf("%s%s @%s +%s%s", ANSI_HIGHLIGHT_RED_ON, name,
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek format_timespan(ts, sizeof(ts), times->activating - boot->userspace_time, USEC_PER_MSEC),
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek format_timespan(ts2, sizeof(ts2), times->time, USEC_PER_MSEC), ANSI_HIGHLIGHT_OFF);
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek else if (times->activated > boot->userspace_time)
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek printf("%s @%s", name, format_timespan(ts, sizeof(ts), times->activated - boot->userspace_time, USEC_PER_MSEC));
2e8fb7026d3c560194cfe9f83935ce0b16263da0Lukas Nykrynstatic int list_dependencies_get_dependencies(sd_bus *bus, const char *name, char ***deps) {
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek r = bus_get_unit_property_strv(bus, path, "After", &ret);
if (times)
if (times)
unsigned int branches) {
int to_print = 0;
return log_oom();
if (times
|| service_longest == 0)) {
if (service_longest == 0 )
to_print++;
if(!to_print)
if (!times
to_print--;
if (!to_print)
return -EINVAL;
r = sd_bus_get_property(
bus,
"org.freedesktop.systemd1",
path,
"org.freedesktop.systemd1.Unit",
&error,
&reply,
if (times) {
printf("%s @%s\n", id, format_timespan(ts, sizeof(ts), times->activated - boot->userspace_time, USEC_PER_MSEC));
Hashmap *h;
return -ENOMEM;
unit_times_hashmap = h;
char **name;
hashmap_free(h);
static int graph_one_property(sd_bus *bus, const struct unit_info *u, const char* prop, const char *color, char* patterns[]) {
char **unit;
assert(u);
bool match_found;
match_found = false;
match_found = true;
if (!match_found)
match_found = false;
match_found = true;
if (!match_found)
match_found = false;
match_found = true;
if (!match_found)
assert(u);
struct unit_info u;
r = sd_bus_call_method(
bus,
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
"org.freedesktop.systemd1.Manager",
&error,
&reply,
if (on_tty())
"-- Try a shell pipeline like 'systemd-analyze dot | dot -Tsvg > systemd.svg'!\n");
return -E2BIG;
r = sd_bus_call_method(
bus,
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
"org.freedesktop.systemd1.Manager",
&error,
&reply,
return -E2BIG;
r = sd_bus_set_property(
bus,
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
"org.freedesktop.systemd1.Manager",
&error,
args[0]);
return -EIO;
static void analyze_help(void) {
* changes to shell-completion/bash/systemd and
* shell-completion/systemd-zsh-completion.zsh too. */
analyze_help();
case ARG_VERSION:
case ARG_USER:
case ARG_SYSTEM:
case ARG_ORDER:
case ARG_REQUIRE:
case ARG_DOT_FROM_PATTERN:
return log_oom();
case ARG_DOT_TO_PATTERN:
return log_oom();
case ARG_FUZZ:
case ARG_NO_PAGER:
arg_no_pager = true;
return -EINVAL;
log_open();
goto finish;
goto finish;
pager_close();