diff options
author | Joshua Zivkovic <joshua.zivkovic@codethink.co.uk> | 2022-11-02 08:55:50 +0000 |
---|---|---|
committer | joshuazivkovic <joshua.zivkovic@codethink.co.uk> | 2023-01-18 14:33:08 +0000 |
commit | ff46b2f97c42d73401ca3ffaaef54a017dc23923 (patch) | |
tree | 7720194dc7f32c5a11c5d837020cba7c4b17d7a3 /src/analyze/analyze-plot.c | |
parent | df0a741cdd7549ca8ceb4a3acf294dd7bf87a2c1 (diff) | |
download | systemd-ff46b2f97c42d73401ca3ffaaef54a017dc23923.tar.gz |
systemd-analyze: Add table and JSON output implementation to plot
Diffstat (limited to 'src/analyze/analyze-plot.c')
-rw-r--r-- | src/analyze/analyze-plot.c | 168 |
1 files changed, 121 insertions, 47 deletions
diff --git a/src/analyze/analyze-plot.c b/src/analyze/analyze-plot.c index 100bdc3787..24f4add099 100644 --- a/src/analyze/analyze-plot.c +++ b/src/analyze/analyze-plot.c @@ -5,6 +5,7 @@ #include "analyze-time-data.h" #include "bus-error.h" #include "bus-map-properties.h" +#include "format-table.h" #include "sort-util.h" #include "version.h" @@ -37,7 +38,7 @@ typedef struct HostInfo { char *architecture; } HostInfo; -static HostInfo* free_host_info(HostInfo *hi) { +static HostInfo *free_host_info(HostInfo *hi) { if (!hi) return NULL; @@ -87,7 +88,7 @@ static int acquire_host_info(sd_bus *bus, HostInfo **hi) { } r = bus_map_all_properties( - system_bus ?: bus, + system_bus ? : bus, "org.freedesktop.hostname1", "/org/freedesktop/hostname1", hostname_map, @@ -156,15 +157,14 @@ static void svg_graph_box(double height, double begin, double end) { SCALE_Y * height); } } - static int plot_unit_times(UnitTimes *u, double width, int y) { bool b; if (!u->name) return 0; - svg_bar("activating", u->activating, u->activated, y); - svg_bar("active", u->activated, u->deactivating, y); + svg_bar("activating", u->activating, u->activated, y); + svg_bar("active", u->activated, u->deactivating, y); svg_bar("deactivating", u->deactivating, u->deactivated, y); /* place the text on the left if we have passed the half of the svg width */ @@ -178,41 +178,27 @@ static int plot_unit_times(UnitTimes *u, double width, int y) { return 1; } -int verb_plot(int argc, char *argv[], void *userdata) { - _cleanup_(free_host_infop) HostInfo *host = NULL; - _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; - _cleanup_(unit_times_free_arrayp) UnitTimes *times = NULL; - _cleanup_free_ char *pretty_times = NULL; - bool use_full_bus = arg_scope == LOOKUP_SCOPE_SYSTEM; - BootTimes *boot; +static void limit_times_to_boot(const BootTimes *boot, UnitTimes *u) { + if (u->deactivated > u->activating && u->deactivated <= boot->finish_time && u->activated == 0 + && u->deactivating == 0) + u->activated = u->deactivating = u->deactivated; + if (u->activated < u->activating || u->activated > boot->finish_time) + u->activated = boot->finish_time; + if (u->deactivating < u->activated || u->deactivating > boot->finish_time) + u->deactivating = boot->finish_time; + if (u->deactivated < u->deactivating || u->deactivated > boot->finish_time) + u->deactivated = boot->finish_time; +} + +static int produce_plot_as_svg( + UnitTimes *times, + const HostInfo *host, + const BootTimes *boot, + const char *pretty_times) { + int m = 1, y = 0; UnitTimes *u; - int n, m = 1, y = 0, r; double width; - r = acquire_bus(&bus, &use_full_bus); - if (r < 0) - return bus_log_connect_error(r, arg_transport); - - n = acquire_boot_times(bus, &boot); - if (n < 0) - return n; - - n = pretty_boot_time(bus, &pretty_times); - if (n < 0) - return n; - - if (use_full_bus || arg_scope != LOOKUP_SCOPE_SYSTEM) { - n = acquire_host_info(bus, &host); - if (n < 0) - return n; - } - - n = acquire_time_data(bus, ×); - if (n <= 0) - return n; - - typesafe_qsort(times, n, compare_unit_start); - width = SCALE_X * (boot->firmware_time + boot->finish_time); if (width < 800.0) width = 800.0; @@ -245,16 +231,8 @@ int verb_plot(int argc, char *argv[], void *userdata) { if (text_width > text_start && text_width + text_start > width) width = text_width + text_start; - if (u->deactivated > u->activating && - u->deactivated <= boot->finish_time && - u->activated == 0 && u->deactivating == 0) - u->activated = u->deactivating = u->deactivated; - if (u->activated < u->activating || u->activated > boot->finish_time) - u->activated = boot->finish_time; - if (u->deactivating < u->activated || u->deactivating > boot->finish_time) - u->deactivating = boot->finish_time; - if (u->deactivated < u->deactivating || u->deactivated > boot->finish_time) - u->deactivated = boot->finish_time; + limit_times_to_boot(boot, u); + m++; } @@ -391,5 +369,101 @@ int verb_plot(int argc, char *argv[], void *userdata) { svg("</svg>\n"); + return 0; +} + +static int show_table(Table *table, const char *word) { + int r; + + assert(table); + assert(word); + + if (table_get_rows(table) > 1) { + table_set_header(table, arg_legend); + + if (!FLAGS_SET(arg_json_format_flags, JSON_FORMAT_OFF)) + r = table_print_json(table, NULL, arg_json_format_flags | JSON_FORMAT_COLOR_AUTO); + else + r = table_print(table, NULL); + if (r < 0) + return table_log_print_error(r); + } + + if (arg_legend) { + if (table_get_rows(table) > 1) + printf("\n%zu %s listed.\n", table_get_rows(table) - 1, word); + else + printf("No %s.\n", word); + } + + return 0; +} + +static int produce_plot_as_text(UnitTimes *times, const BootTimes *boot) { + _cleanup_(table_unrefp) Table *table = NULL; + int r; + + table = table_new("name", "activated", "activating", "time", "deactivated", "deactivating"); + if (!table) + return log_oom(); + + for (; times->has_data; times++) { + limit_times_to_boot(boot, times); + + r = table_add_many( + table, + TABLE_STRING, times->name, + TABLE_TIMESPAN_MSEC, times->activated, + TABLE_TIMESPAN_MSEC, times->activating, + TABLE_TIMESPAN_MSEC, times->time, + TABLE_TIMESPAN_MSEC, times->deactivated, + TABLE_TIMESPAN_MSEC, times->deactivating); + if (r < 0) + return table_log_add_error(r); + } + + return show_table(table, "Units"); +} + +int verb_plot(int argc, char *argv[], void *userdata) { + _cleanup_(free_host_infop) HostInfo *host = NULL; + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + _cleanup_(unit_times_free_arrayp) UnitTimes *times = NULL; + _cleanup_free_ char *pretty_times = NULL; + bool use_full_bus = arg_scope == LOOKUP_SCOPE_SYSTEM; + BootTimes *boot; + int n, r; + + r = acquire_bus(&bus, &use_full_bus); + if (r < 0) + return bus_log_connect_error(r, arg_transport); + + n = acquire_boot_times(bus, &boot); + if (n < 0) + return n; + + n = pretty_boot_time(bus, &pretty_times); + if (n < 0) + return n; + + if (use_full_bus || arg_scope != LOOKUP_SCOPE_SYSTEM) { + n = acquire_host_info(bus, &host); + if (n < 0) + return n; + } + + n = acquire_time_data(bus, ×); + if (n <= 0) + return n; + + typesafe_qsort(times, n, compare_unit_start); + + if (!FLAGS_SET(arg_json_format_flags, JSON_FORMAT_OFF) || arg_table) + r = produce_plot_as_text(times, boot); + else + r = produce_plot_as_svg(times, host, boot, pretty_times); + if (r < 0) + return r; + return EXIT_SUCCESS; } |