From baa9c5f091302dc63d15386e082cabe720d5d84d Mon Sep 17 00:00:00 2001 From: Simon Marchi Date: Thu, 28 Nov 2019 11:30:03 -0500 Subject: [PATCH] string-format: introduce function to format a bt_error The CLI has a function to format a bt_error nicely. We will want to use it in the Python bindings too, so move it to the string-format convenience library. Make it return the formatted string instead of printing directly to stderr. I did not try to make this function handle memory allocation errors, as: 1. It's not very likely anyway 2. We are likely in the process of handling an error, I don't think it would be useful to return an error code. If something fails in this function, I don't know what else remains to do. Change-Id: Ia540b95bd9e1aca7899e5fbccfe3fba463457e3c Signed-off-by: Simon Marchi Reviewed-on: https://review.lttng.org/c/babeltrace/+/2433 Tested-by: jenkins --- src/cli/babeltrace2.c | 105 ++------------------- src/string-format/Makefile.am | 4 +- src/string-format/format-error.c | 155 +++++++++++++++++++++++++++++++ src/string-format/format-error.h | 38 ++++++++ 4 files changed, 204 insertions(+), 98 deletions(-) create mode 100644 src/string-format/format-error.c create mode 100644 src/string-format/format-error.h diff --git a/src/cli/babeltrace2.c b/src/cli/babeltrace2.c index f5164ccb..ad211fa2 100644 --- a/src/cli/babeltrace2.c +++ b/src/cli/babeltrace2.c @@ -27,6 +27,7 @@ #include #include "common/common.h" +#include "string-format/format-error.h" #include "string-format/format-plugin-comp-cls-name.h" #include #include @@ -2591,10 +2592,8 @@ static void print_error_causes(void) { const bt_error *error = bt_current_thread_take_error(); - int64_t i; - GString *folded = NULL; unsigned int columns; - gchar *comp_cls_str = NULL; + gchar *error_str = NULL; if (!error || bt_error_get_cause_count(error) == 0) { fprintf(stderr, "%s%sUnknown command-line error.%s\n", @@ -2613,108 +2612,20 @@ void print_error_causes(void) * 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_bright_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: - comp_cls_str = format_plugin_comp_cls_opt( - 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), - BT_COMMON_COLOR_WHEN_AUTO); - BT_ASSERT(comp_cls_str); - - fprintf(stderr, "%s%s%s: %s", - bt_common_color_bold(), - bt_error_cause_component_actor_get_component_name(cause), - bt_common_color_reset(), - comp_cls_str); - break; - case BT_ERROR_CAUSE_ACTOR_TYPE_COMPONENT_CLASS: - comp_cls_str = format_plugin_comp_cls_opt( - 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), - BT_COMMON_COLOR_WHEN_AUTO); - BT_ASSERT(comp_cls_str); - - fputs(comp_cls_str, stderr); - break; - case BT_ERROR_CAUSE_ACTOR_TYPE_MESSAGE_ITERATOR: - comp_cls_str = format_plugin_comp_cls_opt( - 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) - ,BT_COMMON_COLOR_WHEN_AUTO); - BT_ASSERT(comp_cls_str); - - fprintf(stderr, "%s%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(), - comp_cls_str); - break; - default: - bt_common_abort(); - } + fputc('\n', stderr); - /* Print file name and line number */ - fprintf(stderr, "] (%s%s%s%s:%s%" PRIu64 "%s)\n", - bt_common_color_bold(), - bt_common_color_fg_bright_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; - } + error_str = format_bt_error(error, columns, bt_cli_log_level, + BT_COMMON_COLOR_WHEN_AUTO); + BT_ASSERT(error_str); - fprintf(stderr, "%s\n", folded->str); - g_string_free(folded, TRUE); - folded = NULL; - } + fprintf(stderr, "%s\n", error_str); end: - BT_ASSERT(!folded); - if (error) { bt_error_release(error); } - g_free(comp_cls_str); + g_free(error_str); } int main(int argc, const char **argv) diff --git a/src/string-format/Makefile.am b/src/string-format/Makefile.am index 9041cf88..f73993a0 100644 --- a/src/string-format/Makefile.am +++ b/src/string-format/Makefile.am @@ -2,4 +2,6 @@ noinst_LTLIBRARIES = libbabeltrace2-string-format.la libbabeltrace2_string_format_la_SOURCES = \ format-plugin-comp-cls-name.c \ - format-plugin-comp-cls-name.h + format-plugin-comp-cls-name.h \ + format-error.c \ + format-error.h diff --git a/src/string-format/format-error.c b/src/string-format/format-error.c new file mode 100644 index 00000000..4a2f8bf7 --- /dev/null +++ b/src/string-format/format-error.c @@ -0,0 +1,155 @@ +/* + * Copyright EfficiOS, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#define BT_LOG_OUTPUT_LEVEL log_level +#define BT_LOG_TAG "COMMON/FORMAT-ERROR" +#include + +#include "format-error.h" + +#include +#include + +gchar *format_bt_error( + const bt_error *error, + unsigned int columns, + bt_logging_level log_level, + enum bt_common_color_when use_colors) +{ + GString *str; + int64_t i; + GString *folded = NULL; + gchar *comp_cls_str = NULL; + struct bt_common_color_codes codes; + + BT_ASSERT(error); + BT_ASSERT(bt_error_get_cause_count(error) > 0); + + str = g_string_new(NULL); + BT_ASSERT(str); + + bt_common_color_get_codes(&codes, use_colors); + + /* 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 */ + g_string_append_printf(str, prefix_fmt, + codes.bold, codes.fg_bright_red, codes.reset); + + /* Print actor name */ + g_string_append_c(str, '['); + switch (bt_error_cause_get_actor_type(cause)) { + case BT_ERROR_CAUSE_ACTOR_TYPE_UNKNOWN: + g_string_append_printf(str, "%s%s%s", + codes.bold, + bt_error_cause_get_module_name(cause), + codes.reset); + break; + case BT_ERROR_CAUSE_ACTOR_TYPE_COMPONENT: + comp_cls_str = format_plugin_comp_cls_opt( + 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), + use_colors); + BT_ASSERT(comp_cls_str); + + g_string_append_printf(str, "%s%s%s: %s", + codes.bold, + bt_error_cause_component_actor_get_component_name(cause), + codes.reset, + comp_cls_str); + + break; + case BT_ERROR_CAUSE_ACTOR_TYPE_COMPONENT_CLASS: + comp_cls_str = format_plugin_comp_cls_opt( + 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), + use_colors); + BT_ASSERT(comp_cls_str); + + g_string_append(str, comp_cls_str); + break; + case BT_ERROR_CAUSE_ACTOR_TYPE_MESSAGE_ITERATOR: + comp_cls_str = format_plugin_comp_cls_opt( + 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), + use_colors); + BT_ASSERT(comp_cls_str); + + g_string_append_printf(str, "%s%s%s (%s%s%s): %s", + codes.bold, + bt_error_cause_message_iterator_actor_get_component_name(cause), + codes.reset, + codes.bold, + bt_error_cause_message_iterator_actor_get_component_output_port_name(cause), + codes.reset, + comp_cls_str); + + break; + default: + bt_common_abort(); + } + + /* Print file name and line number */ + g_string_append_printf(str, "] (%s%s%s%s:%s%" PRIu64 "%s)\n", + codes.bold, + codes.fg_bright_magenta, + bt_error_cause_get_file_name(cause), + codes.reset, + codes.fg_green, + bt_error_cause_get_line_number(cause), + codes.reset); + + /* Print message */ + folded = bt_common_fold(bt_error_cause_get_message(cause), + columns, 2); + if (folded) { + g_string_append(str, folded->str); + g_string_free(folded, TRUE); + folded = NULL; + } else { + BT_LOGE_STR("Could not fold string."); + g_string_append(str, bt_error_cause_get_message(cause)); + } + + /* + * Don't append a newline at the end, since that is used to + * generate the Python __str__, which doesn't need a newline + * at the end. + */ + if (i > 0) { + g_string_append_c(str, '\n'); + } + } + + g_free(comp_cls_str); + + return g_string_free(str, FALSE); +} diff --git a/src/string-format/format-error.h b/src/string-format/format-error.h new file mode 100644 index 00000000..3fbef7aa --- /dev/null +++ b/src/string-format/format-error.h @@ -0,0 +1,38 @@ +#ifndef _BABELTRACE_STRING_FORMAT_FORMAT_ERROR_H +#define _BABELTRACE_STRING_FORMAT_FORMAT_ERROR_H + +/* + * Copyright EfficiOS, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include + +BT_HIDDEN +gchar *format_bt_error( + const bt_error *error, + unsigned int columns, + bt_logging_level log_level, + enum bt_common_color_when use_colors); + +#endif /* _BABELTRACE_STRING_FORMAT_FORMAT_ERROR_H */ -- 2.34.1