summaryrefslogtreecommitdiff
path: root/src/analyze/analyze-plot.c
diff options
context:
space:
mode:
authorJoshua Zivkovic <joshua.zivkovic@codethink.co.uk>2022-11-02 08:55:50 +0000
committerjoshuazivkovic <joshua.zivkovic@codethink.co.uk>2023-01-18 14:33:08 +0000
commitff46b2f97c42d73401ca3ffaaef54a017dc23923 (patch)
tree7720194dc7f32c5a11c5d837020cba7c4b17d7a3 /src/analyze/analyze-plot.c
parentdf0a741cdd7549ca8ceb4a3acf294dd7bf87a2c1 (diff)
downloadsystemd-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.c168
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, &times);
- 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, &times);
+ 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;
}