From: Philippe Proulx Date: Thu, 4 Jul 2019 06:00:18 +0000 (-0400) Subject: cli: print current thread's error causes, if any, before exiting X-Git-Url: http://git.efficios.com/?a=commitdiff_plain;h=f393c19b7abdcc7763d1e6bc045022edeebd283e;p=babeltrace.git cli: print current thread's error causes, if any, before exiting This patch makes the CLI print the error causes of the current thread's error object, if any, before it finally exits. The causes are printed from the most recent to the least recent. In other words, the root cause, or deepest cause, is printed at the end of the list. This is similar to what Python does when it prints a traceback. The CLI prints error causes with colors if supported to highlight the cause's module name, specific properties, file name, and line number. The CLI prints the messages indented with two spaces and folded on the terminal's current width if available, otherwise on 80 columns. You can test the output with babeltrace2 $(uuidgen) This prints something like: ERROR: [Babeltrace CLI] (babeltrace2.c:2531) Cannot create components. CAUSED BY [Babeltrace CLI] (babeltrace2.c:2355) Cannot create component: plugin-name="ctf", comp-cls-name="fs", comp-cls-type=0, comp-name="source-ctf-fs" CAUSED BY [Babeltrace library] (graph.c:1336) Component initialization method failed: status=ERROR, comp-addr=0x5590750b8fa0, comp-name="source-ctf-fs", comp-log-level=BT_LOGGING_LEVEL_WARN, comp-class-type=BT_COMPONENT_CLASS_TYPE_SOURCE, comp-class-name="fs", comp-class-partial-descr="Read CTF traces from the file sy", comp-class-is-frozen=0, comp-class-so-handle-addr=0x5590750b2aa0, comp-class-so-handle-path="babeltrace2/plugins/babeltrace-plugin-ctf.so", comp-input-port-count=0, comp-output-port-count=0 CAUSED BY [source-ctf-fs: 'source.ctf.fs'] (fs.c:1320) No CTF traces recursively found in `6419ec89-991d-4cf7-ab7f-b143a9901562`. Signed-off-by: Philippe Proulx Change-Id: Ib8101e097acf98db305775ac5b90f4eb006ce4ff Reviewed-on: https://review.lttng.org/c/babeltrace/+/1622 Tested-by: jenkins Reviewed-by: Francis Deslauriers Reviewed-by: Simon Marchi --- diff --git a/src/cli/babeltrace2.c b/src/cli/babeltrace2.c index 97ad6af9..fa37cf18 100644 --- a/src/cli/babeltrace2.c +++ b/src/cli/babeltrace2.c @@ -400,9 +400,11 @@ void print_plugin_comp_cls_opt(FILE *fh, const char *plugin_name, GString *shell_plugin_name = NULL; GString *shell_comp_cls_name = NULL; - shell_plugin_name = bt_common_shell_quote(plugin_name, false); - if (!shell_plugin_name) { - goto end; + if (plugin_name) { + shell_plugin_name = bt_common_shell_quote(plugin_name, false); + if (!shell_plugin_name) { + goto end; + } } shell_comp_cls_name = bt_common_shell_quote(comp_cls_name, false); @@ -410,14 +412,20 @@ void print_plugin_comp_cls_opt(FILE *fh, const char *plugin_name, goto end; } - fprintf(fh, "'%s%s%s%s.%s%s%s.%s%s%s'", + fprintf(fh, "'%s%s%s%s", bt_common_color_bold(), bt_common_color_fg_cyan(), component_type_str(type), - bt_common_color_fg_default(), - bt_common_color_fg_blue(), - shell_plugin_name->str, - bt_common_color_fg_default(), + bt_common_color_fg_default()); + + if (shell_plugin_name) { + fprintf(fh, ".%s%s%s", + bt_common_color_fg_blue(), + shell_plugin_name->str, + bt_common_color_fg_default()); + } + + fprintf(fh, ".%s%s%s'", bt_common_color_fg_yellow(), shell_comp_cls_name->str, bt_common_color_reset()); @@ -2719,6 +2727,123 @@ void set_auto_log_levels(struct bt_config *cfg) } } +static +void print_error_causes(void) +{ + const bt_error *error = bt_current_thread_take_error(); + int64_t i; + GString *folded = NULL; + unsigned int columns; + + if (!error || bt_error_get_cause_count(error) == 0) { + fprintf(stderr, "%s%sUnknown command-line error.%s\n", + bt_common_color_bold(), bt_common_color_fg_red(), + bt_common_color_reset()); + goto end; + } + + /* Try to get terminal width to fold the error cause messages */ + if (bt_common_get_term_size(&columns, NULL) < 0) { + /* Width not found: default to 80 */ + columns = 80; + } + + /* + * This helps visually separate the error causes from the last + * logging statement. + */ + fprintf(stderr, "\n"); + + /* Reverse order: deepest (root) cause printed at the end */ + for (i = bt_error_get_cause_count(error) - 1; i >= 0; i--) { + const bt_error_cause *cause = + bt_error_borrow_cause_by_index(error, (uint64_t) i); + const char *prefix_fmt = + i == bt_error_get_cause_count(error) - 1 ? + "%s%sERROR%s: " : "%s%sCAUSED BY%s "; + + /* Print prefix */ + fprintf(stderr, prefix_fmt, + bt_common_color_bold(), bt_common_color_fg_red(), + bt_common_color_reset()); + + /* Print actor name */ + fprintf(stderr, "["); + switch (bt_error_cause_get_actor_type(cause)) { + case BT_ERROR_CAUSE_ACTOR_TYPE_UNKNOWN: + fprintf(stderr, "%s%s%s", + bt_common_color_bold(), + bt_error_cause_get_module_name(cause), + bt_common_color_reset()); + break; + case BT_ERROR_CAUSE_ACTOR_TYPE_COMPONENT: + fprintf(stderr, "%s%s%s: ", + bt_common_color_bold(), + bt_error_cause_component_actor_get_component_name(cause), + bt_common_color_reset()); + print_plugin_comp_cls_opt(stderr, + bt_error_cause_component_actor_get_plugin_name(cause), + bt_error_cause_component_actor_get_component_class_name(cause), + bt_error_cause_component_actor_get_component_class_type(cause)); + break; + case BT_ERROR_CAUSE_ACTOR_TYPE_COMPONENT_CLASS: + print_plugin_comp_cls_opt(stderr, + bt_error_cause_component_class_actor_get_plugin_name(cause), + bt_error_cause_component_class_actor_get_component_class_name(cause), + bt_error_cause_component_class_actor_get_component_class_type(cause)); + break; + case BT_ERROR_CAUSE_ACTOR_TYPE_MESSAGE_ITERATOR: + fprintf(stderr, "%s%s%s (%s%s%s): ", + bt_common_color_bold(), + bt_error_cause_message_iterator_actor_get_component_name(cause), + bt_common_color_reset(), + bt_common_color_bold(), + bt_error_cause_message_iterator_actor_get_component_output_port_name(cause), + bt_common_color_reset()); + print_plugin_comp_cls_opt(stderr, + bt_error_cause_message_iterator_actor_get_plugin_name(cause), + bt_error_cause_message_iterator_actor_get_component_class_name(cause), + bt_error_cause_message_iterator_actor_get_component_class_type(cause)); + break; + default: + abort(); + } + + /* Print file name and line number */ + fprintf(stderr, "] (%s%s%s%s:%s%" PRIu64 "%s)\n", + bt_common_color_bold(), + bt_common_color_fg_magenta(), + bt_error_cause_get_file_name(cause), + bt_common_color_reset(), + bt_common_color_fg_green(), + bt_error_cause_get_line_number(cause), + bt_common_color_reset()); + + /* Print message */ + folded = bt_common_fold(bt_error_cause_get_message(cause), + columns, 2); + if (!folded) { + BT_LOGE_STR("Could not fold string."); + fprintf(stderr, "%s\n", + bt_error_cause_get_message(cause)); + continue; + } + + fprintf(stderr, "%s\n", folded->str); + g_string_free(folded, TRUE); + folded = NULL; + } + +end: + if (folded) { + g_string_free(folded, TRUE); + } + + if (error) { + bt_error_release(error); + } +} + int main(int argc, const char **argv) { int ret; @@ -2799,6 +2924,10 @@ end: BT_OBJECT_PUT_REF_AND_RESET(cfg); fini_static_data(); + if (retcode != 0) { + print_error_causes(); + } + /* * Clear current thread's error in case there is one to avoid a * memory leak.