X-Git-Url: https://git.lttng.org/?p=lttng-tools.git;a=blobdiff_plain;f=src%2Fbin%2Flttng%2Fcommands%2Flist_triggers.c;h=59db1c5d4b8b499fbd81a5fe10c9ccf9c374da7b;hp=e10fc29f1fe2903dfc81aee455037b7717d40352;hb=523c4f8cdeb927b789710e3dafcb3f249751ccfd;hpb=46fd07accf36998fca3e43e54513755a98f68f48 diff --git a/src/bin/lttng/commands/list_triggers.c b/src/bin/lttng/commands/list_triggers.c index e10fc29f1..59db1c5d4 100644 --- a/src/bin/lttng/commands/list_triggers.c +++ b/src/bin/lttng/commands/list_triggers.c @@ -29,6 +29,16 @@ static const char help_msg[] = ; #endif +#define INDENTATION_LEVEL_STR " " + +typedef enum lttng_event_rule_status (*event_rule_logging_get_name_pattern)( + const struct lttng_event_rule *rule, const char **pattern); +typedef enum lttng_event_rule_status (*event_rule_logging_get_filter)( + const struct lttng_event_rule *rule, const char **expression); +typedef enum lttng_event_rule_status (*event_rule_logging_get_log_level_rule)( + const struct lttng_event_rule *rule, + const struct lttng_log_level_rule **log_level_rule); + enum { OPT_HELP, OPT_LIST_OPTIONS, @@ -118,26 +128,26 @@ static void print_condition_session_rotation( /* * Returns the human-readable log level name associated with a numerical value - * if there is one. The Log4j and JUL domains have discontinuous log level + * if there is one. The Log4j and JUL event rule have discontinuous log level * values (a value can fall between two labels). In those cases, NULL is * returned. */ static const char *get_pretty_loglevel_name( - enum lttng_domain_type domain, int loglevel) + enum lttng_event_rule_type event_rule_type, int loglevel) { const char *name = NULL; - switch (domain) { - case LTTNG_DOMAIN_UST: + switch (event_rule_type) { + case LTTNG_EVENT_RULE_TYPE_USER_TRACEPOINT: name = loglevel_value_to_name(loglevel); break; - case LTTNG_DOMAIN_LOG4J: + case LTTNG_EVENT_RULE_TYPE_LOG4J_LOGGING: name = loglevel_log4j_value_to_name(loglevel); break; - case LTTNG_DOMAIN_JUL: + case LTTNG_EVENT_RULE_TYPE_JUL_LOGGING: name = loglevel_jul_value_to_name(loglevel); break; - case LTTNG_DOMAIN_PYTHON: + case LTTNG_EVENT_RULE_TYPE_PYTHON_LOGGING: name = loglevel_python_value_to_name(loglevel); break; default: @@ -148,10 +158,9 @@ static const char *get_pretty_loglevel_name( } static -void print_event_rule_tracepoint(const struct lttng_event_rule *event_rule) +void print_event_rule_user_tracepoint(const struct lttng_event_rule *event_rule) { enum lttng_event_rule_status event_rule_status; - enum lttng_domain_type domain_type; const char *pattern; const char *filter; int log_level; @@ -159,18 +168,13 @@ void print_event_rule_tracepoint(const struct lttng_event_rule *event_rule) unsigned int exclusions_count; int i; - event_rule_status = lttng_event_rule_tracepoint_get_name_pattern( + event_rule_status = lttng_event_rule_user_tracepoint_get_name_pattern( event_rule, &pattern); assert(event_rule_status == LTTNG_EVENT_RULE_STATUS_OK); - event_rule_status = lttng_event_rule_tracepoint_get_domain_type( - event_rule, &domain_type); - assert(event_rule_status == LTTNG_EVENT_RULE_STATUS_OK); - - _MSG(" rule: %s (type: tracepoint, domain: %s", pattern, - lttng_domain_type_str(domain_type)); + _MSG(" rule: %s (type: user tracepoint", pattern); - event_rule_status = lttng_event_rule_tracepoint_get_filter( + event_rule_status = lttng_event_rule_user_tracepoint_get_filter( event_rule, &filter); if (event_rule_status == LTTNG_EVENT_RULE_STATUS_OK) { _MSG(", filter: %s", filter); @@ -178,7 +182,7 @@ void print_event_rule_tracepoint(const struct lttng_event_rule *event_rule) assert(event_rule_status == LTTNG_EVENT_RULE_STATUS_UNSET); } - event_rule_status = lttng_event_rule_tracepoint_get_log_level_rule( + event_rule_status = lttng_event_rule_user_tracepoint_get_log_level_rule( event_rule, &log_level_rule); if (event_rule_status == LTTNG_EVENT_RULE_STATUS_OK) { enum lttng_log_level_rule_status llr_status; @@ -203,7 +207,7 @@ void print_event_rule_tracepoint(const struct lttng_event_rule *event_rule) assert(llr_status == LTTNG_LOG_LEVEL_RULE_STATUS_OK); pretty_loglevel_name = get_pretty_loglevel_name( - domain_type, log_level); + LTTNG_EVENT_RULE_TYPE_USER_TRACEPOINT, log_level); if (pretty_loglevel_name) { _MSG(", log level %s %s", log_level_op, pretty_loglevel_name); @@ -214,7 +218,7 @@ void print_event_rule_tracepoint(const struct lttng_event_rule *event_rule) assert(event_rule_status == LTTNG_EVENT_RULE_STATUS_UNSET); } - event_rule_status = lttng_event_rule_tracepoint_get_name_pattern_exclusion_count( + event_rule_status = lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_count( event_rule, &exclusions_count); assert(event_rule_status == LTTNG_EVENT_RULE_STATUS_OK); if (exclusions_count > 0) { @@ -222,7 +226,7 @@ void print_event_rule_tracepoint(const struct lttng_event_rule *event_rule) for (i = 0; i < exclusions_count; i++) { const char *exclusion; - event_rule_status = lttng_event_rule_tracepoint_get_name_pattern_exclusion_at_index( + event_rule_status = lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_at_index( event_rule, i, &exclusion); assert(event_rule_status == LTTNG_EVENT_RULE_STATUS_OK); @@ -233,6 +237,128 @@ void print_event_rule_tracepoint(const struct lttng_event_rule *event_rule) MSG(")"); } +static +void print_event_rule_kernel_tracepoint(const struct lttng_event_rule *event_rule) +{ + enum lttng_event_rule_status event_rule_status; + const char *pattern; + const char *filter; + + event_rule_status = lttng_event_rule_kernel_tracepoint_get_name_pattern( + event_rule, &pattern); + assert(event_rule_status == LTTNG_EVENT_RULE_STATUS_OK); + + _MSG(" rule: %s (type: kernel tracepoint", pattern); + + event_rule_status = lttng_event_rule_kernel_tracepoint_get_filter( + event_rule, &filter); + if (event_rule_status == LTTNG_EVENT_RULE_STATUS_OK) { + _MSG(", filter: %s", filter); + } else { + assert(event_rule_status == LTTNG_EVENT_RULE_STATUS_UNSET); + } + + MSG(")"); +} + +static +void print_event_rule_logging(const struct lttng_event_rule *event_rule) +{ + enum lttng_event_rule_status event_rule_status; + enum lttng_event_rule_type event_rule_type = lttng_event_rule_get_type(event_rule); + const char *pattern; + const char *filter; + int log_level; + const struct lttng_log_level_rule *log_level_rule = NULL; + const char *type_str = NULL; + + event_rule_logging_get_name_pattern logging_get_name_pattern; + event_rule_logging_get_filter logging_get_filter; + event_rule_logging_get_log_level_rule logging_get_log_level_rule; + + switch (event_rule_type) { + case LTTNG_EVENT_RULE_TYPE_JUL_LOGGING: + logging_get_name_pattern = + lttng_event_rule_jul_logging_get_name_pattern; + logging_get_filter = lttng_event_rule_jul_logging_get_filter; + logging_get_log_level_rule = + lttng_event_rule_jul_logging_get_log_level_rule; + type_str = "jul"; + break; + case LTTNG_EVENT_RULE_TYPE_LOG4J_LOGGING: + logging_get_name_pattern = + lttng_event_rule_log4j_logging_get_name_pattern; + logging_get_filter = lttng_event_rule_log4j_logging_get_filter; + logging_get_log_level_rule = + lttng_event_rule_log4j_logging_get_log_level_rule; + type_str = "log4j"; + break; + case LTTNG_EVENT_RULE_TYPE_PYTHON_LOGGING: + logging_get_name_pattern = + lttng_event_rule_python_logging_get_name_pattern; + logging_get_filter = lttng_event_rule_python_logging_get_filter; + logging_get_log_level_rule = + lttng_event_rule_python_logging_get_log_level_rule; + type_str = "python"; + break; + default: + abort(); + break; + } + + event_rule_status = logging_get_name_pattern( + event_rule, &pattern); + assert(event_rule_status == LTTNG_EVENT_RULE_STATUS_OK); + + _MSG(" rule: %s (type: %s:logging", pattern, type_str); + + event_rule_status = logging_get_filter( + event_rule, &filter); + if (event_rule_status == LTTNG_EVENT_RULE_STATUS_OK) { + _MSG(", filter: %s", filter); + } else { + assert(event_rule_status == LTTNG_EVENT_RULE_STATUS_UNSET); + } + + event_rule_status = logging_get_log_level_rule( + event_rule, &log_level_rule); + if (event_rule_status == LTTNG_EVENT_RULE_STATUS_OK) { + enum lttng_log_level_rule_status llr_status; + const char *log_level_op; + const char *pretty_loglevel_name; + + switch (lttng_log_level_rule_get_type(log_level_rule)) { + case LTTNG_LOG_LEVEL_RULE_TYPE_EXACTLY: + log_level_op = "is"; + llr_status = lttng_log_level_rule_exactly_get_level( + log_level_rule, &log_level); + break; + case LTTNG_LOG_LEVEL_RULE_TYPE_AT_LEAST_AS_SEVERE_AS: + log_level_op = "at least"; + llr_status = lttng_log_level_rule_at_least_as_severe_as_get_level( + log_level_rule, &log_level); + break; + default: + abort(); + } + + assert(llr_status == LTTNG_LOG_LEVEL_RULE_STATUS_OK); + + pretty_loglevel_name = get_pretty_loglevel_name( + event_rule_type, log_level); + if (pretty_loglevel_name) { + _MSG(", log level %s %s", log_level_op, + pretty_loglevel_name); + } else { + _MSG(", log level %s %d", log_level_op, log_level); + } + } else { + assert(event_rule_status == LTTNG_EVENT_RULE_STATUS_UNSET); + } + + MSG(")"); +} + static void print_kernel_probe_location( const struct lttng_kernel_probe_location *location) { @@ -294,22 +420,22 @@ void print_event_rule_kernel_probe(const struct lttng_event_rule *event_rule) const char *name; const struct lttng_kernel_probe_location *location; - assert(lttng_event_rule_get_type(event_rule) == LTTNG_EVENT_RULE_TYPE_KERNEL_PROBE); + assert(lttng_event_rule_get_type(event_rule) == LTTNG_EVENT_RULE_TYPE_KERNEL_KPROBE); - event_rule_status = lttng_event_rule_kernel_probe_get_event_name(event_rule, &name); + event_rule_status = lttng_event_rule_kernel_kprobe_get_event_name(event_rule, &name); if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) { ERR("Failed to get kprobe event rule's name."); goto end; } - event_rule_status = lttng_event_rule_kernel_probe_get_location( + event_rule_status = lttng_event_rule_kernel_kprobe_get_location( event_rule, &location); if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) { ERR("Failed to get kprobe event rule's location."); goto end; } - _MSG(" rule: %s (type: probe, location: ", name); + _MSG(" rule: %s (type: kernel:kprobe, location: ", name); print_kernel_probe_location(location); @@ -422,10 +548,18 @@ void print_event_rule(const struct lttng_event_rule *event_rule) lttng_event_rule_get_type(event_rule); switch (event_rule_type) { - case LTTNG_EVENT_RULE_TYPE_TRACEPOINT: - print_event_rule_tracepoint(event_rule); + case LTTNG_EVENT_RULE_TYPE_USER_TRACEPOINT: + print_event_rule_user_tracepoint(event_rule); break; - case LTTNG_EVENT_RULE_TYPE_KERNEL_PROBE: + case LTTNG_EVENT_RULE_TYPE_KERNEL_TRACEPOINT: + print_event_rule_kernel_tracepoint(event_rule); + break; + case LTTNG_EVENT_RULE_TYPE_JUL_LOGGING: + case LTTNG_EVENT_RULE_TYPE_LOG4J_LOGGING: + case LTTNG_EVENT_RULE_TYPE_PYTHON_LOGGING: + print_event_rule_logging(event_rule); + break; + case LTTNG_EVENT_RULE_TYPE_KERNEL_KPROBE: print_event_rule_kernel_probe(event_rule); break; case LTTNG_EVENT_RULE_TYPE_KERNEL_UPROBE: @@ -506,6 +640,79 @@ void print_one_event_expr(const struct lttng_event_expr *event_expr) } } +static +void print_indentation(unsigned int indentation_level) +{ + unsigned int i; + + for (i = 0; i < indentation_level; i++) { + _MSG(INDENTATION_LEVEL_STR); + } +} + +static +void print_error_query_results(struct lttng_error_query_results *results, + unsigned int base_indentation_level) +{ + unsigned int i, count, printed_errors_count = 0; + enum lttng_error_query_results_status results_status; + + results_status = lttng_error_query_results_get_count(results, &count); + assert(results_status == LTTNG_ERROR_QUERY_RESULTS_STATUS_OK); + + assert(results); + + print_indentation(base_indentation_level); + _MSG("errors:"); + + for (i = 0; i < count; i++) { + const struct lttng_error_query_result *result; + enum lttng_error_query_result_status result_status; + const char *result_name; + const char *result_description; + uint64_t result_value; + + results_status = lttng_error_query_results_get_result( + results, &result, i); + assert(results_status == LTTNG_ERROR_QUERY_RESULTS_STATUS_OK); + + result_status = lttng_error_query_result_get_name( + result, &result_name); + assert(result_status == LTTNG_ERROR_QUERY_RESULT_STATUS_OK); + result_status = lttng_error_query_result_get_description( + result, &result_description); + assert(result_status == LTTNG_ERROR_QUERY_RESULT_STATUS_OK); + + + if (lttng_error_query_result_get_type(result) == + LTTNG_ERROR_QUERY_RESULT_TYPE_COUNTER) { + result_status = lttng_error_query_result_counter_get_value( + result, &result_value); + assert(result_status == + LTTNG_ERROR_QUERY_RESULT_STATUS_OK); + if (result_value == 0) { + continue; + } + + MSG(""); + print_indentation(base_indentation_level + 1); + + _MSG("%s: %" PRIu64, result_name, result_value); + printed_errors_count++; + } else { + MSG(""); + print_indentation(base_indentation_level + 1); + _MSG("Unknown error query result type for result '%s' (%s)", + result_name, result_description); + continue; + } + } + + if (printed_errors_count == 0) { + _MSG(" none"); + } +} + static void print_condition_event_rule_matches( const struct lttng_condition *condition) { @@ -544,9 +751,7 @@ static void print_action_errors(const struct lttng_trigger *trigger, const uint64_t *action_path_indexes, size_t action_path_length) { - unsigned int i, count, printed_errors_count = 0; enum lttng_error_code error_query_ret; - enum lttng_error_query_results_status results_status; struct lttng_error_query_results *results = NULL; const char *trigger_name; uid_t trigger_uid; @@ -578,53 +783,7 @@ static void print_action_errors(const struct lttng_trigger *trigger, goto end; } - results_status = lttng_error_query_results_get_count(results, &count); - assert(results_status == LTTNG_ERROR_QUERY_RESULTS_STATUS_OK); - - _MSG(" errors:"); - - for (i = 0; i < count; i++) { - const struct lttng_error_query_result *result; - enum lttng_error_query_result_status result_status; - const char *result_name; - const char *result_description; - uint64_t result_value; - - results_status = lttng_error_query_results_get_result( - results, &result, i); - assert(results_status == LTTNG_ERROR_QUERY_RESULTS_STATUS_OK); - - result_status = lttng_error_query_result_get_name( - result, &result_name); - assert(result_status == LTTNG_ERROR_QUERY_RESULT_STATUS_OK); - result_status = lttng_error_query_result_get_description( - result, &result_description); - assert(result_status == LTTNG_ERROR_QUERY_RESULT_STATUS_OK); - - if (lttng_error_query_result_get_type(result) == - LTTNG_ERROR_QUERY_RESULT_TYPE_COUNTER) { - result_status = lttng_error_query_result_counter_get_value( - result, &result_value); - assert(result_status == - LTTNG_ERROR_QUERY_RESULT_STATUS_OK); - if (result_value == 0) { - continue; - } - - MSG(""); - _MSG(" %s: %" PRIu64, result_name, - result_value); - printed_errors_count++; - } else { - _MSG(" Unknown error query result type for result '%s' (%s)", - result_name, result_description); - continue; - } - } - - if (printed_errors_count == 0) { - _MSG(" none"); - } + print_error_query_results(results, 3); end: MSG(""); @@ -813,9 +972,7 @@ end: static void print_trigger_errors(const struct lttng_trigger *trigger) { - unsigned int i, count, printed_errors_count = 0; enum lttng_error_code error_query_ret; - enum lttng_error_query_results_status results_status; struct lttng_error_query_results *results = NULL; enum lttng_trigger_status trigger_status; const char *trigger_name; @@ -842,53 +999,45 @@ void print_trigger_errors(const struct lttng_trigger *trigger) goto end; } - results_status = lttng_error_query_results_get_count(results, &count); - assert(results_status == LTTNG_ERROR_QUERY_RESULTS_STATUS_OK); + print_error_query_results(results, 1); - _MSG(" errors:"); - - for (i = 0; i < count; i++) { - const struct lttng_error_query_result *result; - enum lttng_error_query_result_status result_status; - const char *result_name; - const char *result_description; - uint64_t result_value; +end: + MSG(""); + lttng_error_query_destroy(query); + lttng_error_query_results_destroy(results); +} - results_status = lttng_error_query_results_get_result( - results, &result, i); - assert(results_status == LTTNG_ERROR_QUERY_RESULTS_STATUS_OK); +static +void print_condition_errors(const struct lttng_trigger *trigger) +{ + enum lttng_error_code error_query_ret; + struct lttng_error_query_results *results = NULL; + enum lttng_trigger_status trigger_status; + const char *trigger_name; + uid_t trigger_uid; + struct lttng_error_query *query = + lttng_error_query_condition_create(trigger); - result_status = lttng_error_query_result_get_name( - result, &result_name); - assert(result_status == LTTNG_ERROR_QUERY_RESULT_STATUS_OK); - result_status = lttng_error_query_result_get_description( - result, &result_description); - assert(result_status == LTTNG_ERROR_QUERY_RESULT_STATUS_OK); + assert(query); + /* + * Anonymous triggers are not listed; this would be an internal error. + */ + trigger_status = lttng_trigger_get_name(trigger, &trigger_name); + assert(trigger_status == LTTNG_TRIGGER_STATUS_OK); - if (lttng_error_query_result_get_type(result) == - LTTNG_ERROR_QUERY_RESULT_TYPE_COUNTER) { - result_status = lttng_error_query_result_counter_get_value( - result, &result_value); - assert(result_status == - LTTNG_ERROR_QUERY_RESULT_STATUS_OK); - if (result_value == 0) { - continue; - } + trigger_status = lttng_trigger_get_owner_uid(trigger, &trigger_uid); + assert(trigger_status == LTTNG_TRIGGER_STATUS_OK); - MSG(""); - _MSG(" %s: %" PRIu64, result_name, - result_value); - printed_errors_count++; - } else { - _MSG(" Unknown error query result type for result '%s' (%s)", - result_name, result_description); - continue; - } + error_query_ret = lttng_error_query_execute( + query, lttng_session_daemon_command_endpoint, &results); + if (error_query_ret != LTTNG_OK) { + ERR("Failed to query errors of condition of trigger '%s' (owner uid: %d): %s", + trigger_name, (int) trigger_uid, + lttng_strerror(-error_query_ret)); + goto end; } - if (printed_errors_count == 0) { - _MSG(" none"); - } + print_error_query_results(results, 2); end: MSG(""); @@ -946,6 +1095,8 @@ void print_one_trigger(const struct lttng_trigger *trigger) abort(); } + print_condition_errors(trigger); + action = lttng_trigger_get_const_action(trigger); action_type = lttng_action_get_type(action); if (action_type == LTTNG_ACTION_TYPE_LIST) { @@ -995,11 +1146,9 @@ int compare_triggers_by_name(const void *a, const void *b) return strcmp(name_a, name_b); } -int cmd_list_triggers(int argc, const char **argv) +static int print_sorted_triggers(const struct lttng_triggers *triggers) { int ret; - struct argpar_parse_ret argpar_parse_ret = {}; - struct lttng_triggers *triggers = NULL; int i; struct lttng_dynamic_pointer_array sorted_triggers; enum lttng_trigger_status trigger_status; @@ -1007,6 +1156,166 @@ int cmd_list_triggers(int argc, const char **argv) lttng_dynamic_pointer_array_init(&sorted_triggers, NULL); + trigger_status = lttng_triggers_get_count(triggers, &num_triggers); + if (trigger_status != LTTNG_TRIGGER_STATUS_OK) { + ERR("Failed to get trigger count."); + goto error; + } + + for (i = 0; i < num_triggers; i++) { + int add_ret; + const char *unused_name; + const struct lttng_trigger *trigger = + lttng_triggers_get_at_index(triggers, i); + + trigger_status = lttng_trigger_get_name(trigger, &unused_name); + switch (trigger_status) { + case LTTNG_TRIGGER_STATUS_OK: + break; + case LTTNG_TRIGGER_STATUS_UNSET: + /* Don't list anonymous triggers. */ + continue; + default: + abort(); + } + + add_ret = lttng_dynamic_pointer_array_add_pointer( + &sorted_triggers, (void *) trigger); + if (add_ret) { + ERR("Failed to allocate array of struct lttng_trigger *."); + goto error; + } + } + + qsort(sorted_triggers.array.buffer.data, num_triggers, + sizeof(struct lttng_trigger *), + compare_triggers_by_name); + + for (i = 0; i < num_triggers; i++) { + const struct lttng_trigger *trigger_to_print = + (const struct lttng_trigger *) + lttng_dynamic_pointer_array_get_pointer( + &sorted_triggers, i); + + print_one_trigger(trigger_to_print); + } + + ret = 0; + goto end; +error: + ret = 1; + +end: + lttng_dynamic_pointer_array_reset(&sorted_triggers); + return ret; +} + +static enum lttng_error_code mi_error_query_trigger_callback( + const struct lttng_trigger *trigger, + struct lttng_error_query_results **results) +{ + enum lttng_error_code ret_code; + struct lttng_error_query *query = + lttng_error_query_trigger_create(trigger); + + assert(results); + assert(query); + + ret_code = lttng_error_query_execute( + query, lttng_session_daemon_command_endpoint, results); + if (ret_code != LTTNG_OK) { + enum lttng_trigger_status trigger_status; + const char *trigger_name; + uid_t trigger_uid; + + trigger_status = lttng_trigger_get_name(trigger, &trigger_name); + assert(trigger_status == LTTNG_TRIGGER_STATUS_OK); + + trigger_status = lttng_trigger_get_owner_uid( + trigger, &trigger_uid); + assert(trigger_status == LTTNG_TRIGGER_STATUS_OK); + + ERR("Failed to query errors of trigger '%s' (owner uid: %d): %s", + trigger_name, (int) trigger_uid, + lttng_strerror(-ret_code)); + } + + return ret_code; +} + +static enum lttng_error_code mi_error_query_action_callback( + const struct lttng_trigger *trigger, + const struct lttng_action_path *action_path, + struct lttng_error_query_results **results) +{ + enum lttng_error_code ret_code; + struct lttng_error_query *query = + lttng_error_query_action_create(trigger, action_path); + + assert(results); + assert(query); + + ret_code = lttng_error_query_execute( + query, lttng_session_daemon_command_endpoint, results); + if (ret_code != LTTNG_OK) { + enum lttng_trigger_status trigger_status; + const char *trigger_name; + uid_t trigger_uid; + + trigger_status = lttng_trigger_get_name(trigger, &trigger_name); + assert(trigger_status == LTTNG_TRIGGER_STATUS_OK); + + trigger_status = lttng_trigger_get_owner_uid( + trigger, &trigger_uid); + assert(trigger_status == LTTNG_TRIGGER_STATUS_OK); + + ERR("Failed to query errors of an action for trigger '%s' (owner uid: %d): %s", + trigger_name, (int) trigger_uid, + lttng_strerror(-ret_code)); + } + return ret_code; +} + +static enum lttng_error_code mi_error_query_condition_callback( + const struct lttng_trigger *trigger, + struct lttng_error_query_results **results) +{ + enum lttng_error_code ret_code; + struct lttng_error_query *query = + lttng_error_query_condition_create(trigger); + + assert(results); + assert(query); + + ret_code = lttng_error_query_execute( + query, lttng_session_daemon_command_endpoint, results); + if (ret_code != LTTNG_OK) { + enum lttng_trigger_status trigger_status; + const char *trigger_name; + uid_t trigger_uid; + + trigger_status = lttng_trigger_get_name(trigger, &trigger_name); + assert(trigger_status == LTTNG_TRIGGER_STATUS_OK); + + trigger_status = lttng_trigger_get_owner_uid( + trigger, &trigger_uid); + assert(trigger_status == LTTNG_TRIGGER_STATUS_OK); + + ERR("Failed to query errors of of condition for condition of trigger '%s' (owner uid: %d): %s", + trigger_name, (int) trigger_uid, + lttng_strerror(-ret_code)); + } + + return ret_code; +} +int cmd_list_triggers(int argc, const char **argv) +{ + int ret; + struct argpar_parse_ret argpar_parse_ret = {}; + struct lttng_triggers *triggers = NULL; + int i; + struct mi_writer *mi_writer = NULL; + argpar_parse_ret = argpar_parse( argc - 1, argv + 1, list_trigger_options, true); if (!argpar_parse_ret.items) { @@ -1029,8 +1338,8 @@ int cmd_list_triggers(int argc, const char **argv) goto end; case OPT_LIST_OPTIONS: - list_cmd_options_argpar(stdout, - list_trigger_options); + list_cmd_options_argpar( + stdout, list_trigger_options); ret = 0; goto end; @@ -1052,49 +1361,68 @@ int cmd_list_triggers(int argc, const char **argv) goto error; } - trigger_status = lttng_triggers_get_count(triggers, &num_triggers); - if (trigger_status != LTTNG_TRIGGER_STATUS_OK) { - ERR("Failed to get trigger count."); - goto error; - } - - for (i = 0; i < num_triggers; i++) { - int add_ret; - const char *unused_name; - const struct lttng_trigger *trigger = - lttng_triggers_get_at_index(triggers, i); + if (lttng_opt_mi) { + mi_writer = mi_lttng_writer_create( + fileno(stdout), lttng_opt_mi); + if (!mi_writer) { + ret = CMD_ERROR; + goto end; + } - trigger_status = lttng_trigger_get_name(trigger, &unused_name); - switch (trigger_status) { - case LTTNG_TRIGGER_STATUS_OK: - break; - case LTTNG_TRIGGER_STATUS_UNSET: - /* Don't list anonymous triggers. */ - continue; - default: - abort(); + /* Open command element. */ + ret = mi_lttng_writer_command_open(mi_writer, + mi_lttng_element_command_list_trigger); + if (ret) { + ret = CMD_ERROR; + goto end; } - add_ret = lttng_dynamic_pointer_array_add_pointer( - &sorted_triggers, (void *) trigger); + /* Open output element. */ + ret = mi_lttng_writer_open_element( + mi_writer, mi_lttng_element_command_output); + if (ret) { + ret = CMD_ERROR; + goto end; + } + } - if (add_ret) { - ERR("Failed to allocate array of struct lttng_trigger *."); + if (lttng_opt_mi) { + const struct mi_lttng_error_query_callbacks callbacks = { + .trigger_cb = mi_error_query_trigger_callback, + .action_cb = mi_error_query_action_callback, + .condition_cb = mi_error_query_condition_callback, + }; + + ret = lttng_triggers_mi_serialize( + triggers, mi_writer, &callbacks); + if (ret != LTTNG_OK) { + ERR("Error printing MI triggers: %s.", + lttng_strerror(-ret)); + goto error; + } + } else { + ret = print_sorted_triggers(triggers); + if (ret) { + ERR("Error printing triggers"); goto error; } } - qsort(sorted_triggers.array.buffer.data, num_triggers, - sizeof(struct lttng_trigger *), - compare_triggers_by_name); - - for (i = 0; i < num_triggers; i++) { - const struct lttng_trigger *trigger_to_print = - (const struct lttng_trigger *) - lttng_dynamic_pointer_array_get_pointer( - &sorted_triggers, i); + /* Mi closing. */ + if (lttng_opt_mi) { + /* Close output element. */ + ret = mi_lttng_writer_close_element(mi_writer); + if (ret) { + ret = CMD_ERROR; + goto end; + } - print_one_trigger(trigger_to_print); + /* Command element close. */ + ret = mi_lttng_writer_command_close(mi_writer); + if (ret) { + ret = CMD_ERROR; + goto end; + } } ret = 0; @@ -1106,7 +1434,10 @@ error: end: argpar_parse_ret_fini(&argpar_parse_ret); lttng_triggers_destroy(triggers); - lttng_dynamic_pointer_array_reset(&sorted_triggers); - + /* Mi clean-up. */ + if (mi_writer && mi_lttng_writer_destroy(mi_writer)) { + /* Preserve original error code. */ + ret = ret ? ret : CMD_ERROR; + } return ret; }