From: Philippe Proulx Date: Wed, 14 Jun 2017 05:17:23 +0000 (-0400) Subject: cli: add global --log-level option X-Git-Url: http://git.efficios.com/?a=commitdiff_plain;h=3efa30527e93de6e2374c47ed9dfb633508e123b;p=babeltrace.git cli: add global --log-level option This new global option (applies before the command name) sets the default log level of all the known (project's) loggers. This default log level can still be overridden by a specific environment variable, for example: BABELTRACE_PLUGIN_CTF_METADATA_LOG_LEVEL=D babeltrace --log-level=I ... In this example, all the log levels are set to INFO, but BABELTRACE_PLUGIN_CTF_METADATA_LOG_LEVEL overrides the `ctf` plugin's metadata module's log level to DEBUG. When you don't specify --log-level, it defaults to W (WARN), the current behaviour. --verbose is now the equivalent of --log-level=I, and --debug is the equivalent of --log-level=V. --verbose and --debug do the same thing, for the `convert` command, whether they are global or specific to the command. --verbose and --debug can still be specified together, and whatever the order, the lowest log level always wins: VERBOSE. The --log-level option can override previous --verbose, --debug, or --log-level options because it didn't exist in Babeltrace 1 anyway so there's no way to break backward compatibility: babeltrace --log-level=W --verbose --log-level=E ... In this case, the final log level is ERROR. Other example with implicit `convert` command: babeltrace --log-level=E /path/to/trace -v In this case, the command's --verbose option sets the log level to INFO because it's lower than ERROR (set by --log-level=E). One of the main use cases of the new --log-level option is to completely disable logging: babeltrace --log-level=N ... Signed-off-by: Philippe Proulx Signed-off-by: Jérémie Galarneau --- diff --git a/cli/babeltrace-cfg-cli-args.c b/cli/babeltrace-cfg-cli-args.c index e2608748..394e9e65 100644 --- a/cli/babeltrace-cfg-cli-args.c +++ b/cli/babeltrace-cfg-cli-args.c @@ -1775,7 +1775,7 @@ void print_help_usage(FILE *fp) fprintf(fp, " --omit-system-plugin-path Omit system plugins from plugin search path\n"); fprintf(fp, " --plugin-path=PATH[:PATH]... Add PATH to the list of paths from which\n"); fprintf(fp, " dynamic plugins can be loaded\n"); - fprintf(fp, " -h --help Show this help and quit\n"); + fprintf(fp, " -h, --help Show this help and quit\n"); fprintf(fp, "\n"); fprintf(fp, "See `babeltrace --help` for the list of general options.\n"); fprintf(fp, "\n"); @@ -1964,7 +1964,7 @@ void print_query_usage(FILE *fp) fprintf(fp, " (see the expected format of PARAMS below)\n"); fprintf(fp, " --plugin-path=PATH[:PATH]... Add PATH to the list of paths from which\n"); fprintf(fp, " dynamic plugins can be loaded\n"); - fprintf(fp, " -h --help Show this help and quit\n"); + fprintf(fp, " -h, --help Show this help and quit\n"); fprintf(fp, "\n\n"); print_expected_params_format(fp); } @@ -2160,7 +2160,7 @@ void print_list_plugins_usage(FILE *fp) fprintf(fp, " --omit-system-plugin-path Omit system plugins from plugin search path\n"); fprintf(fp, " --plugin-path=PATH[:PATH]... Add PATH to the list of paths from which\n"); fprintf(fp, " dynamic plugins can be loaded\n"); - fprintf(fp, " -h --help Show this help and quit\n"); + fprintf(fp, " -h, --help Show this help and quit\n"); fprintf(fp, "\n"); fprintf(fp, "See `babeltrace --help` for the list of general options.\n"); fprintf(fp, "\n"); @@ -2326,7 +2326,7 @@ void print_run_usage(FILE *fp) fprintf(fp, " the current component with a name given by\n"); fprintf(fp, " the last argument of the --key option and a\n"); fprintf(fp, " value set to VAL\n"); - fprintf(fp, " -h --help Show this help and quit\n"); + fprintf(fp, " -h, --help Show this help and quit\n"); fprintf(fp, "\n"); fprintf(fp, "See `babeltrace --help` for the list of general options.\n"); fprintf(fp, "\n\n"); @@ -2793,7 +2793,7 @@ void print_convert_usage(FILE *fp) fprintf(fp, " formatted for `xargs -0`, and quit\n"); fprintf(fp, " -u, --url=URL Set the `url` string parameter of the\n"); fprintf(fp, " current component to URL\n"); - fprintf(fp, " -h --help Show this help and quit\n"); + fprintf(fp, " -h, --help Show this help and quit\n"); fprintf(fp, "\n"); fprintf(fp, "Implicit `source.ctf.fs` component options:\n"); fprintf(fp, "\n"); @@ -3584,7 +3584,7 @@ static struct bt_config *bt_config_convert_from_args(int argc, const char *argv[], int *retcode, bool force_omit_system_plugin_path, bool force_omit_home_plugin_path, bool force_no_debug_info, - struct bt_value *initial_plugin_paths) + struct bt_value *initial_plugin_paths, char *log_level) { poptContext pc = NULL; char *arg = NULL; @@ -3592,8 +3592,6 @@ struct bt_config *bt_config_convert_from_args(int argc, const char *argv[], BT_CONFIG_COMPONENT_DEST_UNKNOWN; int opt, ret = 0; struct bt_config *cfg = NULL; - bool got_verbose_opt = false; - bool got_debug_opt = false; bool got_input_format_opt = false; bool got_output_format_opt = false; bool trimmer_has_begin = false; @@ -4273,18 +4271,12 @@ struct bt_config *bt_config_convert_from_args(int argc, const char *argv[], base_implicit_ctf_input_args.exists = true; break; case OPT_VERBOSE: - if (got_verbose_opt) { - printf_err("Duplicate -v/--verbose option\n"); - goto error; + if (*log_level != 'V' && *log_level != 'D') { + *log_level = 'I'; } - - append_implicit_component_param(&implicit_text_args, - "verbose", "yes"); - implicit_text_args.exists = true; - got_verbose_opt = true; break; case OPT_DEBUG: - got_debug_opt = true; + *log_level = 'V'; break; } @@ -4299,6 +4291,16 @@ struct bt_config *bt_config_convert_from_args(int argc, const char *argv[], goto error; } + /* + * Legacy behaviour: --verbose used to make the `text` output + * format print more information. --verbose is now equivalent to + * the INFO log level, which is why we compare to 'I' here. + */ + if (*log_level == 'I') { + append_implicit_component_param(&implicit_text_args, + "verbose", "yes"); + } + /* * Append home and system plugin paths now that we possibly got * --plugin-path. @@ -4345,8 +4347,6 @@ struct bt_config *bt_config_convert_from_args(int argc, const char *argv[], goto error; } - cfg->debug = got_debug_opt; - cfg->verbose = got_verbose_opt; gs_leftover = leftovers->data; g_string_assign(cfg->cmd_data.print_ctf_metadata.path, gs_leftover->str); @@ -4435,8 +4435,6 @@ struct bt_config *bt_config_convert_from_args(int argc, const char *argv[], goto error; } - cfg->debug = got_debug_opt; - cfg->verbose = got_verbose_opt; g_string_assign(cfg->cmd_data.print_lttng_live_sessions.url, gs_leftover->str); goto end; @@ -4706,8 +4704,6 @@ struct bt_config *bt_config_convert_from_args(int argc, const char *argv[], goto error; } - cfg->debug = got_debug_opt; - cfg->verbose = got_verbose_opt; goto end; error: @@ -4763,10 +4759,12 @@ void print_gen_usage(FILE *fp) fprintf(fp, "\n"); fprintf(fp, "General options:\n"); fprintf(fp, "\n"); - fprintf(fp, " -d, --debug Turn on debug mode\n"); - fprintf(fp, " -h --help Show this help and quit\n"); - fprintf(fp, " -v, --verbose Turn on verbose mode\n"); - fprintf(fp, " -V, --version Show version and quit\n"); + fprintf(fp, " -d, --debug Enable debug mode (same as --log-level=V)\n"); + fprintf(fp, " -h, --help Show this help and quit\n"); + fprintf(fp, " --log-level=LVL Set all log levels to LVL (`N`, `V`, `D`,\n"); + fprintf(fp, " `I`, `W` (default), `E`, or `F`)\n"); + fprintf(fp, " -v, --verbose Enable verbose mode (same as --log-level=I)\n"); + fprintf(fp, " -V, --version Show version and quit\n"); fprintf(fp, "\n"); fprintf(fp, "Available commands:\n"); fprintf(fp, "\n"); @@ -4779,18 +4777,49 @@ void print_gen_usage(FILE *fp) fprintf(fp, "Use `babeltrace COMMAND --help` to show the help of COMMAND.\n"); } +static +char log_level_from_arg(const char *arg) +{ + char level = 'U'; + + if (strcmp(arg, "VERBOSE") == 0 || + strcmp(arg, "V") == 0) { + level = 'V'; + } else if (strcmp(arg, "DEBUG") == 0 || + strcmp(arg, "D") == 0) { + level = 'D'; + } else if (strcmp(arg, "INFO") == 0 || + strcmp(arg, "I") == 0) { + level = 'I'; + } else if (strcmp(arg, "WARN") == 0 || + strcmp(arg, "WARNING") == 0 || + strcmp(arg, "W") == 0) { + level = 'W'; + } else if (strcmp(arg, "ERROR") == 0 || + strcmp(arg, "E") == 0) { + level = 'E'; + } else if (strcmp(arg, "FATAL") == 0 || + strcmp(arg, "F") == 0) { + level = 'F'; + } else if (strcmp(arg, "NONE") == 0 || + strcmp(arg, "N") == 0) { + level = 'N'; + } + + return level; +} + struct bt_config *bt_config_cli_args_create(int argc, const char *argv[], int *retcode, bool force_omit_system_plugin_path, bool force_omit_home_plugin_path, bool force_no_debug_info, struct bt_value *initial_plugin_paths) { struct bt_config *config = NULL; - bool verbose = false; - bool debug = false; int i; const char **command_argv = NULL; int command_argc = -1; const char *command_name = NULL; + char log_level = 'U'; enum command_type { COMMAND_TYPE_NONE = -1, @@ -4820,13 +4849,49 @@ struct bt_config *bt_config_cli_args_create(int argc, const char *argv[], for (i = 1; i < argc; i++) { const char *cur_arg = argv[i]; + const char *next_arg = i == (argc - 1) ? NULL : argv[i + 1]; if (strcmp(cur_arg, "-d") == 0 || strcmp(cur_arg, "--debug") == 0) { - debug = true; + log_level = 'V'; } else if (strcmp(cur_arg, "-v") == 0 || strcmp(cur_arg, "--verbose") == 0) { - verbose = true; + if (log_level != 'V' && log_level != 'D') { + /* + * Legacy: do not override a previous + * --debug because --verbose and --debug + * can be specified together (in this + * case we want the lowest log level to + * apply, VERBOSE). + */ + log_level = 'I'; + } + } else if (strcmp(cur_arg, "--log-level") == 0) { + if (!next_arg) { + printf_err("Missing log level value for --log-level option\n"); + *retcode = 1; + goto end; + } + + log_level = log_level_from_arg(next_arg); + if (log_level == 'U') { + printf_err("Invalid argument for --log-level option:\n %s\n", + next_arg); + *retcode = 1; + goto end; + } + + i++; + } else if (strncmp(cur_arg, "--log-level=", 12) == 0) { + const char *arg = &cur_arg[12]; + + log_level = log_level_from_arg(arg); + if (log_level == 'U') { + printf_err("Invalid argument for --log-level option:\n %s\n", + arg); + *retcode = 1; + goto end; + } } else if (strcmp(cur_arg, "-V") == 0 || strcmp(cur_arg, "--version") == 0) { print_version(); @@ -4836,12 +4901,13 @@ struct bt_config *bt_config_cli_args_create(int argc, const char *argv[], print_gen_usage(stdout); goto end; } else { - bool has_command = true; - /* * First unknown argument: is it a known command * name? */ + command_argv = &argv[i]; + command_argc = argc - i; + if (strcmp(cur_arg, "convert") == 0) { command_type = COMMAND_TYPE_CONVERT; } else if (strcmp(cur_arg, "list-plugins") == 0) { @@ -4855,20 +4921,13 @@ struct bt_config *bt_config_cli_args_create(int argc, const char *argv[], } else { /* * Unknown argument, but not a known - * command name: assume the whole - * arguments are for the default convert - * command. + * command name: assume the default + * `convert` command. */ command_type = COMMAND_TYPE_CONVERT; - command_argv = argv; - command_argc = argc; - has_command = false; - } - - if (has_command) { - command_argv = &argv[i]; - command_argc = argc - i; - command_name = cur_arg; + command_name = "convert"; + command_argv = &argv[i - 1]; + command_argc = argc - i + 1; } break; } @@ -4898,7 +4957,7 @@ struct bt_config *bt_config_cli_args_create(int argc, const char *argv[], config = bt_config_convert_from_args(command_argc, command_argv, retcode, force_omit_system_plugin_path, force_omit_home_plugin_path, force_no_debug_info, - initial_plugin_paths); + initial_plugin_paths, &log_level); break; case COMMAND_TYPE_LIST_PLUGINS: config = bt_config_list_plugins_from_args(command_argc, @@ -4920,14 +4979,11 @@ struct bt_config *bt_config_cli_args_create(int argc, const char *argv[], } if (config) { - if (verbose) { - config->verbose = true; - } - - if (debug) { - config->debug = true; + if (log_level == 'U') { + log_level = 'W'; } + config->log_level = log_level; config->command_name = command_name; } diff --git a/cli/babeltrace-cfg.h b/cli/babeltrace-cfg.h index 87231295..b9a4b5ed 100644 --- a/cli/babeltrace-cfg.h +++ b/cli/babeltrace-cfg.h @@ -70,6 +70,7 @@ struct bt_config { bool omit_home_plugin_path; bool command_needs_plugins; const char *command_name; + char log_level; enum bt_config_command command; union { /* BT_CONFIG_COMMAND_RUN */ diff --git a/cli/babeltrace.c b/cli/babeltrace.c index d7eeec61..668491e7 100644 --- a/cli/babeltrace.c +++ b/cli/babeltrace.c @@ -1938,7 +1938,31 @@ void set_auto_log_levels(struct bt_config *cfg) * Set library's default log level if not * explicitly specified. */ - bt_logging_set_global_level(BT_LOGGING_LEVEL_WARN); + switch (cfg->log_level) { + case 'N': + bt_logging_set_global_level(BT_LOGGING_LEVEL_NONE); + break; + case 'V': + bt_logging_set_global_level(BT_LOGGING_LEVEL_VERBOSE); + break; + case 'D': + bt_logging_set_global_level(BT_LOGGING_LEVEL_DEBUG); + break; + case 'I': + bt_logging_set_global_level(BT_LOGGING_LEVEL_INFO); + break; + case 'W': + bt_logging_set_global_level(BT_LOGGING_LEVEL_WARN); + break; + case 'E': + bt_logging_set_global_level(BT_LOGGING_LEVEL_ERROR); + break; + case 'F': + bt_logging_set_global_level(BT_LOGGING_LEVEL_FATAL); + break; + default: + abort(); + } } } @@ -1952,7 +1976,31 @@ void set_auto_log_levels(struct bt_config *cfg) * Set CLI's default log level if not explicitly * specified. */ - bt_cli_log_level = BT_LOG_WARN; + switch (cfg->log_level) { + case 'N': + bt_cli_log_level = BT_LOG_NONE; + break; + case 'V': + bt_cli_log_level = BT_LOG_VERBOSE; + break; + case 'D': + bt_cli_log_level = BT_LOG_DEBUG; + break; + case 'I': + bt_cli_log_level = BT_LOG_INFO; + break; + case 'W': + bt_cli_log_level = BT_LOG_WARN; + break; + case 'E': + bt_cli_log_level = BT_LOG_ERROR; + break; + case 'F': + bt_cli_log_level = BT_LOG_FATAL; + break; + default: + abort(); + } } } @@ -1965,11 +2013,14 @@ void set_auto_log_levels(struct bt_config *cfg) } else if (cfg->debug) { setenv(*env_var_name, "V", 1); } else { + char val[2] = { 0 }; + /* * Set module's default log level if not * explicitly specified. */ - setenv(*env_var_name, "W", 1); + val[0] = cfg->log_level; + setenv(*env_var_name, val, 1); } }