From: Lennart Poettering Date: Mon, 21 Feb 2022 12:27:08 +0000 (+0100) Subject: analyze: split out "blame" verb + time helpers X-Git-Tag: v251-rc1~249^2~13 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=113dd9cbc402c6560d692d027594f640462c2c8e;p=thirdparty%2Fsystemd.git analyze: split out "blame" verb + time helpers --- diff --git a/src/analyze/analyze-blame.c b/src/analyze/analyze-blame.c new file mode 100644 index 00000000000..6e0e560377d --- /dev/null +++ b/src/analyze/analyze-blame.c @@ -0,0 +1,65 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +#include "analyze.h" +#include "analyze-blame.h" +#include "analyze-time-data.h" +#include "format-table.h" + +int analyze_blame(int argc, char *argv[], void *userdata) { + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + _cleanup_(unit_times_free_arrayp) UnitTimes *times = NULL; + _cleanup_(table_unrefp) Table *table = NULL; + TableCell *cell; + int n, r; + + r = acquire_bus(&bus, NULL); + if (r < 0) + return bus_log_connect_error(r, arg_transport); + + n = acquire_time_data(bus, ×); + if (n <= 0) + return n; + + table = table_new("time", "unit"); + if (!table) + return log_oom(); + + table_set_header(table, false); + + assert_se(cell = table_get_cell(table, 0, 0)); + r = table_set_ellipsize_percent(table, cell, 100); + if (r < 0) + return r; + + r = table_set_align_percent(table, cell, 100); + if (r < 0) + return r; + + assert_se(cell = table_get_cell(table, 0, 1)); + r = table_set_ellipsize_percent(table, cell, 100); + if (r < 0) + return r; + + r = table_set_sort(table, (size_t) 0); + if (r < 0) + return r; + + r = table_set_reverse(table, 0, true); + if (r < 0) + return r; + + for (UnitTimes *u = times; u->has_data; u++) { + if (u->time <= 0) + continue; + + r = table_add_many(table, + TABLE_TIMESPAN_MSEC, u->time, + TABLE_STRING, u->name); + if (r < 0) + return table_log_add_error(r); + } + + pager_open(arg_pager_flags); + + return table_print(table, NULL); +} diff --git a/src/analyze/analyze-blame.h b/src/analyze/analyze-blame.h new file mode 100644 index 00000000000..f099343bc10 --- /dev/null +++ b/src/analyze/analyze-blame.h @@ -0,0 +1,4 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +#pragma once + +int analyze_blame(int argc, char *argv[], void *userdata); diff --git a/src/analyze/analyze-time-data.c b/src/analyze/analyze-time-data.c new file mode 100644 index 00000000000..00aac100e8a --- /dev/null +++ b/src/analyze/analyze-time-data.c @@ -0,0 +1,193 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +#include "analyze.h" +#include "analyze-time-data.h" +#include "bus-error.h" +#include "bus-locator.h" +#include "bus-map-properties.h" +#include "bus-unit-util.h" + +static void subtract_timestamp(usec_t *a, usec_t b) { + assert(a); + + if (*a > 0) { + assert(*a >= b); + *a -= b; + } +} + +int acquire_boot_times(sd_bus *bus, BootTimes **ret) { + static const struct bus_properties_map property_map[] = { + { "FirmwareTimestampMonotonic", "t", NULL, offsetof(BootTimes, firmware_time) }, + { "LoaderTimestampMonotonic", "t", NULL, offsetof(BootTimes, loader_time) }, + { "KernelTimestamp", "t", NULL, offsetof(BootTimes, kernel_time) }, + { "InitRDTimestampMonotonic", "t", NULL, offsetof(BootTimes, initrd_time) }, + { "UserspaceTimestampMonotonic", "t", NULL, offsetof(BootTimes, userspace_time) }, + { "FinishTimestampMonotonic", "t", NULL, offsetof(BootTimes, finish_time) }, + { "SecurityStartTimestampMonotonic", "t", NULL, offsetof(BootTimes, security_start_time) }, + { "SecurityFinishTimestampMonotonic", "t", NULL, offsetof(BootTimes, security_finish_time) }, + { "GeneratorsStartTimestampMonotonic", "t", NULL, offsetof(BootTimes, generators_start_time) }, + { "GeneratorsFinishTimestampMonotonic", "t", NULL, offsetof(BootTimes, generators_finish_time) }, + { "UnitsLoadStartTimestampMonotonic", "t", NULL, offsetof(BootTimes, unitsload_start_time) }, + { "UnitsLoadFinishTimestampMonotonic", "t", NULL, offsetof(BootTimes, unitsload_finish_time) }, + { "InitRDSecurityStartTimestampMonotonic", "t", NULL, offsetof(BootTimes, initrd_security_start_time) }, + { "InitRDSecurityFinishTimestampMonotonic", "t", NULL, offsetof(BootTimes, initrd_security_finish_time) }, + { "InitRDGeneratorsStartTimestampMonotonic", "t", NULL, offsetof(BootTimes, initrd_generators_start_time) }, + { "InitRDGeneratorsFinishTimestampMonotonic", "t", NULL, offsetof(BootTimes, initrd_generators_finish_time) }, + { "InitRDUnitsLoadStartTimestampMonotonic", "t", NULL, offsetof(BootTimes, initrd_unitsload_start_time) }, + { "InitRDUnitsLoadFinishTimestampMonotonic", "t", NULL, offsetof(BootTimes, initrd_unitsload_finish_time) }, + {}, + }; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + static BootTimes times; + static bool cached = false; + int r; + + if (cached) + goto finish; + + assert_cc(sizeof(usec_t) == sizeof(uint64_t)); + + r = bus_map_all_properties( + bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + property_map, + BUS_MAP_STRDUP, + &error, + NULL, + ×); + if (r < 0) + return log_error_errno(r, "Failed to get timestamp properties: %s", bus_error_message(&error, r)); + + if (times.finish_time <= 0) + return log_error_errno(SYNTHETIC_ERRNO(EINPROGRESS), + "Bootup is not yet finished (org.freedesktop.systemd1.Manager.FinishTimestampMonotonic=%"PRIu64").\n" + "Please try again later.\n" + "Hint: Use 'systemctl%s list-jobs' to see active jobs", + times.finish_time, + arg_scope == UNIT_FILE_SYSTEM ? "" : " --user"); + + if (arg_scope == UNIT_FILE_SYSTEM && times.security_start_time > 0) { + /* security_start_time is set when systemd is not running under container environment. */ + if (times.initrd_time > 0) + times.kernel_done_time = times.initrd_time; + else + times.kernel_done_time = times.userspace_time; + } else { + /* + * User-instance-specific or container-system-specific timestamps processing + * (see comment to reverse_offset in BootTimes). + */ + times.reverse_offset = times.userspace_time; + + times.firmware_time = times.loader_time = times.kernel_time = times.initrd_time = + times.userspace_time = times.security_start_time = times.security_finish_time = 0; + + subtract_timestamp(×.finish_time, times.reverse_offset); + + subtract_timestamp(×.generators_start_time, times.reverse_offset); + subtract_timestamp(×.generators_finish_time, times.reverse_offset); + + subtract_timestamp(×.unitsload_start_time, times.reverse_offset); + subtract_timestamp(×.unitsload_finish_time, times.reverse_offset); + } + + cached = true; + +finish: + *ret = × + return 0; +} + +UnitTimes* unit_times_free_array(UnitTimes *t) { + if (!t) + return NULL; + + for (UnitTimes *p = t; p->has_data; p++) + free(p->name); + + return mfree(t); +} + +int acquire_time_data(sd_bus *bus, UnitTimes **out) { + static const struct bus_properties_map property_map[] = { + { "InactiveExitTimestampMonotonic", "t", NULL, offsetof(UnitTimes, activating) }, + { "ActiveEnterTimestampMonotonic", "t", NULL, offsetof(UnitTimes, activated) }, + { "ActiveExitTimestampMonotonic", "t", NULL, offsetof(UnitTimes, deactivating) }, + { "InactiveEnterTimestampMonotonic", "t", NULL, offsetof(UnitTimes, deactivated) }, + {}, + }; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(unit_times_free_arrayp) UnitTimes *unit_times = NULL; + BootTimes *boot_times = NULL; + size_t c = 0; + UnitInfo u; + int r; + + r = acquire_boot_times(bus, &boot_times); + if (r < 0) + return r; + + r = bus_call_method(bus, bus_systemd_mgr, "ListUnits", &error, &reply, NULL); + if (r < 0) + return log_error_errno(r, "Failed to list units: %s", bus_error_message(&error, r)); + + r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssssouso)"); + if (r < 0) + return bus_log_parse_error(r); + + while ((r = bus_parse_unit_info(reply, &u)) > 0) { + UnitTimes *t; + + if (!GREEDY_REALLOC(unit_times, c + 2)) + return log_oom(); + + unit_times[c + 1].has_data = false; + t = &unit_times[c]; + t->name = NULL; + + assert_cc(sizeof(usec_t) == sizeof(uint64_t)); + + r = bus_map_all_properties( + bus, + "org.freedesktop.systemd1", + u.unit_path, + property_map, + BUS_MAP_STRDUP, + &error, + NULL, + t); + if (r < 0) + return log_error_errno(r, "Failed to get timestamp properties of unit %s: %s", + u.id, bus_error_message(&error, r)); + + subtract_timestamp(&t->activating, boot_times->reverse_offset); + subtract_timestamp(&t->activated, boot_times->reverse_offset); + subtract_timestamp(&t->deactivating, boot_times->reverse_offset); + subtract_timestamp(&t->deactivated, boot_times->reverse_offset); + + if (t->activated >= t->activating) + t->time = t->activated - t->activating; + else if (t->deactivated >= t->activating) + t->time = t->deactivated - t->activating; + else + t->time = 0; + + if (t->activating == 0) + continue; + + t->name = strdup(u.id); + if (!t->name) + return log_oom(); + + t->has_data = true; + c++; + } + if (r < 0) + return bus_log_parse_error(r); + + *out = TAKE_PTR(unit_times); + return c; +} diff --git a/src/analyze/analyze-time-data.h b/src/analyze/analyze-time-data.h new file mode 100644 index 00000000000..18e828857c6 --- /dev/null +++ b/src/analyze/analyze-time-data.h @@ -0,0 +1,53 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +#pragma once + +#include "time-util.h" + +typedef struct BootTimes { + usec_t firmware_time; + usec_t loader_time; + usec_t kernel_time; + usec_t kernel_done_time; + usec_t initrd_time; + usec_t userspace_time; + usec_t finish_time; + usec_t security_start_time; + usec_t security_finish_time; + usec_t generators_start_time; + usec_t generators_finish_time; + usec_t unitsload_start_time; + usec_t unitsload_finish_time; + usec_t initrd_security_start_time; + usec_t initrd_security_finish_time; + usec_t initrd_generators_start_time; + usec_t initrd_generators_finish_time; + usec_t initrd_unitsload_start_time; + usec_t initrd_unitsload_finish_time; + + /* + * If we're analyzing the user instance, all timestamps will be offset by its own start-up timestamp, + * which may be arbitrarily big. With "plot", this causes arbitrarily wide output SVG files which + * almost completely consist of empty space. Thus we cancel out this offset. + * + * This offset is subtracted from times above by acquire_boot_times(), but it still needs to be + * subtracted from unit-specific timestamps (so it is stored here for reference). + */ + usec_t reverse_offset; +} BootTimes; + +typedef struct UnitTimes { + bool has_data; + char *name; + usec_t activating; + usec_t activated; + usec_t deactivated; + usec_t deactivating; + usec_t time; +} UnitTimes; + +int acquire_boot_times(sd_bus *bus, BootTimes **ret); + +UnitTimes* unit_times_free_array(UnitTimes *t); +DEFINE_TRIVIAL_CLEANUP_FUNC(UnitTimes*, unit_times_free_array); + +int acquire_time_data(sd_bus *bus, UnitTimes **out); diff --git a/src/analyze/analyze.c b/src/analyze/analyze.c index 2d47d27d6f1..32276c78fb3 100644 --- a/src/analyze/analyze.c +++ b/src/analyze/analyze.c @@ -13,6 +13,7 @@ #include "alloc-util.h" #include "analyze.h" +#include "analyze-blame.h" #include "analyze-calendar.h" #include "analyze-capability.h" #include "analyze-condition.h" @@ -24,6 +25,7 @@ #include "analyze-security.h" #include "analyze-service-watchdogs.h" #include "analyze-syscall-filter.h" +#include "analyze-time-data.h" #include "analyze-timespan.h" #include "analyze-timestamp.h" #include "analyze-verify.h" @@ -98,7 +100,7 @@ static usec_t arg_fuzz = 0; PagerFlags arg_pager_flags = 0; BusTransport arg_transport = BUS_TRANSPORT_LOCAL; static const char *arg_host = NULL; -static UnitFileScope arg_scope = UNIT_FILE_SYSTEM; +UnitFileScope arg_scope = UNIT_FILE_SYSTEM; static RecursiveErrors arg_recursive_errors = RECURSIVE_ERRORS_YES; static bool arg_man = true; static bool arg_generators = false; @@ -122,50 +124,6 @@ STATIC_DESTRUCTOR_REGISTER(arg_security_policy, freep); STATIC_DESTRUCTOR_REGISTER(arg_unit, freep); STATIC_DESTRUCTOR_REGISTER(arg_profile, freep); -typedef struct BootTimes { - usec_t firmware_time; - usec_t loader_time; - usec_t kernel_time; - usec_t kernel_done_time; - usec_t initrd_time; - usec_t userspace_time; - usec_t finish_time; - usec_t security_start_time; - usec_t security_finish_time; - usec_t generators_start_time; - usec_t generators_finish_time; - usec_t unitsload_start_time; - usec_t unitsload_finish_time; - usec_t initrd_security_start_time; - usec_t initrd_security_finish_time; - usec_t initrd_generators_start_time; - usec_t initrd_generators_finish_time; - usec_t initrd_unitsload_start_time; - usec_t initrd_unitsload_finish_time; - - /* - * If we're analyzing the user instance, all timestamps will be offset - * by its own start-up timestamp, which may be arbitrarily big. - * With "plot", this causes arbitrarily wide output SVG files which almost - * completely consist of empty space. Thus we cancel out this offset. - * - * This offset is subtracted from times above by acquire_boot_times(), - * but it still needs to be subtracted from unit-specific timestamps - * (so it is stored here for reference). - */ - usec_t reverse_offset; -} BootTimes; - -typedef struct UnitTimes { - bool has_data; - char *name; - usec_t activating; - usec_t activated; - usec_t deactivated; - usec_t deactivating; - usec_t time; -} UnitTimes; - typedef struct HostInfo { char *hostname; char *kernel_name; @@ -209,7 +167,6 @@ static int bus_get_uint64_property(sd_bus *bus, const char *path, const char *in property, &error, 't', val); - if (r < 0) return log_error_errno(r, "Failed to parse reply: %s", bus_error_message(&error, r)); @@ -290,106 +247,6 @@ static int process_aliases(char *argv[], char *tempdir, char ***ret) { return 0; } -static UnitTimes* unit_times_free_array(UnitTimes *t) { - for (UnitTimes *p = t; p && p->has_data; p++) - free(p->name); - return mfree(t); -} -DEFINE_TRIVIAL_CLEANUP_FUNC(UnitTimes*, unit_times_free_array); - -static void subtract_timestamp(usec_t *a, usec_t b) { - assert(a); - - if (*a > 0) { - assert(*a >= b); - *a -= b; - } -} - -static int acquire_boot_times(sd_bus *bus, BootTimes **bt) { - static const struct bus_properties_map property_map[] = { - { "FirmwareTimestampMonotonic", "t", NULL, offsetof(BootTimes, firmware_time) }, - { "LoaderTimestampMonotonic", "t", NULL, offsetof(BootTimes, loader_time) }, - { "KernelTimestamp", "t", NULL, offsetof(BootTimes, kernel_time) }, - { "InitRDTimestampMonotonic", "t", NULL, offsetof(BootTimes, initrd_time) }, - { "UserspaceTimestampMonotonic", "t", NULL, offsetof(BootTimes, userspace_time) }, - { "FinishTimestampMonotonic", "t", NULL, offsetof(BootTimes, finish_time) }, - { "SecurityStartTimestampMonotonic", "t", NULL, offsetof(BootTimes, security_start_time) }, - { "SecurityFinishTimestampMonotonic", "t", NULL, offsetof(BootTimes, security_finish_time) }, - { "GeneratorsStartTimestampMonotonic", "t", NULL, offsetof(BootTimes, generators_start_time) }, - { "GeneratorsFinishTimestampMonotonic", "t", NULL, offsetof(BootTimes, generators_finish_time) }, - { "UnitsLoadStartTimestampMonotonic", "t", NULL, offsetof(BootTimes, unitsload_start_time) }, - { "UnitsLoadFinishTimestampMonotonic", "t", NULL, offsetof(BootTimes, unitsload_finish_time) }, - { "InitRDSecurityStartTimestampMonotonic", "t", NULL, offsetof(BootTimes, initrd_security_start_time) }, - { "InitRDSecurityFinishTimestampMonotonic", "t", NULL, offsetof(BootTimes, initrd_security_finish_time) }, - { "InitRDGeneratorsStartTimestampMonotonic", "t", NULL, offsetof(BootTimes, initrd_generators_start_time) }, - { "InitRDGeneratorsFinishTimestampMonotonic", "t", NULL, offsetof(BootTimes, initrd_generators_finish_time) }, - { "InitRDUnitsLoadStartTimestampMonotonic", "t", NULL, offsetof(BootTimes, initrd_unitsload_start_time) }, - { "InitRDUnitsLoadFinishTimestampMonotonic", "t", NULL, offsetof(BootTimes, initrd_unitsload_finish_time) }, - {}, - }; - _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; - static BootTimes times; - static bool cached = false; - int r; - - if (cached) - goto finish; - - assert_cc(sizeof(usec_t) == sizeof(uint64_t)); - - r = bus_map_all_properties( - bus, - "org.freedesktop.systemd1", - "/org/freedesktop/systemd1", - property_map, - BUS_MAP_STRDUP, - &error, - NULL, - ×); - if (r < 0) - return log_error_errno(r, "Failed to get timestamp properties: %s", bus_error_message(&error, r)); - - if (times.finish_time <= 0) - return log_error_errno(SYNTHETIC_ERRNO(EINPROGRESS), - "Bootup is not yet finished (org.freedesktop.systemd1.Manager.FinishTimestampMonotonic=%"PRIu64").\n" - "Please try again later.\n" - "Hint: Use 'systemctl%s list-jobs' to see active jobs", - times.finish_time, - arg_scope == UNIT_FILE_SYSTEM ? "" : " --user"); - - if (arg_scope == UNIT_FILE_SYSTEM && times.security_start_time > 0) { - /* security_start_time is set when systemd is not running under container environment. */ - if (times.initrd_time > 0) - times.kernel_done_time = times.initrd_time; - else - times.kernel_done_time = times.userspace_time; - } else { - /* - * User-instance-specific or container-system-specific timestamps processing - * (see comment to reverse_offset in BootTimes). - */ - times.reverse_offset = times.userspace_time; - - times.firmware_time = times.loader_time = times.kernel_time = times.initrd_time = - times.userspace_time = times.security_start_time = times.security_finish_time = 0; - - subtract_timestamp(×.finish_time, times.reverse_offset); - - subtract_timestamp(×.generators_start_time, times.reverse_offset); - subtract_timestamp(×.generators_finish_time, times.reverse_offset); - - subtract_timestamp(×.unitsload_start_time, times.reverse_offset); - subtract_timestamp(×.unitsload_finish_time, times.reverse_offset); - } - - cached = true; - -finish: - *bt = × - return 0; -} - static HostInfo* free_host_info(HostInfo *hi) { if (!hi) return NULL; @@ -406,88 +263,6 @@ static HostInfo* free_host_info(HostInfo *hi) { DEFINE_TRIVIAL_CLEANUP_FUNC(HostInfo *, free_host_info); -static int acquire_time_data(sd_bus *bus, UnitTimes **out) { - static const struct bus_properties_map property_map[] = { - { "InactiveExitTimestampMonotonic", "t", NULL, offsetof(UnitTimes, activating) }, - { "ActiveEnterTimestampMonotonic", "t", NULL, offsetof(UnitTimes, activated) }, - { "ActiveExitTimestampMonotonic", "t", NULL, offsetof(UnitTimes, deactivating) }, - { "InactiveEnterTimestampMonotonic", "t", NULL, offsetof(UnitTimes, deactivated) }, - {}, - }; - _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; - _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; - _cleanup_(unit_times_free_arrayp) UnitTimes *unit_times = NULL; - BootTimes *boot_times = NULL; - size_t c = 0; - UnitInfo u; - int r; - - r = acquire_boot_times(bus, &boot_times); - if (r < 0) - return r; - - r = bus_call_method(bus, bus_systemd_mgr, "ListUnits", &error, &reply, NULL); - if (r < 0) - return log_error_errno(r, "Failed to list units: %s", bus_error_message(&error, r)); - - r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssssouso)"); - if (r < 0) - return bus_log_parse_error(r); - - while ((r = bus_parse_unit_info(reply, &u)) > 0) { - UnitTimes *t; - - if (!GREEDY_REALLOC(unit_times, c + 2)) - return log_oom(); - - unit_times[c + 1].has_data = false; - t = &unit_times[c]; - t->name = NULL; - - assert_cc(sizeof(usec_t) == sizeof(uint64_t)); - - r = bus_map_all_properties( - bus, - "org.freedesktop.systemd1", - u.unit_path, - property_map, - BUS_MAP_STRDUP, - &error, - NULL, - t); - if (r < 0) - return log_error_errno(r, "Failed to get timestamp properties of unit %s: %s", - u.id, bus_error_message(&error, r)); - - subtract_timestamp(&t->activating, boot_times->reverse_offset); - subtract_timestamp(&t->activated, boot_times->reverse_offset); - subtract_timestamp(&t->deactivating, boot_times->reverse_offset); - subtract_timestamp(&t->deactivated, boot_times->reverse_offset); - - if (t->activated >= t->activating) - t->time = t->activated - t->activating; - else if (t->deactivated >= t->activating) - t->time = t->deactivated - t->activating; - else - t->time = 0; - - if (t->activating == 0) - continue; - - t->name = strdup(u.id); - if (!t->name) - return log_oom(); - - t->has_data = true; - c++; - } - if (r < 0) - return bus_log_parse_error(r); - - *out = TAKE_PTR(unit_times); - return c; -} - static int acquire_host_info(sd_bus *bus, HostInfo **hi) { static const struct bus_properties_map hostname_map[] = { { "Hostname", "s", NULL, offsetof(HostInfo, hostname) }, @@ -1127,65 +902,6 @@ static int analyze_critical_chain(int argc, char *argv[], void *userdata) { return 0; } -static int analyze_blame(int argc, char *argv[], void *userdata) { - _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; - _cleanup_(unit_times_free_arrayp) UnitTimes *times = NULL; - _cleanup_(table_unrefp) Table *table = NULL; - TableCell *cell; - int n, r; - - r = acquire_bus(&bus, NULL); - if (r < 0) - return bus_log_connect_error(r, arg_transport); - - n = acquire_time_data(bus, ×); - if (n <= 0) - return n; - - table = table_new("time", "unit"); - if (!table) - return log_oom(); - - table_set_header(table, false); - - assert_se(cell = table_get_cell(table, 0, 0)); - r = table_set_ellipsize_percent(table, cell, 100); - if (r < 0) - return r; - - r = table_set_align_percent(table, cell, 100); - if (r < 0) - return r; - - assert_se(cell = table_get_cell(table, 0, 1)); - r = table_set_ellipsize_percent(table, cell, 100); - if (r < 0) - return r; - - r = table_set_sort(table, (size_t) 0); - if (r < 0) - return r; - - r = table_set_reverse(table, 0, true); - if (r < 0) - return r; - - for (UnitTimes *u = times; u->has_data; u++) { - if (u->time <= 0) - continue; - - r = table_add_many(table, - TABLE_TIMESPAN_MSEC, u->time, - TABLE_STRING, u->name); - if (r < 0) - return table_log_add_error(r); - } - - pager_open(arg_pager_flags); - - return table_print(table, NULL); -} - static int analyze_time(int argc, char *argv[], void *userdata) { _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; _cleanup_free_ char *buf = NULL; diff --git a/src/analyze/analyze.h b/src/analyze/analyze.h index 1819b5d731d..cd978a532fa 100644 --- a/src/analyze/analyze.h +++ b/src/analyze/analyze.h @@ -6,6 +6,7 @@ #include "bus-util.h" #include "pager.h" #include "time-util.h" +#include "unit-file.h" typedef enum DotMode { DEP_ALL, @@ -17,6 +18,7 @@ extern DotMode arg_dot; extern char **arg_dot_from_patterns, **arg_dot_to_patterns; extern PagerFlags arg_pager_flags; extern BusTransport arg_transport; +extern UnitFileScope arg_scope; extern unsigned arg_iterations; extern usec_t arg_base_time; extern bool arg_quiet; diff --git a/src/analyze/meson.build b/src/analyze/meson.build index 8e9e780c71f..30fa0487fb0 100644 --- a/src/analyze/meson.build +++ b/src/analyze/meson.build @@ -1,6 +1,8 @@ # SPDX-License-Identifier: LGPL-2.1-or-later systemd_analyze_sources = files(''' + analyze-blame.c + analyze-blame.h analyze-calendar.c analyze-calendar.h analyze-capability.c @@ -23,6 +25,8 @@ systemd_analyze_sources = files(''' analyze-service-watchdogs.h analyze-syscall-filter.c analyze-syscall-filter.h + analyze-time-data.c + analyze-time-data.h analyze-timespan.c analyze-timespan.h analyze-timestamp.c