X-Git-Url: https://git.lttng.org/?p=lttng-tools.git;a=blobdiff_plain;f=src%2Fbin%2Flttng%2Fcommands%2Fadd_trigger.c;h=d460c0ffbda494a31aedd1b1832f498587254c00;hp=9ae8263c64a3a396e1b385d459ba996bf93474f1;hb=bbadb5e0b423348492c56ef7d8430087d9d9349d;hpb=f27911615bc5907d61d8ea236da974090bd85d24 diff --git a/src/bin/lttng/commands/add_trigger.c b/src/bin/lttng/commands/add_trigger.c index 9ae8263c6..d460c0ffb 100644 --- a/src/bin/lttng/commands/add_trigger.c +++ b/src/bin/lttng/commands/add_trigger.c @@ -40,9 +40,8 @@ enum { OPT_CONDITION, OPT_ACTION, OPT_ID, - OPT_FIRE_ONCE_AFTER, - OPT_FIRE_EVERY, OPT_USER_ID, + OPT_RATE_POLICY, OPT_ALL, OPT_FILTER, @@ -541,6 +540,7 @@ struct parse_event_rule_res parse_event_rule(int *argc, const char ***argv) struct parse_event_rule_res res = { 0 }; struct lttng_event_expr *event_expr = NULL; struct filter_parser_ctx *parser_ctx = NULL; + struct lttng_log_level_rule *log_level_rule = NULL; /* Was the -a/--all flag provided? */ bool all_events = false; @@ -627,7 +627,7 @@ struct parse_event_rule_res parse_event_rule(int *argc, const char ***argv) /* Event rule types */ case OPT_FUNCTION: if (!assign_event_rule_type(&event_rule_type, - LTTNG_EVENT_RULE_TYPE_KRETPROBE)) { + LTTNG_EVENT_RULE_TYPE_KERNEL_FUNCTION)) { goto error; } @@ -645,7 +645,7 @@ struct parse_event_rule_res parse_event_rule(int *argc, const char ***argv) break; case OPT_USERSPACE_PROBE: if (!assign_event_rule_type(&event_rule_type, - LTTNG_EVENT_RULE_TYPE_UPROBE)) { + LTTNG_EVENT_RULE_TYPE_USERSPACE_PROBE)) { goto error; } @@ -818,8 +818,8 @@ struct parse_event_rule_res parse_event_rule(int *argc, const char ***argv) /* Validate event rule type against domain. */ switch (event_rule_type) { case LTTNG_EVENT_RULE_TYPE_KERNEL_PROBE: - case LTTNG_EVENT_RULE_TYPE_KRETPROBE: - case LTTNG_EVENT_RULE_TYPE_UPROBE: + case LTTNG_EVENT_RULE_TYPE_KERNEL_FUNCTION: + case LTTNG_EVENT_RULE_TYPE_USERSPACE_PROBE: case LTTNG_EVENT_RULE_TYPE_SYSCALL: if (domain_type != LTTNG_DOMAIN_KERNEL) { ERR("Event type not available for user-space tracing."); @@ -938,15 +938,20 @@ struct parse_event_rule_res parse_event_rule(int *argc, const char ***argv) } if (loglevel_only) { - event_rule_status = lttng_event_rule_tracepoint_set_log_level( - res.er, - loglevel); + log_level_rule = lttng_log_level_rule_exactly_create(loglevel); } else { - event_rule_status = lttng_event_rule_tracepoint_set_log_level_range_lower_bound( - res.er, - loglevel); + log_level_rule = lttng_log_level_rule_at_least_as_severe_as_create(loglevel); } + if (log_level_rule == NULL) { + ERR("Failed to create log level rule object."); + goto error; + } + + event_rule_status = + lttng_event_rule_tracepoint_set_log_level_rule( + res.er, log_level_rule); + if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) { ERR("Failed to set log level on event fule."); goto error; @@ -960,11 +965,6 @@ struct parse_event_rule_res parse_event_rule(int *argc, const char ***argv) int ret; enum lttng_event_rule_status event_rule_status; - res.er = lttng_event_rule_kernel_probe_create(); - if (!res.er) { - ERR("Failed to create kprobe event rule."); - goto error; - } ret = parse_kernel_probe_opts(source, &kernel_probe_location); if (ret) { @@ -972,22 +972,22 @@ struct parse_event_rule_res parse_event_rule(int *argc, const char ***argv) goto error; } - event_rule_status = lttng_event_rule_kernel_probe_set_name(res.er, tracepoint_name); - if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) { - ERR("Failed to set kprobe event rule's name to '%s'.", tracepoint_name); + assert(kernel_probe_location); + res.er = lttng_event_rule_kernel_probe_create(kernel_probe_location); + if (!res.er) { + ERR("Failed to create kprobe event rule."); goto error; } - assert(kernel_probe_location); - event_rule_status = lttng_event_rule_kernel_probe_set_location(res.er, kernel_probe_location); + event_rule_status = lttng_event_rule_kernel_probe_set_event_name(res.er, tracepoint_name); if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) { - ERR("Failed to set kprobe event rule's location."); + ERR("Failed to set kprobe event rule's name to '%s'.", tracepoint_name); goto error; } break; } - case LTTNG_EVENT_RULE_TYPE_UPROBE: + case LTTNG_EVENT_RULE_TYPE_USERSPACE_PROBE: { int ret; enum lttng_event_rule_status event_rule_status; @@ -999,20 +999,13 @@ struct parse_event_rule_res parse_event_rule(int *argc, const char ***argv) goto error; } - res.er = lttng_event_rule_uprobe_create(); + res.er = lttng_event_rule_userspace_probe_create(userspace_probe_location); if (!res.er) { ERR("Failed to create userspace probe event rule."); goto error; } - event_rule_status = lttng_event_rule_uprobe_set_location( - res.er, userspace_probe_location); - if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) { - ERR("Failed to set user space probe event rule's location."); - goto error; - } - - event_rule_status = lttng_event_rule_uprobe_set_name( + event_rule_status = lttng_event_rule_userspace_probe_set_event_name( res.er, tracepoint_name); if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) { ERR("Failed to set user space probe event rule's name to '%s'.", @@ -1080,6 +1073,7 @@ end: strutils_free_null_terminated_array_of_strings(exclusion_list); lttng_kernel_probe_location_destroy(kernel_probe_location); lttng_userspace_probe_location_destroy(userspace_probe_location); + lttng_log_level_rule_destroy(log_level_rule); return res; } @@ -1096,7 +1090,7 @@ struct lttng_condition *handle_condition_event(int *argc, const char ***argv) goto error; } - c = lttng_condition_event_rule_create(res.er); + c = lttng_condition_on_event_create(res.er); lttng_event_rule_destroy(res.er); res.er = NULL; if (!c) { @@ -1112,7 +1106,7 @@ struct lttng_condition *handle_condition_event(int *argc, const char ***argv) assert(expr); assert(*expr); - status = lttng_condition_event_rule_append_capture_descriptor( + status = lttng_condition_on_event_append_capture_descriptor( c, *expr); if (status != LTTNG_CONDITION_STATUS_OK) { if (status == LTTNG_CONDITION_STATUS_UNSUPPORTED) { @@ -1341,27 +1335,191 @@ end: return cond; } - -static -struct lttng_action *handle_action_notify(int *argc, const char ***argv) +static struct lttng_rate_policy *parse_rate_policy(const char *policy_str) { - return lttng_action_notify_create(); + int num_token; + char **tokens = NULL; + struct lttng_rate_policy *policy = NULL; + enum lttng_rate_policy_type policy_type; + unsigned long long value; + char *policy_type_str; + char *policy_value_str; + + assert(policy_str); + + /* + * rate policy fields are separated by ':'. + */ + tokens = strutils_split(policy_str, ':', 1); + num_token = strutils_array_of_strings_len(tokens); + + /* + * Early sanity check that the number of parameter is exactly 2. + * i.e : type:value + */ + if (num_token != 2) { + ERR("Rate policy format is invalid."); + goto end; + } + + policy_type_str = tokens[0]; + policy_value_str = tokens[1]; + + /* Parse the type. */ + if (strcmp(policy_type_str, "once-after") == 0) { + policy_type = LTTNG_RATE_POLICY_TYPE_ONCE_AFTER_N; + } else if (strcmp(policy_type_str, "every") == 0) { + policy_type = LTTNG_RATE_POLICY_TYPE_EVERY_N; + } else { + ERR("Rate policy type `%s` unknown.", policy_type_str); + goto end; + } + + /* Parse the value. */ + if (utils_parse_unsigned_long_long(policy_value_str, &value) != 0) { + ERR("Failed to parse rate policy value `%s` as an integer.", + policy_value_str); + goto end; + } + + if (value == 0) { + ERR("Rate policy value `%s` must be > 0.", policy_value_str); + goto end; + } + + switch (policy_type) { + case LTTNG_RATE_POLICY_TYPE_EVERY_N: + policy = lttng_rate_policy_every_n_create(value); + break; + case LTTNG_RATE_POLICY_TYPE_ONCE_AFTER_N: + policy = lttng_rate_policy_once_after_n_create(value); + break; + default: + abort(); + } + + if (policy == NULL) { + ERR("Failed to create rate policy `%s`.", policy_str); + } + +end: + strutils_free_null_terminated_array_of_strings(tokens); + return policy; } -static const struct argpar_opt_descr no_opt_descrs[] = { +static const struct argpar_opt_descr notify_action_opt_descrs[] = { + { OPT_RATE_POLICY, '\0', "rate-policy", true }, ARGPAR_OPT_DESCR_SENTINEL }; +static +struct lttng_action *handle_action_notify(int *argc, const char ***argv) +{ + struct lttng_action *action = NULL; + struct argpar_state *state = NULL; + struct argpar_item *item = NULL; + char *error = NULL; + struct lttng_rate_policy *policy = NULL; + + state = argpar_state_create(*argc, *argv, notify_action_opt_descrs); + if (!state) { + ERR("Failed to allocate an argpar state."); + goto error; + } + + while (true) { + enum argpar_state_parse_next_status status; + + ARGPAR_ITEM_DESTROY_AND_RESET(item); + status = argpar_state_parse_next(state, &item, &error); + if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_ERROR) { + ERR("%s", error); + goto error; + } else if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_ERROR_UNKNOWN_OPT) { + /* Just stop parsing here. */ + break; + } else if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_END) { + break; + } + + assert(status == ARGPAR_STATE_PARSE_NEXT_STATUS_OK); + + if (item->type == ARGPAR_ITEM_TYPE_OPT) { + const struct argpar_item_opt *item_opt = + (const struct argpar_item_opt *) item; + + switch (item_opt->descr->id) { + case OPT_RATE_POLICY: + { + policy = parse_rate_policy(item_opt->arg); + if (!policy) { + goto error; + } + break; + } + default: + abort(); + } + } else { + const struct argpar_item_non_opt *item_non_opt; + + assert(item->type == ARGPAR_ITEM_TYPE_NON_OPT); + + item_non_opt = (const struct argpar_item_non_opt *) item; + + switch (item_non_opt->non_opt_index) { + default: + ERR("Unexpected argument `%s`.", + item_non_opt->arg); + goto error; + } + } + } + + *argc -= argpar_state_get_ingested_orig_args(state); + *argv += argpar_state_get_ingested_orig_args(state); + + action = lttng_action_notify_create(); + if (!action) { + ERR("Failed to create notify action"); + goto error; + } + + if (policy) { + enum lttng_action_status status; + status = lttng_action_notify_set_rate_policy(action, policy); + if (status != LTTNG_ACTION_STATUS_OK) { + ERR("Failed to set rate policy"); + goto error; + } + } + + goto end; + +error: + lttng_action_destroy(action); + action = NULL; + free(error); +end: + lttng_rate_policy_destroy(policy); + argpar_state_destroy(state); + argpar_item_destroy(item); + return action; +} + /* - * Generic handler for a kind of action that takes a session name as its sole - * argument. + * Generic handler for a kind of action that takes a session name and an + * optional rate policy. */ -static -struct lttng_action *handle_action_simple_session( - int *argc, const char ***argv, +static struct lttng_action *handle_action_simple_session_with_policy(int *argc, + const char ***argv, struct lttng_action *(*create_action_cb)(void), - enum lttng_action_status (*set_session_name_cb)(struct lttng_action *, const char *), + enum lttng_action_status (*set_session_name_cb)( + struct lttng_action *, const char *), + enum lttng_action_status (*set_rate_policy_cb)( + struct lttng_action *, + const struct lttng_rate_policy *), const char *action_name) { struct lttng_action *action = NULL; @@ -1370,8 +1528,17 @@ struct lttng_action *handle_action_simple_session( const char *session_name_arg = NULL; char *error = NULL; enum lttng_action_status action_status; + struct lttng_rate_policy *policy = NULL; + + assert(set_session_name_cb); + assert(set_rate_policy_cb); - state = argpar_state_create(*argc, *argv, no_opt_descrs); + const struct argpar_opt_descr rate_policy_opt_descrs[] = { + { OPT_RATE_POLICY, '\0', "rate-policy", true }, + ARGPAR_OPT_DESCR_SENTINEL + }; + + state = argpar_state_create(*argc, *argv, rate_policy_opt_descrs); if (!state) { ERR("Failed to allocate an argpar state."); goto error; @@ -1379,14 +1546,14 @@ struct lttng_action *handle_action_simple_session( while (true) { enum argpar_state_parse_next_status status; - const struct argpar_item_non_opt *item_non_opt; ARGPAR_ITEM_DESTROY_AND_RESET(item); status = argpar_state_parse_next(state, &item, &error); if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_ERROR) { ERR("%s", error); goto error; - } else if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_ERROR_UNKNOWN_OPT) { + } else if (status == + ARGPAR_STATE_PARSE_NEXT_STATUS_ERROR_UNKNOWN_OPT) { /* Just stop parsing here. */ break; } else if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_END) { @@ -1394,17 +1561,35 @@ struct lttng_action *handle_action_simple_session( } assert(status == ARGPAR_STATE_PARSE_NEXT_STATUS_OK); - assert(item->type == ARGPAR_ITEM_TYPE_NON_OPT); + if (item->type == ARGPAR_ITEM_TYPE_OPT) { + const struct argpar_item_opt *item_opt = + (const struct argpar_item_opt *) item; - item_non_opt = (const struct argpar_item_non_opt *) item; + switch (item_opt->descr->id) { + case OPT_RATE_POLICY: + { + policy = parse_rate_policy(item_opt->arg); + if (!policy) { + goto error; + } + break; + } + default: + abort(); + } + } else { + const struct argpar_item_non_opt *item_non_opt; + item_non_opt = (const struct argpar_item_non_opt *) item; - switch (item_non_opt->non_opt_index) { - case 0: - session_name_arg = item_non_opt->arg; - break; - default: - ERR("Unexpected argument `%s`.", item_non_opt->arg); - goto error; + switch (item_non_opt->non_opt_index) { + case 0: + session_name_arg = item_non_opt->arg; + break; + default: + ERR("Unexpected argument `%s`.", + item_non_opt->arg); + goto error; + } } } @@ -1429,6 +1614,14 @@ struct lttng_action *handle_action_simple_session( goto error; } + if (policy) { + action_status = set_rate_policy_cb(action, policy); + if (action_status != LTTNG_ACTION_STATUS_OK) { + ERR("Failed to set rate policy"); + goto error; + } + } + goto end; error: @@ -1436,6 +1629,7 @@ error: action = NULL; argpar_item_destroy(item); end: + lttng_rate_policy_destroy(policy); free(error); argpar_state_destroy(state); return action; @@ -1445,29 +1639,30 @@ static struct lttng_action *handle_action_start_session(int *argc, const char ***argv) { - return handle_action_simple_session(argc, argv, - lttng_action_start_session_create, - lttng_action_start_session_set_session_name, - "start"); + return handle_action_simple_session_with_policy(argc, argv, + lttng_action_start_session_create, + lttng_action_start_session_set_session_name, + lttng_action_start_session_set_rate_policy, "start"); } static struct lttng_action *handle_action_stop_session(int *argc, const char ***argv) { - return handle_action_simple_session(argc, argv, - lttng_action_stop_session_create, - lttng_action_stop_session_set_session_name, - "stop"); + return handle_action_simple_session_with_policy(argc, argv, + lttng_action_stop_session_create, + lttng_action_stop_session_set_session_name, + lttng_action_stop_session_set_rate_policy, "stop"); } static struct lttng_action *handle_action_rotate_session(int *argc, const char ***argv) { - return handle_action_simple_session(argc, argv, + return handle_action_simple_session_with_policy(argc, argv, lttng_action_rotate_session_create, lttng_action_rotate_session_set_session_name, + lttng_action_rotate_session_set_rate_policy, "rotate"); } @@ -1478,6 +1673,7 @@ static const struct argpar_opt_descr snapshot_action_opt_descrs[] = { { OPT_DATA_URL, '\0', "data-url", true }, { OPT_URL, '\0', "url", true }, { OPT_PATH, '\0', "path", true }, + { OPT_RATE_POLICY, '\0', "rate-policy", true }, ARGPAR_OPT_DESCR_SENTINEL }; @@ -1498,6 +1694,7 @@ struct lttng_action *handle_action_snapshot_session(int *argc, char *error = NULL; enum lttng_action_status action_status; struct lttng_snapshot_output *snapshot_output = NULL; + struct lttng_rate_policy *policy = NULL; int ret; unsigned int locations_specified = 0; @@ -1565,6 +1762,14 @@ struct lttng_action *handle_action_snapshot_session(int *argc, } break; + case OPT_RATE_POLICY: + { + policy = parse_rate_policy(item_opt->arg); + if (!policy) { + goto error; + } + break; + } default: abort(); } @@ -1749,6 +1954,16 @@ struct lttng_action *handle_action_snapshot_session(int *argc, snapshot_output = NULL; } + if (policy) { + enum lttng_action_status status; + status = lttng_action_snapshot_session_set_rate_policy( + action, policy); + if (status != LTTNG_ACTION_STATUS_OK) { + ERR("Failed to set rate policy"); + goto error; + } + } + goto end; error: @@ -1763,6 +1978,7 @@ end: free(data_url_arg); free(snapshot_output); free(max_size_arg); + lttng_rate_policy_destroy(policy); argpar_state_destroy(state); argpar_item_destroy(item); return action; @@ -1832,8 +2048,6 @@ struct argpar_opt_descr add_trigger_options[] = { { OPT_CONDITION, '\0', "condition", false }, { OPT_ACTION, '\0', "action", false }, { OPT_ID, '\0', "id", true }, - { OPT_FIRE_ONCE_AFTER, '\0', "fire-once-after", true }, - { OPT_FIRE_EVERY, '\0', "fire-every", true }, { OPT_USER_ID, '\0', "user-id", true }, ARGPAR_OPT_DESCR_SENTINEL, }; @@ -1861,8 +2075,6 @@ int cmd_add_trigger(int argc, const char **argv) char *error = NULL; char *id = NULL; int i; - char *fire_once_after_str = NULL; - char *fire_every_str = NULL; char *user_id = NULL; lttng_dynamic_pointer_array_init(&actions, lttng_actions_destructor); @@ -1969,24 +2181,6 @@ int cmd_add_trigger(int argc, const char **argv) break; } - case OPT_FIRE_ONCE_AFTER: - { - if (!assign_string(&fire_once_after_str, item_opt->arg, - "--fire-once-after")) { - goto error; - } - - break; - } - case OPT_FIRE_EVERY: - { - if (!assign_string(&fire_every_str, item_opt->arg, - "--fire-every")) { - goto error; - } - - break; - } case OPT_USER_ID: { if (!assign_string(&user_id, item_opt->arg, @@ -2011,11 +2205,6 @@ int cmd_add_trigger(int argc, const char **argv) goto error; } - if (fire_every_str && fire_once_after_str) { - ERR("Can't specify both --fire-once-after and --fire-every."); - goto error; - } - action_group = lttng_action_group_create(); if (!action_group) { goto error; @@ -2054,41 +2243,6 @@ int cmd_add_trigger(int argc, const char **argv) } } - if (fire_once_after_str) { - unsigned long long threshold; - enum lttng_trigger_status trigger_status; - - if (utils_parse_unsigned_long_long(fire_once_after_str, &threshold) != 0) { - ERR("Failed to parse `%s` as an integer.", fire_once_after_str); - goto error; - } - - trigger_status = lttng_trigger_set_firing_policy(trigger, - LTTNG_TRIGGER_FIRING_POLICY_ONCE_AFTER_N, - threshold); - if (trigger_status != LTTNG_TRIGGER_STATUS_OK) { - ERR("Failed to set trigger's policy to `fire once after N`."); - goto error; - } - } - - if (fire_every_str) { - unsigned long long threshold; - enum lttng_trigger_status trigger_status; - - if (utils_parse_unsigned_long_long(fire_every_str, &threshold) != 0) { - ERR("Failed to parse `%s` as an integer.", fire_every_str); - goto error; - } - - trigger_status = lttng_trigger_set_firing_policy(trigger, - LTTNG_TRIGGER_FIRING_POLICY_EVERY_N, threshold); - if (trigger_status != LTTNG_TRIGGER_STATUS_OK) { - ERR("Failed to set trigger's policy to `fire every N`."); - goto error; - } - } - if (user_id) { enum lttng_trigger_status trigger_status; char *end; @@ -2130,8 +2284,6 @@ end: lttng_trigger_destroy(trigger); free(error); free(id); - free(fire_once_after_str); - free(fire_every_str); free(user_id); return ret; }