From 0f7c296359bf90005e1dadf2d7a02a4b223a8031 Mon Sep 17 00:00:00 2001 From: Jonathan Rajotte Date: Thu, 6 May 2021 21:26:17 -0400 Subject: [PATCH] MI: implement all objects related to trigger machine interface MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Signed-off-by: Jonathan Rajotte Signed-off-by: Jérémie Galarneau Change-Id: Idb2045135b1ba87853d6214b149afbe27bb7a1ca --- include/lttng/action/action-internal.h | 16 +- include/lttng/action/list-internal.h | 12 + include/lttng/action/rate-policy-internal.h | 7 + include/lttng/condition/condition-internal.h | 23 +- include/lttng/error-query-internal.h | 7 + include/lttng/event-expr-internal.h | 6 + .../lttng/event-rule/event-rule-internal.h | 9 + include/lttng/kernel-probe-internal.h | 10 + include/lttng/log-level-rule-internal.h | 7 + include/lttng/trigger/trigger-internal.h | 22 ++ include/lttng/userspace-probe-internal.h | 10 + src/common/actions/action.c | 98 +++++- src/common/actions/list.c | 95 +++++- src/common/actions/notify.c | 48 ++- src/common/actions/rate-policy.c | 148 ++++++++- src/common/actions/rotate-session.c | 60 +++- src/common/actions/snapshot-session.c | 74 ++++- src/common/actions/start-session.c | 60 +++- src/common/actions/stop-session.c | 60 +++- src/common/conditions/buffer-usage.c | 134 +++++++- src/common/conditions/condition.c | 72 ++++- src/common/conditions/event-rule-matches.c | 77 +++++ src/common/conditions/session-consumed-size.c | 71 +++- src/common/conditions/session-rotation.c | 75 ++++- src/common/error-query.c | 183 +++++++++++ src/common/event-expr/event-expr.c | 265 +++++++++++++++ src/common/event-rule/event-rule.c | 51 ++- src/common/event-rule/jul-logging.c | 87 ++++- src/common/event-rule/kernel-kprobe.c | 70 +++- src/common/event-rule/kernel-syscall.c | 97 +++++- src/common/event-rule/kernel-tracepoint.c | 69 +++- src/common/event-rule/kernel-uprobe.c | 65 +++- src/common/event-rule/log4j-logging.c | 86 ++++- src/common/event-rule/python-logging.c | 86 ++++- src/common/event-rule/user-tracepoint.c | 123 ++++++- src/common/kernel-probe.c | 168 +++++++++- src/common/log-level-rule.c | 75 ++++- src/common/mi-lttng.c | 227 ++++++++++++- src/common/mi-lttng.h | 186 ++++++++++- src/common/snapshot.c | 81 ++++- src/common/snapshot.h | 6 + src/common/trigger.c | 200 ++++++++++++ src/common/userspace-probe.c | 304 +++++++++++++++++- 43 files changed, 3544 insertions(+), 86 deletions(-) diff --git a/include/lttng/action/action-internal.h b/include/lttng/action/action-internal.h index 0649333f2..e97d4f032 100644 --- a/include/lttng/action/action-internal.h +++ b/include/lttng/action/action-internal.h @@ -20,6 +20,9 @@ #include struct lttng_rate_policy; +struct mi_writer; +struct mi_lttng_error_query_callbacks; +struct lttng_trigger; typedef bool (*action_validate_cb)(struct lttng_action *action); typedef void (*action_destroy_cb)(struct lttng_action *action); @@ -35,6 +38,8 @@ typedef const struct lttng_rate_policy *(*action_get_rate_policy_cb)( typedef enum lttng_action_status (*action_add_error_query_results_cb)( const struct lttng_action *action, struct lttng_error_query_results *results); +typedef enum lttng_error_code (*action_mi_serialize_cb)( + const struct lttng_action *condition, struct mi_writer *writer); struct lttng_action { struct urcu_ref ref; @@ -45,6 +50,7 @@ struct lttng_action { action_destroy_cb destroy; action_get_rate_policy_cb get_rate_policy; action_add_error_query_results_cb add_error_query_results; + action_mi_serialize_cb mi_serialize; /* Internal use only. */ @@ -76,7 +82,8 @@ void lttng_action_init(struct lttng_action *action, action_equal_cb equal, action_destroy_cb destroy, action_get_rate_policy_cb get_rate_policy, - action_add_error_query_results_cb add_error_query_results); + action_add_error_query_results_cb add_error_query_results, + action_mi_serialize_cb mi); LTTNG_HIDDEN bool lttng_action_validate(struct lttng_action *action); @@ -128,5 +135,12 @@ LTTNG_HIDDEN enum lttng_action_status lttng_action_generic_add_error_query_results( const struct lttng_action *action, struct lttng_error_query_results *results); +LTTNG_HIDDEN +enum lttng_error_code lttng_action_mi_serialize(const struct lttng_trigger *trigger, + const struct lttng_action *action, + struct mi_writer *writer, + const struct mi_lttng_error_query_callbacks + *error_query_callbacks, + struct lttng_dynamic_array *action_path_indexes); #endif /* LTTNG_ACTION_INTERNAL_H */ diff --git a/include/lttng/action/list-internal.h b/include/lttng/action/list-internal.h index 4aca7fa27..ea9fc0df0 100644 --- a/include/lttng/action/list-internal.h +++ b/include/lttng/action/list-internal.h @@ -14,6 +14,10 @@ struct lttng_action; struct lttng_payload_view; +struct mi_writer; +struct mi_lttng_error_query_callbacks; +struct lttng_dynamic_array; +struct lttng_trigger; /* * Create an action list from a payload view. @@ -30,4 +34,12 @@ LTTNG_HIDDEN extern struct lttng_action *lttng_action_list_borrow_mutable_at_index( const struct lttng_action *list, unsigned int index); +LTTNG_HIDDEN +enum lttng_error_code lttng_action_list_mi_serialize(const struct lttng_trigger *trigger, + const struct lttng_action *action, + struct mi_writer *writer, + const struct mi_lttng_error_query_callbacks + *error_query_callbacks, + struct lttng_dynamic_array *action_path_indexes); + #endif /* LTTNG_ACTION_LIST_INTERNAL_H */ diff --git a/include/lttng/action/rate-policy-internal.h b/include/lttng/action/rate-policy-internal.h index 03f6d9736..ca9d2c00e 100644 --- a/include/lttng/action/rate-policy-internal.h +++ b/include/lttng/action/rate-policy-internal.h @@ -13,6 +13,8 @@ #include #include +struct mi_writer; + LTTNG_HIDDEN int lttng_rate_policy_serialize(struct lttng_rate_policy *rate_policy, struct lttng_payload *buf); @@ -37,4 +39,9 @@ LTTNG_HIDDEN bool lttng_rate_policy_should_execute( const struct lttng_rate_policy *policy, uint64_t counter); +LTTNG_HIDDEN +enum lttng_error_code lttng_rate_policy_mi_serialize( + const struct lttng_rate_policy *policy, + struct mi_writer *writer); + #endif /* LTTNG_RATE_POLICY */ diff --git a/include/lttng/condition/condition-internal.h b/include/lttng/condition/condition-internal.h index 92bb4de71..9552fa4a4 100644 --- a/include/lttng/condition/condition-internal.h +++ b/include/lttng/condition/condition-internal.h @@ -8,15 +8,20 @@ #ifndef LTTNG_CONDITION_INTERNAL_H #define LTTNG_CONDITION_INTERNAL_H -#include #include #include #include +#include +#include #include -#include -#include #include #include +#include +#include + +struct mi_writer; +struct mi_lttng_error_query_callbacks; +struct lttng_trigger; typedef void (*condition_destroy_cb)(struct lttng_condition *condition); typedef bool (*condition_validate_cb)(const struct lttng_condition *condition); @@ -28,6 +33,9 @@ typedef bool (*condition_equal_cb)(const struct lttng_condition *a, typedef ssize_t (*condition_create_from_payload_cb)( struct lttng_payload_view *view, struct lttng_condition **condition); +typedef enum lttng_error_code (*condition_mi_serialize_cb)( + const struct lttng_condition *condition, + struct mi_writer *writer); struct lttng_condition { /* Reference counting is only exposed to internal users. */ @@ -37,6 +45,7 @@ struct lttng_condition { condition_serialize_cb serialize; condition_equal_cb equal; condition_destroy_cb destroy; + condition_mi_serialize_cb mi_serialize; }; struct lttng_condition_comm { @@ -71,6 +80,14 @@ LTTNG_HIDDEN bool lttng_condition_is_equal(const struct lttng_condition *a, const struct lttng_condition *b); +LTTNG_HIDDEN +enum lttng_error_code lttng_condition_mi_serialize( + const struct lttng_trigger *trigger, + const struct lttng_condition *condition, + struct mi_writer *writer, + const struct mi_lttng_error_query_callbacks + *error_query_callbacks); + LTTNG_HIDDEN const char *lttng_condition_type_str(enum lttng_condition_type type); diff --git a/include/lttng/error-query-internal.h b/include/lttng/error-query-internal.h index 5de3c43f9..506ebcf97 100644 --- a/include/lttng/error-query-internal.h +++ b/include/lttng/error-query-internal.h @@ -15,6 +15,8 @@ #include #include +struct mi_writer; + enum lttng_error_query_target_type { LTTNG_ERROR_QUERY_TARGET_TYPE_TRIGGER, LTTNG_ERROR_QUERY_TARGET_TYPE_CONDITION, @@ -87,4 +89,9 @@ int lttng_error_query_results_add_result( struct lttng_error_query_results *results, struct lttng_error_query_result *result); +LTTNG_HIDDEN +enum lttng_error_code lttng_error_query_results_mi_serialize( + const struct lttng_error_query_results *results, + struct mi_writer *writer); + #endif /* LTTNG_ERROR_QUERY_INTERNAL_H */ diff --git a/include/lttng/event-expr-internal.h b/include/lttng/event-expr-internal.h index 048aaff18..e51a770ce 100644 --- a/include/lttng/event-expr-internal.h +++ b/include/lttng/event-expr-internal.h @@ -13,6 +13,7 @@ #include struct lttng_bytecode; +struct mi_writer; struct lttng_event_expr { enum lttng_event_expr_type type; @@ -61,4 +62,9 @@ LTTNG_HIDDEN int lttng_event_expr_to_bytecode(const struct lttng_event_expr *expr, struct lttng_bytecode **bytecode_out); +LTTNG_HIDDEN +enum lttng_error_code lttng_event_expr_mi_serialize( + const struct lttng_event_expr *expression, + struct mi_writer *writer); + #endif /* LTTNG_EVENT_EXPR_INTERNAL_H */ diff --git a/include/lttng/event-rule/event-rule-internal.h b/include/lttng/event-rule/event-rule-internal.h index dd2d7dd18..acd84827c 100644 --- a/include/lttng/event-rule/event-rule-internal.h +++ b/include/lttng/event-rule/event-rule-internal.h @@ -22,6 +22,7 @@ struct lttng_payload; struct lttng_payload_view; +struct mi_writer; enum lttng_event_rule_generate_exclusions_status { LTTNG_EVENT_RULE_GENERATE_EXCLUSIONS_STATUS_OK, @@ -57,6 +58,9 @@ typedef unsigned long (*event_rule_hash_cb)( const struct lttng_event_rule *event_rule); typedef struct lttng_event *(*event_rule_generate_lttng_event_cb)( const struct lttng_event_rule *event_rule); +typedef enum lttng_error_code (*event_rule_mi_serialize_cb)( + const struct lttng_event_rule *event_rule, + struct mi_writer *writer); struct lttng_event_rule { struct urcu_ref ref; @@ -71,6 +75,7 @@ struct lttng_event_rule { event_rule_generate_exclusions_cb generate_exclusions; event_rule_hash_cb hash; event_rule_generate_lttng_event_cb generate_lttng_event; + event_rule_mi_serialize_cb mi_serialize; }; struct lttng_event_rule_comm { @@ -161,4 +166,8 @@ struct lttng_event *lttng_event_rule_generate_lttng_event( LTTNG_HIDDEN bool lttng_event_rule_targets_agent_domain(const struct lttng_event_rule *rule); +LTTNG_HIDDEN +enum lttng_error_code lttng_event_rule_mi_serialize( + const struct lttng_event_rule *rule, struct mi_writer *writer); + #endif /* LTTNG_EVENT_RULE_INTERNAL_H */ diff --git a/include/lttng/kernel-probe-internal.h b/include/lttng/kernel-probe-internal.h index e2889fd78..2a655fb80 100644 --- a/include/lttng/kernel-probe-internal.h +++ b/include/lttng/kernel-probe-internal.h @@ -18,6 +18,7 @@ struct lttng_payload; struct lttng_payload_view; struct lttng_dynamic_buffer; +struct mi_writer; typedef bool (*kernel_probe_location_equal_cb)( const struct lttng_kernel_probe_location *a, @@ -33,6 +34,9 @@ typedef ssize_t (*kernel_probe_location_create_from_payload_cb)( struct lttng_kernel_probe_location **kernel_probe_location); typedef unsigned long (*kernel_probe_location_hash_cb)( const struct lttng_kernel_probe_location *location); +typedef enum lttng_error_code (*kernel_probe_location_mi_serialize_cb)( + const struct lttng_kernel_probe_location *location, + struct mi_writer *writer); struct lttng_kernel_probe_location_comm { /* enum lttng_kernel_probe_location_type */ @@ -66,6 +70,7 @@ struct lttng_kernel_probe_location { kernel_probe_location_equal_cb equal; kernel_probe_location_serialize_cb serialize; kernel_probe_location_hash_cb hash; + kernel_probe_location_mi_serialize_cb mi_serialize; }; struct lttng_kernel_probe_location_symbol { @@ -102,4 +107,9 @@ LTTNG_HIDDEN unsigned long lttng_kernel_probe_location_hash( const struct lttng_kernel_probe_location *location); +LTTNG_HIDDEN +enum lttng_error_code lttng_kernel_probe_location_mi_serialize( + const struct lttng_kernel_probe_location *location, + struct mi_writer *writer); + #endif /* LTTNG_KERNEL_PROBE_INTERNAL_H */ diff --git a/include/lttng/log-level-rule-internal.h b/include/lttng/log-level-rule-internal.h index f0ca63222..f3b2a1c2a 100644 --- a/include/lttng/log-level-rule-internal.h +++ b/include/lttng/log-level-rule-internal.h @@ -18,6 +18,8 @@ #include #include +struct mi_writer; + /* * For now only a single backing struct is used for both type of log level * rule (exactly, as_severe) since both only have require "level" as property. @@ -60,4 +62,9 @@ LTTNG_HIDDEN unsigned long lttng_log_level_rule_hash( const struct lttng_log_level_rule *log_level_rule); +LTTNG_HIDDEN +enum lttng_error_code lttng_log_level_rule_mi_serialize( + const struct lttng_log_level_rule *rule, + struct mi_writer *writer); + #endif /* LTTNG_LOG_LEVEL_RULE_INTERNAL_H */ diff --git a/include/lttng/trigger/trigger-internal.h b/include/lttng/trigger/trigger-internal.h index 02dcf5335..d917ffa01 100644 --- a/include/lttng/trigger/trigger-internal.h +++ b/include/lttng/trigger/trigger-internal.h @@ -21,6 +21,8 @@ struct lttng_payload; struct lttng_payload_view; +struct mi_writer; +struct mi_lttng_error_query_callbacks; struct lttng_trigger { /* Reference counting is only exposed to internal users. */ @@ -122,6 +124,16 @@ void lttng_trigger_get(struct lttng_trigger *trigger); LTTNG_HIDDEN void lttng_trigger_put(struct lttng_trigger *trigger); +/* + * Serialize a trigger to a mi_writer. + * Return LTTNG_OK in success, other enum lttng_error_code on error. + */ +LTTNG_HIDDEN +enum lttng_error_code lttng_trigger_mi_serialize(const struct lttng_trigger *trigger, + struct mi_writer *writer, + const struct mi_lttng_error_query_callbacks + *error_query_callbacks); + /* * Allocate a new set of triggers. * The returned object must be freed via lttng_triggers_destroy. @@ -165,6 +177,16 @@ LTTNG_HIDDEN ssize_t lttng_triggers_create_from_payload(struct lttng_payload_view *view, struct lttng_triggers **triggers); +/* + * Serialize a trigger set to a mi_writer. + * Return LTTNG_OK in success, other enum lttng_error_code on error. + */ +LTTNG_HIDDEN +enum lttng_error_code lttng_triggers_mi_serialize(const struct lttng_triggers *triggers, + struct mi_writer *writer, + const struct mi_lttng_error_query_callbacks + *error_query_callbacks); + LTTNG_HIDDEN const struct lttng_credentials *lttng_trigger_get_credentials( const struct lttng_trigger *trigger); diff --git a/include/lttng/userspace-probe-internal.h b/include/lttng/userspace-probe-internal.h index b530e2963..e0075974f 100644 --- a/include/lttng/userspace-probe-internal.h +++ b/include/lttng/userspace-probe-internal.h @@ -17,12 +17,16 @@ struct lttng_payload; struct lttng_payload_view; struct lttng_dynamic_buffer; +struct mi_writer; typedef bool (*userspace_probe_location_equal_cb)( const struct lttng_userspace_probe_location *a, const struct lttng_userspace_probe_location *b); typedef unsigned long (*userspace_probe_location_hash_cb)( const struct lttng_userspace_probe_location *location); +typedef enum lttng_error_code (*userspace_probe_location_mi)( + const struct lttng_userspace_probe_location *location, + struct mi_writer); /* * No elf-specific comm structure is defined since no elf-specific payload is @@ -91,6 +95,7 @@ struct lttng_userspace_probe_location { struct lttng_userspace_probe_location_lookup_method *lookup_method; userspace_probe_location_equal_cb equal; userspace_probe_location_hash_cb hash; + userspace_probe_location_hash_cb mi; }; struct lttng_userspace_probe_location_function { @@ -157,4 +162,9 @@ LTTNG_HIDDEN unsigned long lttng_userspace_probe_location_hash( const struct lttng_userspace_probe_location *location); +LTTNG_HIDDEN +enum lttng_error_code lttng_userspace_probe_location_mi_serialize( + const struct lttng_userspace_probe_location *location, + struct mi_writer *writer); + #endif /* LTTNG_USERSPACE_PROBE_INTERNAL_H */ diff --git a/src/common/actions/action.c b/src/common/actions/action.c index 498e41f79..4dabfff30 100644 --- a/src/common/actions/action.c +++ b/src/common/actions/action.c @@ -7,6 +7,7 @@ #include #include +#include #include #include #include @@ -53,7 +54,8 @@ void lttng_action_init(struct lttng_action *action, action_equal_cb equal, action_destroy_cb destroy, action_get_rate_policy_cb get_rate_policy, - action_add_error_query_results_cb add_error_query_results) + action_add_error_query_results_cb add_error_query_results, + action_mi_serialize_cb mi) { urcu_ref_init(&action->ref); action->type = type; @@ -63,6 +65,7 @@ void lttng_action_init(struct lttng_action *action, action->destroy = destroy; action->get_rate_policy = get_rate_policy; action->add_error_query_results = add_error_query_results; + action->mi_serialize = mi; action->execution_request_counter = 0; action->execution_counter = 0; @@ -334,3 +337,96 @@ end: lttng_error_query_result_destroy(error_counter); return action_status; } + +LTTNG_HIDDEN +enum lttng_error_code lttng_action_mi_serialize(const struct lttng_trigger *trigger, + const struct lttng_action *action, + struct mi_writer *writer, + const struct mi_lttng_error_query_callbacks + *error_query_callbacks, + struct lttng_dynamic_array *action_path_indexes) +{ + int ret; + enum lttng_error_code ret_code; + struct lttng_action_path *action_path = NULL; + struct lttng_error_query_results *error_query_results = NULL; + + assert(action); + assert(writer); + + /* Open action. */ + ret = mi_lttng_writer_open_element(writer, mi_lttng_element_action); + if (ret) { + goto mi_error; + } + + if (action->type == LTTNG_ACTION_TYPE_LIST) { + /* + * Recursion is safe since action lists can't be nested for + * the moment. + */ + ret_code = lttng_action_list_mi_serialize(trigger, action, writer, + error_query_callbacks, action_path_indexes); + if (ret_code != LTTNG_OK) { + goto end; + } + + /* Nothing else to do. */ + goto close_action_element; + } + + assert(action->mi_serialize); + ret_code = action->mi_serialize(action, writer); + if (ret_code != LTTNG_OK) { + goto end; + } + + /* Error query for the action. */ + if (error_query_callbacks && error_query_callbacks->action_cb) { + const uint64_t *action_path_indexes_raw_pointer = NULL; + const size_t action_path_indexes_size = + lttng_dynamic_array_get_count( + action_path_indexes); + + if (action_path_indexes_size != 0) { + action_path_indexes_raw_pointer = + (const uint64_t *) action_path_indexes + ->buffer.data; + } + + action_path = lttng_action_path_create( + action_path_indexes_raw_pointer, + action_path_indexes_size); + assert(action_path); + + ret_code = error_query_callbacks->action_cb( + trigger, action_path, &error_query_results); + if (ret_code != LTTNG_OK) { + goto end; + } + + /* Serialize the error query results. */ + ret_code = lttng_error_query_results_mi_serialize( + error_query_results, writer); + if (ret_code != LTTNG_OK) { + goto end; + } + } + +close_action_element: + /* Close action. */ + ret = mi_lttng_writer_close_element(writer); + if (ret) { + goto mi_error; + } + + ret_code = LTTNG_OK; + goto end; + +mi_error: + ret_code = LTTNG_ERR_MI_IO_FAIL; +end: + lttng_action_path_destroy(action_path); + lttng_error_query_results_destroy(error_query_results); + return ret_code; +} diff --git a/src/common/actions/list.c b/src/common/actions/list.c index 9b2d129b6..3713cbd76 100644 --- a/src/common/actions/list.c +++ b/src/common/actions/list.c @@ -7,10 +7,11 @@ #include #include -#include -#include #include #include +#include +#include +#include #include #include #include @@ -278,6 +279,86 @@ end: return action_status; } +LTTNG_HIDDEN +enum lttng_error_code lttng_action_list_mi_serialize( + const struct lttng_trigger *trigger, + const struct lttng_action *action, + struct mi_writer *writer, + const struct mi_lttng_error_query_callbacks + *error_query_callbacks, + struct lttng_dynamic_array *action_path_indexes) +{ + int ret; + struct lttng_action_list *action_list; + unsigned int i, count; + enum lttng_error_code ret_code; + + assert(action); + assert(IS_LIST_ACTION(action)); + assert(writer); + + /* Open action list. */ + ret = mi_lttng_writer_open_element( + writer, mi_lttng_element_action_list); + if (ret) { + goto mi_error; + } + + /* Serialize every action of the list. */ + action_list = action_list_from_action(action); + count = lttng_dynamic_pointer_array_get_count(&action_list->actions); + for (i = 0; i < count; i++) { + const struct lttng_action *child = + lttng_action_list_get_at_index(action, i); + const uint64_t index = (uint64_t) i; + + assert(child); + + /* + * Add the index to the action path. + * + * This index is replaced on every iteration to walk the action + * tree in-order and to re-use the dynamic array instead of + * copying it at every level. + */ + ret = lttng_dynamic_array_add_element( + action_path_indexes, &index); + if (ret) { + ret_code = LTTNG_ERR_NOMEM; + goto end; + } + + ret_code = lttng_action_mi_serialize(trigger, child, writer, + error_query_callbacks, action_path_indexes); + if (ret_code != LTTNG_OK) { + goto end; + } + + ret = lttng_dynamic_array_remove_element(action_path_indexes, + lttng_dynamic_array_get_count( + action_path_indexes) - + 1); + if (ret) { + ret_code = LTTNG_ERR_UNK; + goto end; + } + } + + /* Close action_list element. */ + ret = mi_lttng_writer_close_element(writer); + if (ret) { + goto mi_error; + } + + ret_code = LTTNG_OK; + goto end; + +mi_error: + ret_code = LTTNG_ERR_MI_IO_FAIL; +end: + return ret_code; +} + struct lttng_action *lttng_action_list_create(void) { struct lttng_action_list *action_list; @@ -291,12 +372,14 @@ struct lttng_action *lttng_action_list_create(void) action = &action_list->parent; + /* + * The mi for the list is handled at the lttng_action_mi level to ease + * action path management for error query. + */ lttng_action_init(action, LTTNG_ACTION_TYPE_LIST, - lttng_action_list_validate, - lttng_action_list_serialize, + lttng_action_list_validate, lttng_action_list_serialize, lttng_action_list_is_equal, lttng_action_list_destroy, - NULL, - lttng_action_list_add_error_query_results); + NULL, lttng_action_list_add_error_query_results, NULL); lttng_dynamic_pointer_array_init(&action_list->actions, destroy_lttng_action_list_element); diff --git a/src/common/actions/notify.c b/src/common/actions/notify.c index 646bffe9d..93726468e 100644 --- a/src/common/actions/notify.c +++ b/src/common/actions/notify.c @@ -8,9 +8,11 @@ #include #include #include +#include #include #include #include +#include #define IS_NOTIFY_ACTION(action) \ (lttng_action_get_type(action) == LTTNG_ACTION_TYPE_NOTIFY) @@ -82,6 +84,49 @@ lttng_action_notify_internal_get_rate_policy(const struct lttng_action *action) return _action->policy; } +static enum lttng_error_code lttng_action_notify_mi_serialize( + const struct lttng_action *action, struct mi_writer *writer) +{ + int ret; + enum lttng_action_status status; + enum lttng_error_code ret_code; + const struct lttng_rate_policy *policy = NULL; + + assert(action); + assert(IS_NOTIFY_ACTION(action)); + assert(writer); + + status = lttng_action_notify_get_rate_policy(action, &policy); + assert(status == LTTNG_ACTION_STATUS_OK); + assert(policy != NULL); + + /* Open action notify. */ + ret = mi_lttng_writer_open_element( + writer, mi_lttng_element_action_notify); + if (ret) { + goto mi_error; + } + + ret_code = lttng_rate_policy_mi_serialize(policy, writer); + if (ret_code != LTTNG_OK) { + goto end; + } + + /* Close action notify element. */ + ret = mi_lttng_writer_close_element(writer); + if (ret) { + goto mi_error; + } + + ret_code = LTTNG_OK; + goto end; + +mi_error: + ret_code = LTTNG_ERR_MI_IO_FAIL; +end: + return ret_code; +} + struct lttng_action *lttng_action_notify_create(void) { struct lttng_rate_policy *policy = NULL; @@ -104,7 +149,8 @@ struct lttng_action *lttng_action_notify_create(void) lttng_action_notify_is_equal, lttng_action_notify_destroy, lttng_action_notify_internal_get_rate_policy, - lttng_action_generic_add_error_query_results); + lttng_action_generic_add_error_query_results, + lttng_action_notify_mi_serialize); notify->policy = policy; policy = NULL; diff --git a/src/common/actions/rate-policy.c b/src/common/actions/rate-policy.c index 244fb70e3..8e05a3ecc 100644 --- a/src/common/actions/rate-policy.c +++ b/src/common/actions/rate-policy.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -35,6 +36,9 @@ typedef ssize_t (*rate_policy_create_from_payload_cb)( struct lttng_rate_policy **rate_policy); typedef struct lttng_rate_policy *(*rate_policy_copy_cb)( const struct lttng_rate_policy *source); +typedef enum lttng_error_code (*rate_policy_mi_serialize_cb)( + const struct lttng_rate_policy *rate_policy, + struct mi_writer *writer); struct lttng_rate_policy { enum lttng_rate_policy_type type; @@ -42,6 +46,7 @@ struct lttng_rate_policy { rate_policy_equal_cb equal; rate_policy_destroy_cb destroy; rate_policy_copy_cb copy; + rate_policy_mi_serialize_cb mi_serialize; }; struct lttng_rate_policy_every_n { @@ -73,7 +78,8 @@ static void lttng_rate_policy_init(struct lttng_rate_policy *rate_policy, rate_policy_serialize_cb serialize, rate_policy_equal_cb equal, rate_policy_destroy_cb destroy, - rate_policy_copy_cb copy); + rate_policy_copy_cb copy, + rate_policy_mi_serialize_cb mi); /* Forward declaration. Every n */ static bool lttng_rate_policy_every_n_should_execute( @@ -109,13 +115,15 @@ void lttng_rate_policy_init(struct lttng_rate_policy *rate_policy, rate_policy_serialize_cb serialize, rate_policy_equal_cb equal, rate_policy_destroy_cb destroy, - rate_policy_copy_cb copy) + rate_policy_copy_cb copy, + rate_policy_mi_serialize_cb mi) { rate_policy->type = type; rate_policy->serialize = serialize; rate_policy->equal = equal; rate_policy->destroy = destroy; rate_policy->copy = copy; + rate_policy->mi_serialize = mi; } void lttng_rate_policy_destroy(struct lttng_rate_policy *rate_policy) @@ -429,6 +437,51 @@ end: return copy; } +static enum lttng_error_code lttng_rate_policy_every_n_mi_serialize( + const struct lttng_rate_policy *rate_policy, + struct mi_writer *writer) +{ + int ret; + enum lttng_error_code ret_code; + const struct lttng_rate_policy_every_n *every_n_policy = NULL; + + assert(rate_policy); + assert(IS_EVERY_N_RATE_POLICY(rate_policy)); + assert(writer); + + every_n_policy = rate_policy_every_n_from_rate_policy_const( + rate_policy); + + /* Open rate_policy_every_n element. */ + ret = mi_lttng_writer_open_element( + writer, mi_lttng_element_rate_policy_every_n); + if (ret) { + goto mi_error; + } + + /* Interval. */ + ret = mi_lttng_writer_write_element_unsigned_int(writer, + mi_lttng_element_rate_policy_every_n_interval, + every_n_policy->interval); + if (ret) { + goto mi_error; + } + + /* Close rate_policy_every_n element. */ + ret = mi_lttng_writer_close_element(writer); + if (ret) { + goto mi_error; + } + + ret_code = LTTNG_OK; + goto end; + +mi_error: + ret_code = LTTNG_ERR_MI_IO_FAIL; +end: + return ret_code; +} + struct lttng_rate_policy *lttng_rate_policy_every_n_create(uint64_t interval) { struct lttng_rate_policy_every_n *policy = NULL; @@ -450,7 +503,8 @@ struct lttng_rate_policy *lttng_rate_policy_every_n_create(uint64_t interval) lttng_rate_policy_every_n_serialize, lttng_rate_policy_every_n_is_equal, lttng_rate_policy_every_n_destroy, - lttng_rate_policy_every_n_copy); + lttng_rate_policy_every_n_copy, + lttng_rate_policy_every_n_mi_serialize); policy->interval = interval; @@ -600,6 +654,51 @@ end: return copy; } +static enum lttng_error_code lttng_rate_policy_once_after_n_mi_serialize( + const struct lttng_rate_policy *rate_policy, + struct mi_writer *writer) +{ + int ret; + enum lttng_error_code ret_code; + const struct lttng_rate_policy_once_after_n *once_after_n_policy = NULL; + + assert(rate_policy); + assert(IS_ONCE_AFTER_N_RATE_POLICY(rate_policy)); + assert(writer); + + once_after_n_policy = rate_policy_once_after_n_from_rate_policy_const( + rate_policy); + + /* Open rate_policy_once_after_n. */ + ret = mi_lttng_writer_open_element( + writer, mi_lttng_element_rate_policy_once_after_n); + if (ret) { + goto mi_error; + } + + /* Threshold. */ + ret = mi_lttng_writer_write_element_unsigned_int(writer, + mi_lttng_element_rate_policy_once_after_n_threshold, + once_after_n_policy->threshold); + if (ret) { + goto mi_error; + } + + /* Close rate_policy_once_after_n element. */ + ret = mi_lttng_writer_close_element(writer); + if (ret) { + goto mi_error; + } + + ret_code = LTTNG_OK; + goto end; + +mi_error: + ret_code = LTTNG_ERR_MI_IO_FAIL; +end: + return ret_code; +} + struct lttng_rate_policy *lttng_rate_policy_once_after_n_create( uint64_t threshold) { @@ -621,7 +720,8 @@ struct lttng_rate_policy *lttng_rate_policy_once_after_n_create( lttng_rate_policy_once_after_n_serialize, lttng_rate_policy_once_after_n_is_equal, lttng_rate_policy_once_after_n_destroy, - lttng_rate_policy_once_after_n_copy); + lttng_rate_policy_once_after_n_copy, + lttng_rate_policy_once_after_n_mi_serialize); policy->threshold = threshold; @@ -681,3 +781,43 @@ static bool lttng_rate_policy_once_after_n_should_execute( return counter == once_after_n_policy->threshold; } + +LTTNG_HIDDEN +enum lttng_error_code lttng_rate_policy_mi_serialize( + const struct lttng_rate_policy *rate_policy, + struct mi_writer *writer) +{ + int ret; + enum lttng_error_code ret_code; + + assert(rate_policy); + assert(writer); + assert(rate_policy->mi_serialize); + + /* Open rate policy element. */ + ret = mi_lttng_writer_open_element( + writer, mi_lttng_element_rate_policy); + if (ret) { + goto mi_error; + } + + /* Serialize underlying rate policy. */ + ret_code = rate_policy->mi_serialize(rate_policy, writer); + if (ret_code != LTTNG_OK) { + goto end; + } + + /* Close rate policy element. */ + ret = mi_lttng_writer_close_element(writer); + if (ret) { + goto mi_error; + } + + ret_code = LTTNG_OK; + goto end; + +mi_error: + ret_code = LTTNG_ERR_MI_IO_FAIL; +end: + return ret_code; +} diff --git a/src/common/actions/rotate-session.c b/src/common/actions/rotate-session.c index c8dadd119..1eddacaea 100644 --- a/src/common/actions/rotate-session.c +++ b/src/common/actions/rotate-session.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -230,6 +231,62 @@ end: return consumed_len; } +static enum lttng_error_code lttng_action_rotate_session_mi_serialize( + const struct lttng_action *action, struct mi_writer *writer) +{ + int ret; + enum lttng_error_code ret_code; + enum lttng_action_status status; + const char *session_name = NULL; + const struct lttng_rate_policy *policy = NULL; + + assert(action); + assert(IS_ROTATE_SESSION_ACTION(action)); + + status = lttng_action_rotate_session_get_session_name( + action, &session_name); + assert(status == LTTNG_ACTION_STATUS_OK); + assert(session_name != NULL); + + status = lttng_action_notify_get_rate_policy(action, &policy); + assert(status == LTTNG_ACTION_STATUS_OK); + assert(policy != NULL); + + /* Open action rotate session element. */ + ret = mi_lttng_writer_open_element( + writer, mi_lttng_element_action_rotate_session); + if (ret) { + goto mi_error; + } + + /* Session name. */ + ret = mi_lttng_writer_write_element_string( + writer, mi_lttng_element_session_name, session_name); + if (ret) { + goto mi_error; + } + + /* Rate policy. */ + ret_code = lttng_rate_policy_mi_serialize(policy, writer); + if (ret_code != LTTNG_OK) { + goto end; + } + + /* Close action rotate session element. */ + ret = mi_lttng_writer_close_element(writer); + if (ret) { + goto mi_error; + } + + ret_code = LTTNG_OK; + goto end; + +mi_error: + ret_code = LTTNG_ERR_MI_IO_FAIL; +end: + return ret_code; +} + struct lttng_action *lttng_action_rotate_session_create(void) { struct lttng_action *action = NULL; @@ -253,7 +310,8 @@ struct lttng_action *lttng_action_rotate_session_create(void) lttng_action_rotate_session_is_equal, lttng_action_rotate_session_destroy, lttng_action_rotate_session_internal_get_rate_policy, - lttng_action_generic_add_error_query_results); + lttng_action_generic_add_error_query_results, + lttng_action_rotate_session_mi_serialize); status = lttng_action_rotate_session_set_rate_policy(action, policy); if (status != LTTNG_ACTION_STATUS_OK) { diff --git a/src/common/actions/snapshot-session.c b/src/common/actions/snapshot-session.c index 776615003..6c765edea 100644 --- a/src/common/actions/snapshot-session.c +++ b/src/common/actions/snapshot-session.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -373,6 +374,76 @@ end: return consumed_len; } +static enum lttng_error_code lttng_action_snapshot_session_mi_serialize( + const struct lttng_action *action, struct mi_writer *writer) +{ + int ret; + enum lttng_error_code ret_code; + enum lttng_action_status status; + const char *session_name = NULL; + const struct lttng_snapshot_output *output = NULL; + const struct lttng_rate_policy *policy = NULL; + + assert(action); + assert(IS_SNAPSHOT_SESSION_ACTION(action)); + + status = lttng_action_snapshot_session_get_session_name( + action, &session_name); + assert(status == LTTNG_ACTION_STATUS_OK); + assert(session_name != NULL); + + status = lttng_action_snapshot_session_get_rate_policy(action, &policy); + assert(status == LTTNG_ACTION_STATUS_OK); + assert(policy != NULL); + + /* Open action snapshot session element. */ + ret = mi_lttng_writer_open_element( + writer, mi_lttng_element_action_snapshot_session); + if (ret) { + goto mi_error; + } + + /* Session name. */ + ret = mi_lttng_writer_write_element_string( + writer, mi_lttng_element_session_name, session_name); + if (ret) { + goto mi_error; + } + + /* Output if any. */ + status = lttng_action_snapshot_session_get_output(action, &output); + if (status == LTTNG_ACTION_STATUS_OK) { + assert(output != NULL); + ret_code = lttng_snapshot_output_mi_serialize(output, writer); + if (ret_code != LTTNG_OK) { + goto end; + } + } else if (status != LTTNG_ACTION_STATUS_UNSET) { + /* This should not happen at this point. */ + abort(); + } + + /* Rate policy. */ + ret_code = lttng_rate_policy_mi_serialize(policy, writer); + if (ret_code != LTTNG_OK) { + goto end; + } + + /* Close action_snapshot_session element. */ + ret = mi_lttng_writer_close_element(writer); + if (ret) { + goto mi_error; + } + + ret_code = LTTNG_OK; + goto end; + +mi_error: + ret_code = LTTNG_ERR_MI_IO_FAIL; +end: + return ret_code; +} + struct lttng_action *lttng_action_snapshot_session_create(void) { struct lttng_action *action = NULL; @@ -396,7 +467,8 @@ struct lttng_action *lttng_action_snapshot_session_create(void) lttng_action_snapshot_session_is_equal, lttng_action_snapshot_session_destroy, lttng_action_snapshot_session_internal_get_rate_policy, - lttng_action_generic_add_error_query_results); + lttng_action_generic_add_error_query_results, + lttng_action_snapshot_session_mi_serialize); status = lttng_action_snapshot_session_set_rate_policy(action, policy); if (status != LTTNG_ACTION_STATUS_OK) { diff --git a/src/common/actions/start-session.c b/src/common/actions/start-session.c index e5cbac726..792098258 100644 --- a/src/common/actions/start-session.c +++ b/src/common/actions/start-session.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -233,6 +234,62 @@ end: return consumed_len; } +static enum lttng_error_code lttng_action_start_session_mi_serialize( + const struct lttng_action *action, struct mi_writer *writer) +{ + int ret; + enum lttng_error_code ret_code; + enum lttng_action_status status; + const char *session_name = NULL; + const struct lttng_rate_policy *policy = NULL; + + assert(action); + assert(IS_START_SESSION_ACTION(action)); + + status = lttng_action_start_session_get_session_name( + action, &session_name); + assert(status == LTTNG_ACTION_STATUS_OK); + assert(session_name != NULL); + + status = lttng_action_start_session_get_rate_policy(action, &policy); + assert(status == LTTNG_ACTION_STATUS_OK); + assert(policy != NULL); + + /* Open action start session element. */ + ret = mi_lttng_writer_open_element( + writer, mi_lttng_element_action_start_session); + if (ret) { + goto mi_error; + } + + /* Session name. */ + ret = mi_lttng_writer_write_element_string( + writer, mi_lttng_element_session_name, session_name); + if (ret) { + goto mi_error; + } + + /* Rate policy. */ + ret_code = lttng_rate_policy_mi_serialize(policy, writer); + if (ret_code != LTTNG_OK) { + goto end; + } + + /* Close action start session element. */ + ret = mi_lttng_writer_close_element(writer); + if (ret) { + goto mi_error; + } + + ret_code = LTTNG_OK; + goto end; + +mi_error: + ret_code = LTTNG_ERR_MI_IO_FAIL; +end: + return ret_code; +} + struct lttng_action *lttng_action_start_session_create(void) { struct lttng_action *action = NULL; @@ -256,7 +313,8 @@ struct lttng_action *lttng_action_start_session_create(void) lttng_action_start_session_is_equal, lttng_action_start_session_destroy, lttng_action_start_session_internal_get_rate_policy, - lttng_action_generic_add_error_query_results); + lttng_action_generic_add_error_query_results, + lttng_action_start_session_mi_serialize); status = lttng_action_start_session_set_rate_policy(action, policy); if (status != LTTNG_ACTION_STATUS_OK) { diff --git a/src/common/actions/stop-session.c b/src/common/actions/stop-session.c index ec167d1ed..39d174277 100644 --- a/src/common/actions/stop-session.c +++ b/src/common/actions/stop-session.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -233,6 +234,62 @@ end: return consumed_len; } +static enum lttng_error_code lttng_action_stop_session_mi_serialize( + const struct lttng_action *action, struct mi_writer *writer) +{ + int ret; + enum lttng_error_code ret_code; + enum lttng_action_status status; + const char *session_name = NULL; + const struct lttng_rate_policy *policy = NULL; + + assert(action); + assert(IS_STOP_SESSION_ACTION(action)); + + status = lttng_action_stop_session_get_session_name( + action, &session_name); + assert(status == LTTNG_ACTION_STATUS_OK); + assert(session_name != NULL); + + status = lttng_action_stop_session_get_rate_policy(action, &policy); + assert(status == LTTNG_ACTION_STATUS_OK); + assert(policy != NULL); + + /* Open action stop session. */ + ret = mi_lttng_writer_open_element( + writer, mi_lttng_element_action_start_session); + if (ret) { + goto mi_error; + } + + /* Session name. */ + ret = mi_lttng_writer_write_element_string( + writer, mi_lttng_element_session_name, session_name); + if (ret) { + goto mi_error; + } + + /* Rate policy. */ + ret_code = lttng_rate_policy_mi_serialize(policy, writer); + if (ret_code != LTTNG_OK) { + goto end; + } + + /* Close action stop session element. */ + ret = mi_lttng_writer_close_element(writer); + if (ret) { + goto mi_error; + } + + ret_code = LTTNG_OK; + goto end; + +mi_error: + ret_code = LTTNG_ERR_MI_IO_FAIL; +end: + return ret_code; +} + struct lttng_action *lttng_action_stop_session_create(void) { struct lttng_action *action = NULL; @@ -256,7 +313,8 @@ struct lttng_action *lttng_action_stop_session_create(void) lttng_action_stop_session_is_equal, lttng_action_stop_session_destroy, lttng_action_stop_session_internal_get_rate_policy, - lttng_action_generic_add_error_query_results); + lttng_action_generic_add_error_query_results, + lttng_action_stop_session_mi_serialize); status = lttng_action_stop_session_set_rate_policy(action, policy); if (status != LTTNG_ACTION_STATUS_OK) { diff --git a/src/common/conditions/buffer-usage.c b/src/common/conditions/buffer-usage.c index a97f6d59f..0b9cfcd8e 100644 --- a/src/common/conditions/buffer-usage.c +++ b/src/common/conditions/buffer-usage.c @@ -5,13 +5,14 @@ * */ -#include -#include -#include -#include #include -#include +#include +#include +#include #include +#include +#include +#include #include #define IS_USAGE_CONDITION(condition) ( \ @@ -193,6 +194,128 @@ end: return is_equal; } +static enum lttng_error_code lttng_condition_buffer_usage_mi_serialize( + const struct lttng_condition *condition, + struct mi_writer *writer) +{ + int ret; + enum lttng_error_code ret_code; + enum lttng_condition_status status; + const char *session_name = NULL, *channel_name = NULL; + enum lttng_domain_type domain_type; + bool is_threshold_bytes = false; + double threshold_ratio; + uint64_t threshold_bytes; + const char *condition_type_str = NULL; + + assert(condition); + assert(IS_USAGE_CONDITION(condition)); + + status = lttng_condition_buffer_usage_get_session_name( + condition, &session_name); + assert(status == LTTNG_CONDITION_STATUS_OK); + assert(session_name); + + status = lttng_condition_buffer_usage_get_channel_name( + condition, &channel_name); + assert(status == LTTNG_CONDITION_STATUS_OK); + assert(session_name); + + status = lttng_condition_buffer_usage_get_domain_type( + condition, &domain_type); + assert(status == LTTNG_CONDITION_STATUS_OK); + + status = lttng_condition_buffer_usage_get_threshold( + condition, &threshold_bytes); + if (status == LTTNG_CONDITION_STATUS_OK) { + is_threshold_bytes = true; + } else if (status != LTTNG_CONDITION_STATUS_UNSET) { + /* Unexpected at this stage. */ + ret_code = LTTNG_ERR_INVALID; + goto end; + } + + if (!is_threshold_bytes) { + status = lttng_condition_buffer_usage_get_threshold_ratio( + condition, &threshold_ratio); + assert(status == LTTNG_CONDITION_STATUS_OK); + } + + switch (lttng_condition_get_type(condition)) { + case LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH: + condition_type_str = + mi_lttng_element_condition_buffer_usage_high; + break; + case LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW: + condition_type_str = + mi_lttng_element_condition_buffer_usage_low; + break; + default: + abort(); + break; + } + + /* Open the sub type condition element. */ + ret = mi_lttng_writer_open_element(writer, condition_type_str); + if (ret) { + goto mi_error; + } + + /* Session name. */ + ret = mi_lttng_writer_write_element_string( + writer, mi_lttng_element_session_name, session_name); + if (ret) { + goto mi_error; + } + + /* Channel name. */ + ret = mi_lttng_writer_write_element_string(writer, + mi_lttng_element_condition_channel_name, channel_name); + if (ret) { + goto mi_error; + } + + /* Domain. */ + ret = mi_lttng_writer_write_element_string(writer, + config_element_domain, + mi_lttng_domaintype_string(domain_type)); + if (ret) { + goto mi_error; + } + + if (is_threshold_bytes) { + /* Usage in bytes. */ + ret = mi_lttng_writer_write_element_unsigned_int(writer, + mi_lttng_element_condition_threshold_bytes, + threshold_bytes); + if (ret) { + goto mi_error; + } + } else { + /* Ratio. */ + ret = mi_lttng_writer_write_element_double(writer, + mi_lttng_element_condition_threshold_ratio, + threshold_ratio); + if (ret) { + goto mi_error; + } + } + + /* Closing sub type condition element. */ + ret = mi_lttng_writer_close_element(writer); + if (ret) { + goto mi_error; + } + + ret_code = LTTNG_OK; + goto end; + +mi_error: + ret_code = LTTNG_ERR_MI_IO_FAIL; +end: + return ret_code; +} + static struct lttng_condition *lttng_condition_buffer_usage_create( enum lttng_condition_type type) @@ -209,6 +332,7 @@ struct lttng_condition *lttng_condition_buffer_usage_create( condition->parent.serialize = lttng_condition_buffer_usage_serialize; condition->parent.equal = lttng_condition_buffer_usage_is_equal; condition->parent.destroy = lttng_condition_buffer_usage_destroy; + condition->parent.mi_serialize = lttng_condition_buffer_usage_mi_serialize; return &condition->parent; } diff --git a/src/common/conditions/condition.c b/src/common/conditions/condition.c index 4b290cdb4..2a21f8190 100644 --- a/src/common/conditions/condition.c +++ b/src/common/conditions/condition.c @@ -5,17 +5,19 @@ * */ -#include +#include +#include +#include +#include +#include +#include #include +#include #include #include #include -#include -#include -#include -#include +#include #include -#include enum lttng_condition_type lttng_condition_get_type( const struct lttng_condition *condition) @@ -238,3 +240,61 @@ const char *lttng_condition_type_str(enum lttng_condition_type type) return "???"; } } + +LTTNG_HIDDEN +enum lttng_error_code lttng_condition_mi_serialize( + const struct lttng_trigger *trigger, + const struct lttng_condition *condition, + struct mi_writer *writer, + const struct mi_lttng_error_query_callbacks *error_query_callbacks) +{ + int ret; + enum lttng_error_code ret_code; + struct lttng_error_query_results *error_query_results = NULL; + + assert(condition); + assert(writer); + assert(condition->mi_serialize); + + /* Open condition element. */ + ret = mi_lttng_writer_open_element(writer, mi_lttng_element_condition); + if (ret) { + goto mi_error; + } + + /* Serialize underlying condition. */ + ret_code = condition->mi_serialize(condition, writer); + if (ret_code != LTTNG_OK) { + goto end; + } + + /* Serialize error query results for the action. */ + if (error_query_callbacks && error_query_callbacks->action_cb) { + ret_code = error_query_callbacks->condition_cb( + trigger, &error_query_results); + if (ret_code != LTTNG_OK) { + goto end; + } + + ret_code = lttng_error_query_results_mi_serialize( + error_query_results, writer); + if (ret_code != LTTNG_OK) { + goto end; + } + } + + /* Close condition element. */ + ret = mi_lttng_writer_close_element(writer); + if (ret) { + goto mi_error; + } + + ret_code = LTTNG_OK; + goto end; + +mi_error: + ret_code = LTTNG_ERR_MI_IO_FAIL; +end: + lttng_error_query_results_destroy(error_query_results); + return ret_code; +} diff --git a/src/common/conditions/event-rule-matches.c b/src/common/conditions/event-rule-matches.c index 259173a63..21963d1ae 100644 --- a/src/common/conditions/event-rule-matches.c +++ b/src/common/conditions/event-rule-matches.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -433,6 +434,81 @@ void destroy_capture_descriptor(void *ptr) free(desc); } +static enum lttng_error_code lttng_condition_event_rule_matches_mi_serialize( + const struct lttng_condition *condition, + struct mi_writer *writer) +{ + int ret; + enum lttng_error_code ret_code; + enum lttng_condition_status status; + const struct lttng_event_rule *rule = NULL; + unsigned int capture_descriptor_count, i; + + assert(condition); + assert(writer); + assert(IS_EVENT_RULE_MATCHES_CONDITION(condition)); + + status = lttng_condition_event_rule_matches_get_rule(condition, &rule); + assert(status == LTTNG_CONDITION_STATUS_OK); + assert(rule != NULL); + + status = lttng_condition_event_rule_matches_get_capture_descriptor_count( + condition, &capture_descriptor_count); + assert(status == LTTNG_CONDITION_STATUS_OK); + + /* Open condition event rule matches element. */ + ret = mi_lttng_writer_open_element( + writer, mi_lttng_element_condition_event_rule_matches); + if (ret) { + goto mi_error; + } + + /* Serialize the event rule. */ + ret_code = lttng_event_rule_mi_serialize(rule, writer); + if (ret_code != LTTNG_OK) { + goto end; + } + + /* Open the capture descriptors element. */ + ret = mi_lttng_writer_open_element( + writer, mi_lttng_element_capture_descriptors); + if (ret) { + goto mi_error; + } + + for (i = 0; i < capture_descriptor_count; i++) { + const struct lttng_event_expr *descriptor = NULL; + + descriptor = lttng_condition_event_rule_matches_get_capture_descriptor_at_index( + condition, i); + assert(descriptor); + + ret_code = lttng_event_expr_mi_serialize(descriptor, writer); + if (ret_code != LTTNG_OK) { + goto end; + } + } + + /* Close capture descriptors element. */ + ret = mi_lttng_writer_close_element(writer); + if (ret) { + goto mi_error; + } + + /* Close condition_event_rule_matches. */ + ret = mi_lttng_writer_close_element(writer); + if (ret) { + goto mi_error; + } + ret_code = LTTNG_OK; + goto end; + +mi_error: + ret_code = LTTNG_ERR_MI_IO_FAIL; +end: + return ret_code; +} + struct lttng_condition *lttng_condition_event_rule_matches_create( struct lttng_event_rule *rule) { @@ -456,6 +532,7 @@ struct lttng_condition *lttng_condition_event_rule_matches_create( lttng_condition_event_rule_matches_serialize, condition->parent.equal = lttng_condition_event_rule_matches_is_equal, condition->parent.destroy = lttng_condition_event_rule_matches_destroy, + condition->parent.mi_serialize = lttng_condition_event_rule_matches_mi_serialize, lttng_event_rule_get(rule); condition->rule = rule; diff --git a/src/common/conditions/session-consumed-size.c b/src/common/conditions/session-consumed-size.c index e147d1e5f..c366a0efc 100644 --- a/src/common/conditions/session-consumed-size.c +++ b/src/common/conditions/session-consumed-size.c @@ -5,14 +5,15 @@ * */ +#include +#include +#include +#include +#include #include #include #include -#include -#include -#include #include -#include #include #define IS_CONSUMED_SIZE_CONDITION(condition) ( \ @@ -138,6 +139,67 @@ end: return is_equal; } +static +enum lttng_error_code lttng_condition_session_consumed_size_mi_serialize( + const struct lttng_condition *condition, + struct mi_writer *writer) +{ + int ret; + enum lttng_error_code ret_code; + enum lttng_condition_status status; + const char *session_name = NULL; + uint64_t threshold_bytes; + + assert(condition); + assert(writer); + assert(IS_CONSUMED_SIZE_CONDITION(condition)); + + status = lttng_condition_session_consumed_size_get_session_name( + condition, &session_name); + assert(status == LTTNG_CONDITION_STATUS_OK); + assert(session_name); + + status = lttng_condition_session_consumed_size_get_threshold( + condition, &threshold_bytes); + assert(status == LTTNG_CONDITION_STATUS_OK); + + /* Open condition session consumed size element. */ + ret = mi_lttng_writer_open_element(writer, + mi_lttng_element_condition_session_consumed_size); + if (ret) { + goto mi_error; + } + + /* Session name. */ + ret = mi_lttng_writer_write_element_string( + writer, mi_lttng_element_session_name, session_name); + if (ret) { + goto mi_error; + } + + /* Threshold in bytes. */ + ret = mi_lttng_writer_write_element_unsigned_int(writer, + mi_lttng_element_condition_threshold_bytes, + threshold_bytes); + if (ret) { + goto mi_error; + } + + /* Close condition session consumed size element. */ + ret = mi_lttng_writer_close_element(writer); + if (ret) { + goto mi_error; + } + + ret_code = LTTNG_OK; + goto end; + +mi_error: + ret_code = LTTNG_ERR_MI_IO_FAIL; +end: + return ret_code; +} + struct lttng_condition *lttng_condition_session_consumed_size_create(void) { struct lttng_condition_session_consumed_size *condition; @@ -152,6 +214,7 @@ struct lttng_condition *lttng_condition_session_consumed_size_create(void) condition->parent.serialize = lttng_condition_session_consumed_size_serialize; condition->parent.equal = lttng_condition_session_consumed_size_is_equal; condition->parent.destroy = lttng_condition_session_consumed_size_destroy; + condition->parent.mi_serialize = lttng_condition_session_consumed_size_mi_serialize; return &condition->parent; } diff --git a/src/common/conditions/session-rotation.c b/src/common/conditions/session-rotation.c index 7df5ebab0..1be0f0ad2 100644 --- a/src/common/conditions/session-rotation.c +++ b/src/common/conditions/session-rotation.c @@ -5,12 +5,13 @@ * */ +#include +#include +#include +#include #include #include #include -#include -#include -#include #include static @@ -27,6 +28,11 @@ static void lttng_condition_session_rotation_destroy( struct lttng_condition *condition); +static +enum lttng_error_code lttng_condition_session_rotation_mi_serialize( + const struct lttng_condition *condition, + struct mi_writer *writer); + static const struct lttng_condition rotation_condition_template = { /* .type omitted; shall be set on creation. */ @@ -34,6 +40,7 @@ struct lttng_condition rotation_condition_template = { .serialize = lttng_condition_session_rotation_serialize, .equal = lttng_condition_session_rotation_is_equal, .destroy = lttng_condition_session_rotation_destroy, + .mi_serialize = lttng_condition_session_rotation_mi_serialize, }; static @@ -586,3 +593,65 @@ lttng_evaluation_session_rotation_completed_get_location( end: return status; } + +static +enum lttng_error_code lttng_condition_session_rotation_mi_serialize( + const struct lttng_condition *condition, + struct mi_writer *writer) +{ + int ret; + enum lttng_error_code ret_code; + enum lttng_condition_status status; + const char *session_name = NULL; + const char *type_element_str = NULL; + + assert(condition); + assert(writer); + assert(is_rotation_condition(condition)); + + switch (lttng_condition_get_type(condition)) { + case LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED: + type_element_str = + mi_lttng_element_condition_session_rotation_completed; + break; + case LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING: + type_element_str = + mi_lttng_element_condition_session_rotation_ongoing; + break; + default: + abort(); + break; + } + + status = lttng_condition_session_rotation_get_session_name( + condition, &session_name); + assert(status == LTTNG_CONDITION_STATUS_OK); + assert(session_name); + + /* Open condition session rotation_* element. */ + ret = mi_lttng_writer_open_element(writer, type_element_str); + if (ret) { + goto mi_error; + } + + /* Session name. */ + ret = mi_lttng_writer_write_element_string( + writer, mi_lttng_element_session_name, session_name); + if (ret) { + goto mi_error; + } + + /* Close condition session rotation element. */ + ret = mi_lttng_writer_close_element(writer); + if (ret) { + goto mi_error; + } + + ret_code = LTTNG_OK; + goto end; + +mi_error: + ret_code = LTTNG_ERR_MI_IO_FAIL; +end: + return ret_code; +} diff --git a/src/common/error-query.c b/src/common/error-query.c index 7b0872d90..2eb1c9717 100644 --- a/src/common/error-query.c +++ b/src/common/error-query.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -85,6 +86,15 @@ struct lttng_error_query_results { struct lttng_dynamic_pointer_array results; }; +static +enum lttng_error_code lttng_error_query_result_mi_serialize( + const struct lttng_error_query_result *result, + struct mi_writer *writer); + +static +enum lttng_error_code lttng_error_query_result_counter_mi_serialize( + const struct lttng_error_query_result *result, + struct mi_writer *writer); struct lttng_error_query *lttng_error_query_trigger_create( const struct lttng_trigger *trigger) @@ -1049,3 +1059,176 @@ enum lttng_error_query_result_status lttng_error_query_result_counter_get_value( end: return status; } + +static +enum lttng_error_code lttng_error_query_result_counter_mi_serialize( + const struct lttng_error_query_result *result, + struct mi_writer *writer) +{ + int ret; + enum lttng_error_code ret_code; + enum lttng_error_query_result_status status; + uint64_t value; + + assert(result); + assert(writer); + + status = lttng_error_query_result_counter_get_value(result, &value); + assert(status == LTTNG_ERROR_QUERY_RESULT_STATUS_OK); + + /* Open error query result counter element. */ + ret = mi_lttng_writer_open_element( + writer, mi_lttng_element_error_query_result_counter); + if (ret) { + goto mi_error; + } + + /* Value. */ + ret = mi_lttng_writer_write_element_unsigned_int(writer, + mi_lttng_element_error_query_result_counter_value, + value); + if (ret) { + goto mi_error; + } + + /* Close error query result counter element. */ + ret = mi_lttng_writer_close_element(writer); + if (ret) { + goto mi_error; + } + + ret_code = LTTNG_OK; + goto end; + +mi_error: + ret_code = LTTNG_ERR_MI_IO_FAIL; +end: + return ret_code; +} + +static +enum lttng_error_code lttng_error_query_result_mi_serialize( + const struct lttng_error_query_result *result, + struct mi_writer *writer) +{ + int ret; + enum lttng_error_code ret_code; + enum lttng_error_query_result_status result_status; + enum lttng_error_query_result_type type; + const char *name = NULL; + const char *description = NULL; + + assert(result); + assert(writer); + + type = lttng_error_query_result_get_type(result); + + result_status = lttng_error_query_result_get_name(result, &name); + assert(result_status == LTTNG_ERROR_QUERY_RESULT_STATUS_OK); + + result_status = lttng_error_query_result_get_description( + result, &description); + assert(result_status == LTTNG_ERROR_QUERY_RESULT_STATUS_OK); + + /* Open error query result element. */ + ret = mi_lttng_writer_open_element( + writer, mi_lttng_element_error_query_result); + if (ret) { + goto mi_error; + } + + /* Name. */ + ret = mi_lttng_writer_write_element_string( + writer, mi_lttng_element_error_query_result_name, name); + if (ret) { + goto mi_error; + } + + /* Description. */ + ret = mi_lttng_writer_write_element_string(writer, + mi_lttng_element_error_query_result_description, + description); + if (ret) { + goto mi_error; + } + + /* Serialize the result according to its sub type. */ + switch (type) { + case LTTNG_ERROR_QUERY_RESULT_TYPE_COUNTER: + ret_code = lttng_error_query_result_counter_mi_serialize( + result, writer); + break; + default: + abort(); + } + + if (ret_code != LTTNG_OK) { + goto end; + } + + /* Close error query result element. */ + ret = mi_lttng_writer_close_element(writer); + if (ret) { + goto mi_error; + } + + ret_code = LTTNG_OK; + goto end; + +mi_error: + ret_code = LTTNG_ERR_MI_IO_FAIL; +end: + return ret_code; +} + +LTTNG_HIDDEN +enum lttng_error_code lttng_error_query_results_mi_serialize( + const struct lttng_error_query_results *results, + struct mi_writer *writer) +{ + int ret; + enum lttng_error_code ret_code; + unsigned int i, count; + enum lttng_error_query_results_status results_status; + + assert(results); + assert(writer); + + /* Open error query results element. */ + ret = mi_lttng_writer_open_element( + writer, mi_lttng_element_error_query_results); + if (ret) { + goto mi_error; + } + + results_status = lttng_error_query_results_get_count(results, &count); + assert(results_status == LTTNG_ERROR_QUERY_RESULTS_STATUS_OK); + + for (i = 0; i < count; i++) { + const struct lttng_error_query_result *result; + + results_status = lttng_error_query_results_get_result( + results, &result, i); + assert(results_status == LTTNG_ERROR_QUERY_RESULTS_STATUS_OK); + + /* A single error query result. */ + ret_code = lttng_error_query_result_mi_serialize(result, writer); + if (ret_code != LTTNG_OK) { + goto end; + } + } + + /* Close error query results. */ + ret = mi_lttng_writer_close_element(writer); + if (ret) { + goto mi_error; + } + + ret_code = LTTNG_OK; + goto end; + +mi_error: + ret_code = LTTNG_ERR_MI_IO_FAIL; +end: + return ret_code; +} diff --git a/src/common/event-expr/event-expr.c b/src/common/event-expr/event-expr.c index 1351a347f..c3709c882 100644 --- a/src/common/event-expr/event-expr.c +++ b/src/common/event-expr/event-expr.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -657,3 +658,267 @@ end: return status; } + +static +enum lttng_error_code lttng_event_expr_event_payload_field_mi_serialize( + const struct lttng_event_expr *expression, + struct mi_writer *writer) +{ + int ret; + enum lttng_error_code ret_code; + const char *name = NULL; + + assert(expression); + assert(writer); + assert(expression->type == LTTNG_EVENT_EXPR_TYPE_EVENT_PAYLOAD_FIELD); + + name = lttng_event_expr_event_payload_field_get_name(expression); + assert(name); + + /* Open event expr payload field element. */ + ret = mi_lttng_writer_open_element( + writer, mi_lttng_element_event_expr_payload_field); + if (ret) { + goto mi_error; + } + + /* Name. */ + ret = mi_lttng_writer_write_element_string( + writer, config_element_name, name); + if (ret) { + goto mi_error; + } + + /* Close event expr payload field element. */ + ret = mi_lttng_writer_close_element(writer); + if (ret) { + goto mi_error; + } + + ret_code = LTTNG_OK; + goto end; + +mi_error: + ret_code = LTTNG_ERR_MI_IO_FAIL; +end: + return ret_code; +} + +static +enum lttng_error_code lttng_event_expr_channel_context_field_mi_serialize( + const struct lttng_event_expr *expression, + struct mi_writer *writer) +{ + int ret; + enum lttng_error_code ret_code; + const char *name = NULL; + + assert(expression); + assert(writer); + assert(expression->type == LTTNG_EVENT_EXPR_TYPE_CHANNEL_CONTEXT_FIELD); + + name = lttng_event_expr_channel_context_field_get_name(expression); + assert(name); + + /* Open event expr channel context field element. */ + ret = mi_lttng_writer_open_element(writer, + mi_lttng_element_event_expr_channel_context_field); + if (ret) { + goto mi_error; + } + + /* Name. */ + ret = mi_lttng_writer_write_element_string( + writer, config_element_name, name); + if (ret) { + goto mi_error; + } + + /* Close event expr channel context field element. */ + ret = mi_lttng_writer_close_element(writer); + if (ret) { + goto mi_error; + } + + ret_code = LTTNG_OK; + goto end; + +mi_error: + ret_code = LTTNG_ERR_MI_IO_FAIL; +end: + return ret_code; +} + +static +enum lttng_error_code lttng_event_expr_app_specific_context_field_mi_serialize( + const struct lttng_event_expr *expression, + struct mi_writer *writer) +{ + int ret; + enum lttng_error_code ret_code; + const char *provider_name = NULL; + const char *type_name = NULL; + + assert(expression); + assert(writer); + assert(expression->type == + LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD); + + provider_name = lttng_event_expr_app_specific_context_field_get_provider_name( + expression); + assert(provider_name); + + type_name = lttng_event_expr_app_specific_context_field_get_type_name( + expression); + assert(provider_name); + + /* Open event expr app specific context field element. */ + ret = mi_lttng_writer_open_element(writer, + mi_lttng_element_event_expr_app_specific_context_field); + if (ret) { + goto mi_error; + } + + /* Provider name. */ + ret = mi_lttng_writer_write_element_string(writer, + mi_lttng_element_event_expr_provider_name, + provider_name); + if (ret) { + goto mi_error; + } + + /* Type name. */ + ret = mi_lttng_writer_write_element_string(writer, + mi_lttng_element_event_expr_type_name, type_name); + if (ret) { + goto mi_error; + } + + /* Close event expr app specific context field element. */ + ret = mi_lttng_writer_close_element(writer); + if (ret) { + goto mi_error; + } + + ret_code = LTTNG_OK; + goto end; + +mi_error: + ret_code = LTTNG_ERR_MI_IO_FAIL; +end: + return ret_code; +} + +static +enum lttng_error_code lttng_event_expr_array_field_element_mi_serialize( + const struct lttng_event_expr *expression, + struct mi_writer *writer) +{ + int ret; + enum lttng_error_code ret_code; + enum lttng_event_expr_status status; + const struct lttng_event_expr *parent_expr = NULL; + unsigned int index; + + assert(expression); + assert(writer); + assert(expression->type == LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT); + + status = lttng_event_expr_array_field_element_get_index( + expression, &index); + assert(status == LTTNG_EVENT_EXPR_STATUS_OK); + + parent_expr = lttng_event_expr_array_field_element_get_parent_expr( + expression); + assert(parent_expr != NULL); + + /* Open event expr array field element. */ + ret = mi_lttng_writer_open_element(writer, + mi_lttng_element_event_expr_array_field_element); + if (ret) { + goto mi_error; + } + + /* Index. */ + ret = mi_lttng_writer_write_element_unsigned_int( + writer, mi_lttng_element_event_expr_index, index); + if (ret) { + goto mi_error; + } + + /* Parent expression. */ + ret_code = lttng_event_expr_mi_serialize(parent_expr, writer); + if (ret_code != LTTNG_OK) { + goto end; + } + + /* Close event expr array field element. */ + ret = mi_lttng_writer_close_element(writer); + if (ret) { + goto mi_error; + } + + ret_code = LTTNG_OK; + goto end; + +mi_error: + ret_code = LTTNG_ERR_MI_IO_FAIL; +end: + return ret_code; +} + +LTTNG_HIDDEN +enum lttng_error_code lttng_event_expr_mi_serialize( + const struct lttng_event_expr *expression, + struct mi_writer *writer) +{ + int ret; + enum lttng_error_code ret_code; + + assert(expression); + assert(writer); + + ret = mi_lttng_writer_open_element(writer, mi_lttng_element_event_expr); + if (ret) { + goto mi_error; + } + + switch (expression->type) { + case LTTNG_EVENT_EXPR_TYPE_EVENT_PAYLOAD_FIELD: + ret_code = lttng_event_expr_event_payload_field_mi_serialize( + expression, writer); + break; + case LTTNG_EVENT_EXPR_TYPE_CHANNEL_CONTEXT_FIELD: + ret_code = lttng_event_expr_channel_context_field_mi_serialize( + expression, writer); + break; + case LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD: + ret_code = lttng_event_expr_app_specific_context_field_mi_serialize( + expression, writer); + break; + case LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT: + ret_code = lttng_event_expr_array_field_element_mi_serialize( + expression, writer); + break; + default: + abort(); + } + + if (ret_code != LTTNG_OK) { + goto end; + } + + ret = mi_lttng_writer_close_element(writer); + if (ret) { + goto mi_error; + } + + ret_code = LTTNG_OK; + goto end; + +mi_error: + ret_code = LTTNG_ERR_MI_IO_FAIL; + +end: + return ret_code; +} diff --git a/src/common/event-rule/event-rule.c b/src/common/event-rule/event-rule.c index b4225f867..2a84a1328 100644 --- a/src/common/event-rule/event-rule.c +++ b/src/common/event-rule/event-rule.c @@ -8,19 +8,20 @@ #include #include -#include -#include -#include #include #include +#include +#include +#include +#include #include +#include #include #include -#include -#include -#include #include #include +#include +#include #include #include @@ -361,3 +362,41 @@ unsigned long lttng_event_rule_hash(const struct lttng_event_rule *rule) assert(rule->hash); return rule->hash(rule); } + +LTTNG_HIDDEN +enum lttng_error_code lttng_event_rule_mi_serialize( + const struct lttng_event_rule *rule, struct mi_writer *writer) +{ + int ret; + enum lttng_error_code ret_code; + + assert(rule); + assert(writer); + assert(rule->mi_serialize); + + /* Open event rule element. */ + ret = mi_lttng_writer_open_element(writer, mi_lttng_element_event_rule); + if (ret) { + goto mi_error; + } + + /* Serialize underlying event rule. */ + ret_code = rule->mi_serialize(rule, writer); + if (ret_code != LTTNG_OK) { + goto end; + } + + /* Close event rule element. */ + ret = mi_lttng_writer_close_element(writer); + if (ret) { + goto mi_error; + } + + ret_code = LTTNG_OK; + goto end; + +mi_error: + ret_code = LTTNG_ERR_MI_IO_FAIL; +end: + return ret_code; +} diff --git a/src/common/event-rule/jul-logging.c b/src/common/event-rule/jul-logging.c index 588835951..5f69f84c7 100644 --- a/src/common/event-rule/jul-logging.c +++ b/src/common/event-rule/jul-logging.c @@ -8,18 +8,19 @@ #include #include #include +#include +#include #include +#include #include -#include #include +#include #include -#include -#include #include #include #include -#include #include +#include #define IS_JUL_LOGGING_EVENT_RULE(rule) \ (lttng_event_rule_get_type(rule) == LTTNG_EVENT_RULE_TYPE_JUL_LOGGING) @@ -478,6 +479,83 @@ error: return event; } +static enum lttng_error_code lttng_event_rule_jul_logging_mi_serialize( + const struct lttng_event_rule *rule, struct mi_writer *writer) +{ + int ret; + enum lttng_error_code ret_code; + enum lttng_event_rule_status status; + + const char *filter = NULL; + const char *name_pattern = NULL; + const struct lttng_log_level_rule *log_level_rule = NULL; + + assert(rule); + assert(writer); + assert(IS_JUL_LOGGING_EVENT_RULE(rule)); + + status = lttng_event_rule_jul_logging_get_name_pattern( + rule, &name_pattern); + assert(status == LTTNG_EVENT_RULE_STATUS_OK); + assert(name_pattern); + + status = lttng_event_rule_jul_logging_get_filter(rule, &filter); + assert(status == LTTNG_EVENT_RULE_STATUS_OK || + status == LTTNG_EVENT_RULE_STATUS_UNSET); + + status = lttng_event_rule_jul_logging_get_log_level_rule( + rule, &log_level_rule); + assert(status == LTTNG_EVENT_RULE_STATUS_OK || + status == LTTNG_EVENT_RULE_STATUS_UNSET); + + /* Open event rule jul logging element. */ + ret = mi_lttng_writer_open_element( + writer, mi_lttng_element_event_rule_jul_logging); + if (ret) { + goto mi_error; + } + + /* Name pattern. */ + ret = mi_lttng_writer_write_element_string(writer, + mi_lttng_element_event_rule_name_pattern, name_pattern); + if (ret) { + goto mi_error; + } + + /* Filter expression. */ + if (filter != NULL) { + ret = mi_lttng_writer_write_element_string(writer, + mi_lttng_element_event_rule_filter_expression, + filter); + if (ret) { + goto mi_error; + } + } + + /* Log level rule. */ + if (log_level_rule) { + ret_code = lttng_log_level_rule_mi_serialize( + log_level_rule, writer); + if (ret_code != LTTNG_OK) { + goto end; + } + } + + /* Close event rule jul logging element. */ + ret = mi_lttng_writer_close_element(writer); + if (ret) { + goto mi_error; + } + + ret_code = LTTNG_OK; + goto end; + +mi_error: + ret_code = LTTNG_ERR_MI_IO_FAIL; +end: + return ret_code; +} + struct lttng_event_rule *lttng_event_rule_jul_logging_create(void) { struct lttng_event_rule *rule = NULL; @@ -506,6 +584,7 @@ struct lttng_event_rule *lttng_event_rule_jul_logging_create(void) tp_rule->parent.hash = lttng_event_rule_jul_logging_hash; tp_rule->parent.generate_lttng_event = lttng_event_rule_jul_logging_generate_lttng_event; + tp_rule->parent.mi_serialize = lttng_event_rule_jul_logging_mi_serialize; tp_rule->log_level_rule = NULL; diff --git a/src/common/event-rule/kernel-kprobe.c b/src/common/event-rule/kernel-kprobe.c index b069bdb31..0b7878630 100644 --- a/src/common/event-rule/kernel-kprobe.c +++ b/src/common/event-rule/kernel-kprobe.c @@ -8,19 +8,20 @@ #include #include #include +#include +#include #include -#include +#include #include +#include #include -#include -#include #include #include -#include #include +#include #include -#include #include +#include #include #define IS_KPROBE_EVENT_RULE(rule) \ @@ -223,6 +224,64 @@ end: return ret; } +static +enum lttng_error_code lttng_event_rule_kernel_kprobe_mi_serialize( + const struct lttng_event_rule *rule, struct mi_writer *writer) +{ + int ret; + enum lttng_error_code ret_code; + enum lttng_event_rule_status status; + const char *event_name = NULL; + const struct lttng_kernel_probe_location *location = NULL; + + assert(rule); + assert(writer); + assert(IS_KPROBE_EVENT_RULE(rule)); + + status = lttng_event_rule_kernel_kprobe_get_event_name( + rule, &event_name); + assert(status == LTTNG_EVENT_RULE_STATUS_OK); + assert(event_name); + + status = lttng_event_rule_kernel_kprobe_get_location(rule, &location); + assert(status == LTTNG_EVENT_RULE_STATUS_OK); + assert(location); + + /* Open event rule kernel kprobe element. */ + ret = mi_lttng_writer_open_element( + writer, mi_lttng_element_event_rule_kernel_kprobe); + if (ret) { + goto mi_error; + } + + /* Name. */ + ret = mi_lttng_writer_write_element_string(writer, + mi_lttng_element_event_rule_event_name, event_name); + if (ret) { + goto mi_error; + } + + /* Probe location. */ + ret_code = lttng_kernel_probe_location_mi_serialize(location, writer); + if (ret_code != LTTNG_OK) { + goto end; + } + + /* Close event rule kernel kprobe element. */ + ret = mi_lttng_writer_close_element(writer); + if (ret) { + goto mi_error; + } + + ret_code = LTTNG_OK; + goto end; + +mi_error: + ret_code = LTTNG_ERR_MI_IO_FAIL; +end: + return ret_code; +} + struct lttng_event_rule *lttng_event_rule_kernel_kprobe_create( const struct lttng_kernel_probe_location *location) { @@ -248,6 +307,7 @@ struct lttng_event_rule *lttng_event_rule_kernel_kprobe_create( krule->parent.generate_exclusions = lttng_event_rule_kernel_kprobe_generate_exclusions; krule->parent.hash = lttng_event_rule_kernel_kprobe_hash; + krule->parent.mi_serialize = lttng_event_rule_kernel_kprobe_mi_serialize; if (kernel_probe_set_location(krule, location)) { lttng_event_rule_destroy(rule); diff --git a/src/common/event-rule/kernel-syscall.c b/src/common/event-rule/kernel-syscall.c index a2a77a3c4..5f944d1be 100644 --- a/src/common/event-rule/kernel-syscall.c +++ b/src/common/event-rule/kernel-syscall.c @@ -8,12 +8,13 @@ #include #include #include +#include +#include #include -#include +#include #include +#include #include -#include -#include #include #include #include @@ -247,6 +248,95 @@ lttng_event_rule_kernel_syscall_hash( return hash; } +static enum lttng_error_code lttng_event_rule_kernel_syscall_mi_serialize( + const struct lttng_event_rule *rule, struct mi_writer *writer) +{ + int ret; + enum lttng_error_code ret_code; + enum lttng_event_rule_status status; + + enum lttng_event_rule_kernel_syscall_emission_site site_type; + const char *filter = NULL; + const char *name_pattern = NULL; + const char *site_type_str = NULL; + + assert(rule); + assert(writer); + assert(IS_SYSCALL_EVENT_RULE(rule)); + + status = lttng_event_rule_kernel_syscall_get_name_pattern( + rule, &name_pattern); + assert(status == LTTNG_EVENT_RULE_STATUS_OK); + assert(name_pattern); + + status = lttng_event_rule_kernel_syscall_get_filter(rule, &filter); + assert(status == LTTNG_EVENT_RULE_STATUS_OK || + status == LTTNG_EVENT_RULE_STATUS_UNSET); + + site_type = lttng_event_rule_kernel_syscall_get_emission_site(rule); + + switch (site_type) { + case LTTNG_EVENT_RULE_KERNEL_SYSCALL_EMISSION_SITE_ENTRY_EXIT: + site_type_str = mi_lttng_event_rule_kernel_syscall_emission_site_entry_exit; + break; + case LTTNG_EVENT_RULE_KERNEL_SYSCALL_EMISSION_SITE_ENTRY: + site_type_str = mi_lttng_event_rule_kernel_syscall_emission_site_entry; + break; + case LTTNG_EVENT_RULE_KERNEL_SYSCALL_EMISSION_SITE_EXIT: + site_type_str = mi_lttng_event_rule_kernel_syscall_emission_site_exit; + break; + default: + abort(); + break; + } + + /* Open event rule kernel syscall element. */ + ret = mi_lttng_writer_open_element( + writer, mi_lttng_element_event_rule_kernel_syscall); + if (ret) { + goto mi_error; + } + + /* Emission site. */ + ret = mi_lttng_writer_write_element_string(writer, + mi_lttng_element_event_rule_kernel_syscall_emission_site, + site_type_str); + if (ret) { + goto mi_error; + } + + /* Name pattern. */ + ret = mi_lttng_writer_write_element_string(writer, + mi_lttng_element_event_rule_name_pattern, name_pattern); + if (ret) { + goto mi_error; + } + + /* Filter. */ + if (filter != NULL) { + ret = mi_lttng_writer_write_element_string(writer, + mi_lttng_element_event_rule_filter_expression, + filter); + if (ret) { + goto mi_error; + } + } + + /* Close event rule kernel syscall. */ + ret = mi_lttng_writer_close_element(writer); + if (ret) { + goto mi_error; + } + + ret_code = LTTNG_OK; + goto end; + +mi_error: + ret_code = LTTNG_ERR_MI_IO_FAIL; +end: + return ret_code; +} + struct lttng_event_rule *lttng_event_rule_kernel_syscall_create( enum lttng_event_rule_kernel_syscall_emission_site emission_site) @@ -287,6 +377,7 @@ struct lttng_event_rule *lttng_event_rule_kernel_syscall_create( syscall_rule->parent.generate_exclusions = lttng_event_rule_kernel_syscall_generate_exclusions; syscall_rule->parent.hash = lttng_event_rule_kernel_syscall_hash; + syscall_rule->parent.mi_serialize = lttng_event_rule_kernel_syscall_mi_serialize; /* Default pattern is '*'. */ status = lttng_event_rule_kernel_syscall_set_name_pattern(rule, "*"); diff --git a/src/common/event-rule/kernel-tracepoint.c b/src/common/event-rule/kernel-tracepoint.c index 11b34045f..0c62308f5 100644 --- a/src/common/event-rule/kernel-tracepoint.c +++ b/src/common/event-rule/kernel-tracepoint.c @@ -8,13 +8,14 @@ #include #include #include +#include +#include #include +#include #include -#include #include +#include #include -#include -#include #include #include #include @@ -266,6 +267,67 @@ static unsigned long lttng_event_rule_kernel_tracepoint_hash( return hash; } +static enum lttng_error_code lttng_event_rule_kernel_tracepoint_mi_serialize( + const struct lttng_event_rule *rule, struct mi_writer *writer) +{ + int ret; + enum lttng_error_code ret_code; + enum lttng_event_rule_status status; + const char *filter = NULL; + const char *name_pattern = NULL; + + assert(rule); + assert(writer); + assert(IS_KERNEL_TRACEPOINT_EVENT_RULE(rule)); + + status = lttng_event_rule_kernel_tracepoint_get_name_pattern( + rule, &name_pattern); + assert(status == LTTNG_EVENT_RULE_STATUS_OK); + assert(name_pattern); + + status = lttng_event_rule_kernel_tracepoint_get_filter(rule, &filter); + assert(status == LTTNG_EVENT_RULE_STATUS_OK || + status == LTTNG_EVENT_RULE_STATUS_UNSET); + + /* Open event rule kernel tracepoint element. */ + ret = mi_lttng_writer_open_element( + writer, mi_lttng_element_event_rule_kernel_tracepoint); + if (ret) { + goto mi_error; + } + + /* Name pattern. */ + ret = mi_lttng_writer_write_element_string(writer, + mi_lttng_element_event_rule_name_pattern, name_pattern); + if (ret) { + goto mi_error; + } + + /* Filter. */ + if (filter != NULL) { + ret = mi_lttng_writer_write_element_string(writer, + mi_lttng_element_event_rule_filter_expression, + filter); + if (ret) { + goto mi_error; + } + } + + /* Close event rule kernel tracepoint element. */ + ret = mi_lttng_writer_close_element(writer); + if (ret) { + goto mi_error; + } + + ret_code = LTTNG_OK; + goto end; + +mi_error: + ret_code = LTTNG_ERR_MI_IO_FAIL; +end: + return ret_code; +} + struct lttng_event_rule *lttng_event_rule_kernel_tracepoint_create(void) { struct lttng_event_rule *rule = NULL; @@ -292,6 +354,7 @@ struct lttng_event_rule *lttng_event_rule_kernel_tracepoint_create(void) tp_rule->parent.generate_exclusions = lttng_event_rule_kernel_tracepoint_generate_exclusions; tp_rule->parent.hash = lttng_event_rule_kernel_tracepoint_hash; + tp_rule->parent.mi_serialize = lttng_event_rule_kernel_tracepoint_mi_serialize; /* Not necessary for now. */ tp_rule->parent.generate_lttng_event = NULL; diff --git a/src/common/event-rule/kernel-uprobe.c b/src/common/event-rule/kernel-uprobe.c index df5b896cf..2af1a028c 100644 --- a/src/common/event-rule/kernel-uprobe.c +++ b/src/common/event-rule/kernel-uprobe.c @@ -8,12 +8,13 @@ #include #include #include +#include +#include #include -#include +#include #include +#include #include -#include -#include #include #include #include @@ -214,6 +215,63 @@ end: return ret; } +static enum lttng_error_code lttng_event_rule_kernel_uprobe_mi_serialize( + const struct lttng_event_rule *rule, struct mi_writer *writer) +{ + int ret; + enum lttng_error_code ret_code; + enum lttng_event_rule_status status; + const char *event_name = NULL; + const struct lttng_userspace_probe_location *location = NULL; + + assert(rule); + assert(writer); + assert(IS_UPROBE_EVENT_RULE(rule)); + + status = lttng_event_rule_kernel_uprobe_get_event_name( + rule, &event_name); + assert(status == LTTNG_EVENT_RULE_STATUS_OK); + assert(event_name); + + status = lttng_event_rule_kernel_uprobe_get_location(rule, &location); + assert(status == LTTNG_EVENT_RULE_STATUS_OK); + assert(location); + + /* Open event rule kernel uprobe element. */ + ret = mi_lttng_writer_open_element( + writer, mi_lttng_element_event_rule_kernel_uprobe); + if (ret) { + goto mi_error; + } + + /* Event name. */ + ret = mi_lttng_writer_write_element_string(writer, + mi_lttng_element_event_rule_event_name, event_name); + if (ret) { + goto mi_error; + } + + /* Probe location. */ + ret_code = lttng_userspace_probe_location_mi_serialize(location, writer); + if (ret_code != LTTNG_OK) { + goto end; + } + + /* Close event rule kernel uprobe element. */ + ret = mi_lttng_writer_close_element(writer); + if (ret) { + goto mi_error; + } + + ret_code = LTTNG_OK; + goto end; + +mi_error: + ret_code = LTTNG_ERR_MI_IO_FAIL; +end: + return ret_code; +} + struct lttng_event_rule *lttng_event_rule_kernel_uprobe_create( const struct lttng_userspace_probe_location *location) { @@ -239,6 +297,7 @@ struct lttng_event_rule *lttng_event_rule_kernel_uprobe_create( urule->parent.generate_exclusions = lttng_event_rule_kernel_uprobe_generate_exclusions; urule->parent.hash = lttng_event_rule_kernel_uprobe_hash; + urule->parent.mi_serialize = lttng_event_rule_kernel_uprobe_mi_serialize; if (userspace_probe_set_location(urule, location)) { lttng_event_rule_destroy(rule); diff --git a/src/common/event-rule/log4j-logging.c b/src/common/event-rule/log4j-logging.c index efe70aa59..755ae26c6 100644 --- a/src/common/event-rule/log4j-logging.c +++ b/src/common/event-rule/log4j-logging.c @@ -8,18 +8,19 @@ #include #include #include +#include +#include #include +#include #include -#include #include +#include #include -#include -#include #include #include #include -#include #include +#include #define IS_LOG4J_LOGGING_EVENT_RULE(rule) \ (lttng_event_rule_get_type(rule) == LTTNG_EVENT_RULE_TYPE_LOG4J_LOGGING) @@ -478,6 +479,82 @@ error: return event; } +static enum lttng_error_code lttng_event_rule_log4j_logging_mi_serialize( + const struct lttng_event_rule *rule, struct mi_writer *writer) +{ + int ret; + enum lttng_error_code ret_code; + enum lttng_event_rule_status status; + const char *filter = NULL; + const char *name_pattern = NULL; + const struct lttng_log_level_rule *log_level_rule = NULL; + + assert(rule); + assert(writer); + assert(IS_LOG4J_LOGGING_EVENT_RULE(rule)); + + status = lttng_event_rule_log4j_logging_get_name_pattern( + rule, &name_pattern); + assert(status == LTTNG_EVENT_RULE_STATUS_OK); + assert(name_pattern); + + status = lttng_event_rule_log4j_logging_get_filter(rule, &filter); + assert(status == LTTNG_EVENT_RULE_STATUS_OK || + status == LTTNG_EVENT_RULE_STATUS_UNSET); + + status = lttng_event_rule_log4j_logging_get_log_level_rule( + rule, &log_level_rule); + assert(status == LTTNG_EVENT_RULE_STATUS_OK || + status == LTTNG_EVENT_RULE_STATUS_UNSET); + + /* Open event rule log4j logging element. */ + ret = mi_lttng_writer_open_element( + writer, mi_lttng_element_event_rule_log4j_logging); + if (ret) { + goto mi_error; + } + + /* Name pattern. */ + ret = mi_lttng_writer_write_element_string(writer, + mi_lttng_element_event_rule_name_pattern, name_pattern); + if (ret) { + goto mi_error; + } + + /* Filter expression. */ + if (filter != NULL) { + ret = mi_lttng_writer_write_element_string(writer, + mi_lttng_element_event_rule_filter_expression, + filter); + if (ret) { + goto mi_error; + } + } + + /* Log level rule. */ + if (log_level_rule) { + ret_code = lttng_log_level_rule_mi_serialize( + log_level_rule, writer); + if (ret_code != LTTNG_OK) { + goto end; + } + } + + /* Close event rule log4j logging element. */ + ret = mi_lttng_writer_close_element(writer); + if (ret) { + goto mi_error; + } + + ret_code = LTTNG_OK; + goto end; + +mi_error: + ret_code = LTTNG_ERR_MI_IO_FAIL; +end: + return ret_code; +} + struct lttng_event_rule *lttng_event_rule_log4j_logging_create(void) { struct lttng_event_rule *rule = NULL; @@ -506,6 +583,7 @@ struct lttng_event_rule *lttng_event_rule_log4j_logging_create(void) tp_rule->parent.hash = lttng_event_rule_log4j_logging_hash; tp_rule->parent.generate_lttng_event = lttng_event_rule_log4j_logging_generate_lttng_event; + tp_rule->parent.mi_serialize = lttng_event_rule_log4j_logging_mi_serialize; tp_rule->log_level_rule = NULL; diff --git a/src/common/event-rule/python-logging.c b/src/common/event-rule/python-logging.c index 5c49a590d..4b5cebaf0 100644 --- a/src/common/event-rule/python-logging.c +++ b/src/common/event-rule/python-logging.c @@ -8,18 +8,19 @@ #include #include #include +#include +#include #include +#include #include -#include #include +#include #include -#include -#include #include #include #include -#include #include +#include #define IS_PYTHON_LOGGING_EVENT_RULE(rule) \ (lttng_event_rule_get_type(rule) == LTTNG_EVENT_RULE_TYPE_PYTHON_LOGGING) @@ -478,6 +479,82 @@ error: return event; } +static enum lttng_error_code lttng_event_rule_python_logging_mi_serialize( + const struct lttng_event_rule *rule, struct mi_writer *writer) +{ + int ret; + enum lttng_error_code ret_code; + enum lttng_event_rule_status status; + const char *filter = NULL; + const char *name_pattern = NULL; + const struct lttng_log_level_rule *log_level_rule = NULL; + + assert(rule); + assert(writer); + assert(IS_PYTHON_LOGGING_EVENT_RULE(rule)); + + status = lttng_event_rule_python_logging_get_name_pattern( + rule, &name_pattern); + assert(status == LTTNG_EVENT_RULE_STATUS_OK); + assert(name_pattern); + + status = lttng_event_rule_python_logging_get_filter(rule, &filter); + assert(status == LTTNG_EVENT_RULE_STATUS_OK || + status == LTTNG_EVENT_RULE_STATUS_UNSET); + + status = lttng_event_rule_python_logging_get_log_level_rule( + rule, &log_level_rule); + assert(status == LTTNG_EVENT_RULE_STATUS_OK || + status == LTTNG_EVENT_RULE_STATUS_UNSET); + + /* Open event rule python logging element. */ + ret = mi_lttng_writer_open_element( + writer, mi_lttng_element_event_rule_python_logging); + if (ret) { + goto mi_error; + } + + /* Name pattern. */ + ret = mi_lttng_writer_write_element_string(writer, + mi_lttng_element_event_rule_name_pattern, name_pattern); + if (ret) { + goto mi_error; + } + + /* Filter expression. */ + if (filter != NULL) { + ret = mi_lttng_writer_write_element_string(writer, + mi_lttng_element_event_rule_filter_expression, + filter); + if (ret) { + goto mi_error; + } + } + + /* Log level rule. */ + if (log_level_rule) { + ret_code = lttng_log_level_rule_mi_serialize( + log_level_rule, writer); + if (ret_code != LTTNG_OK) { + goto end; + } + } + + /* Close event rule python logging element. */ + ret = mi_lttng_writer_close_element(writer); + if (ret) { + goto mi_error; + } + + ret_code = LTTNG_OK; + goto end; + +mi_error: + ret_code = LTTNG_ERR_MI_IO_FAIL; +end: + return ret_code; +} + struct lttng_event_rule *lttng_event_rule_python_logging_create(void) { struct lttng_event_rule *rule = NULL; @@ -506,6 +583,7 @@ struct lttng_event_rule *lttng_event_rule_python_logging_create(void) tp_rule->parent.hash = lttng_event_rule_python_logging_hash; tp_rule->parent.generate_lttng_event = lttng_event_rule_python_logging_generate_lttng_event; + tp_rule->parent.mi_serialize = lttng_event_rule_python_logging_mi_serialize; tp_rule->log_level_rule = NULL; diff --git a/src/common/event-rule/user-tracepoint.c b/src/common/event-rule/user-tracepoint.c index 45b7eda25..503e7163f 100644 --- a/src/common/event-rule/user-tracepoint.c +++ b/src/common/event-rule/user-tracepoint.c @@ -8,18 +8,19 @@ #include #include #include +#include +#include #include +#include #include -#include #include +#include #include -#include -#include #include #include #include -#include #include +#include #define IS_USER_TRACEPOINT_EVENT_RULE(rule) \ (lttng_event_rule_get_type(rule) == LTTNG_EVENT_RULE_TYPE_USER_TRACEPOINT) @@ -439,6 +440,119 @@ static unsigned long lttng_event_rule_user_tracepoint_hash( return hash; } +static enum lttng_error_code lttng_event_rule_user_tracepoint_mi_serialize( + const struct lttng_event_rule *rule, struct mi_writer *writer) +{ + int ret; + enum lttng_error_code ret_code; + enum lttng_event_rule_status status; + const char *filter = NULL; + const char *name_pattern = NULL; + const struct lttng_log_level_rule *log_level_rule = NULL; + unsigned int exclusion_count = 0; + + assert(rule); + assert(writer); + assert(IS_USER_TRACEPOINT_EVENT_RULE(rule)); + + status = lttng_event_rule_user_tracepoint_get_name_pattern( + rule, &name_pattern); + assert(status == LTTNG_EVENT_RULE_STATUS_OK); + assert(name_pattern); + + status = lttng_event_rule_user_tracepoint_get_filter(rule, &filter); + assert(status == LTTNG_EVENT_RULE_STATUS_OK || + status == LTTNG_EVENT_RULE_STATUS_UNSET); + + status = lttng_event_rule_user_tracepoint_get_log_level_rule( + rule, &log_level_rule); + assert(status == LTTNG_EVENT_RULE_STATUS_OK || + status == LTTNG_EVENT_RULE_STATUS_UNSET); + + status = lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_count( + rule, &exclusion_count); + assert(status == LTTNG_EVENT_RULE_STATUS_OK); + + /* Open event rule user tracepoint element. */ + ret = mi_lttng_writer_open_element( + writer, mi_lttng_element_event_rule_user_tracepoint); + if (ret) { + goto mi_error; + } + + /* Name pattern. */ + ret = mi_lttng_writer_write_element_string(writer, + mi_lttng_element_event_rule_name_pattern, name_pattern); + if (ret) { + goto mi_error; + } + + /* Filter expression. */ + if (filter != NULL) { + ret = mi_lttng_writer_write_element_string(writer, + mi_lttng_element_event_rule_filter_expression, + filter); + if (ret) { + goto mi_error; + } + } + + /* Log level rule. */ + if (log_level_rule) { + ret_code = lttng_log_level_rule_mi_serialize( + log_level_rule, writer); + if (ret_code != LTTNG_OK) { + goto end; + } + } + + if (exclusion_count != 0) { + int i; + + /* Open the exclusion list. */ + ret = mi_lttng_writer_open_element(writer, + mi_lttng_element_event_rule_user_tracepoint_name_pattern_exclusions); + if (ret) { + goto mi_error; + } + + for (i = 0; i < exclusion_count; i++) { + const char *exclusion; + + status = lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_at_index( + rule, i, &exclusion); + assert(status == LTTNG_EVENT_RULE_STATUS_OK); + + ret = mi_lttng_writer_write_element_string(writer, + mi_lttng_element_event_rule_user_tracepoint_name_pattern_exclusion, + exclusion); + if (ret) { + goto mi_error; + } + } + + /* Close the list. */ + ret = mi_lttng_writer_close_element(writer); + if (ret) { + goto mi_error; + } + } + + /* Close event rule user tracepoint element. */ + ret = mi_lttng_writer_close_element(writer); + if (ret) { + goto mi_error; + } + + ret_code = LTTNG_OK; + goto end; + +mi_error: + ret_code = LTTNG_ERR_MI_IO_FAIL; +end: + return ret_code; +} + struct lttng_event_rule *lttng_event_rule_user_tracepoint_create(void) { struct lttng_event_rule *rule = NULL; @@ -465,6 +579,7 @@ struct lttng_event_rule *lttng_event_rule_user_tracepoint_create(void) tp_rule->parent.generate_exclusions = lttng_event_rule_user_tracepoint_generate_exclusions; tp_rule->parent.hash = lttng_event_rule_user_tracepoint_hash; + tp_rule->parent.mi_serialize = lttng_event_rule_user_tracepoint_mi_serialize; /* Not necessary for now. */ tp_rule->parent.generate_lttng_event = NULL; diff --git a/src/common/kernel-probe.c b/src/common/kernel-probe.c index d2637f933..2beb53fab 100644 --- a/src/common/kernel-probe.c +++ b/src/common/kernel-probe.c @@ -8,15 +8,16 @@ #include "lttng/lttng-error.h" #include #include -#include -#include -#include #include #include +#include +#include +#include +#include #include #include -#include #include +#include #include #include #include @@ -49,6 +50,16 @@ static unsigned long lttng_kernel_probe_location_symbol_hash( const struct lttng_kernel_probe_location *location); +static +enum lttng_error_code lttng_kernel_probe_location_address_mi_serialize( + const struct lttng_kernel_probe_location *location, + struct mi_writer *writer); + +static +enum lttng_error_code lttng_kernel_probe_location_symbol_mi_serialize( + const struct lttng_kernel_probe_location *location, + struct mi_writer *writer); + enum lttng_kernel_probe_location_type lttng_kernel_probe_location_get_type( const struct lttng_kernel_probe_location *location) { @@ -120,6 +131,7 @@ lttng_kernel_probe_location_address_create(uint64_t address) ret->equal = lttng_kernel_probe_location_address_is_equal; ret->serialize = lttng_kernel_probe_location_address_serialize; ret->hash = lttng_kernel_probe_location_address_hash; + ret->mi_serialize = lttng_kernel_probe_location_address_mi_serialize; end: return ret; @@ -157,6 +169,7 @@ lttng_kernel_probe_location_symbol_create(const char *symbol_name, ret->equal = lttng_kernel_probe_location_symbol_is_equal; ret->serialize = lttng_kernel_probe_location_symbol_serialize; ret->hash = lttng_kernel_probe_location_symbol_hash; + ret->mi_serialize = lttng_kernel_probe_location_symbol_mi_serialize; goto end; error: @@ -724,3 +737,150 @@ unsigned long lttng_kernel_probe_location_hash( { return location->hash(location); } + +static +enum lttng_error_code lttng_kernel_probe_location_address_mi_serialize( + const struct lttng_kernel_probe_location *location, + struct mi_writer *writer) +{ + int ret; + enum lttng_error_code ret_code; + enum lttng_kernel_probe_location_status status; + uint64_t address; + + assert(location); + assert(writer); + assert(location->type == LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS); + + status = lttng_kernel_probe_location_address_get_address( + location, &address); + assert(status == LTTNG_KERNEL_PROBE_LOCATION_STATUS_OK); + + /* Open kernel probe location address element. */ + ret = mi_lttng_writer_open_element( + writer, mi_lttng_element_kernel_probe_location_address); + if (ret) { + goto mi_error; + } + + ret = mi_lttng_writer_write_element_unsigned_int(writer, + mi_lttng_element_kernel_probe_location_address_address, + address); + if (ret) { + goto mi_error; + } + + /* Close kernel probe location address element. */ + ret = mi_lttng_writer_close_element(writer); + if (ret) { + goto mi_error; + } + + ret_code = LTTNG_OK; + goto end; + +mi_error: + ret_code = LTTNG_ERR_MI_IO_FAIL; +end: + return ret_code; +} + +static +enum lttng_error_code lttng_kernel_probe_location_symbol_mi_serialize( + const struct lttng_kernel_probe_location *location, + struct mi_writer *writer) +{ + int ret; + enum lttng_error_code ret_code; + enum lttng_kernel_probe_location_status status; + const char *name = NULL; + uint64_t offset; + + assert(location); + assert(writer); + assert(location->type == + LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET); + + name = lttng_kernel_probe_location_symbol_get_name(location); + assert(name); + + status = lttng_kernel_probe_location_symbol_get_offset( + location, &offset); + assert(status == LTTNG_KERNEL_PROBE_LOCATION_STATUS_OK); + + /* Open kernel probe location symbol offset element. */ + ret = mi_lttng_writer_open_element(writer, + mi_lttng_element_kernel_probe_location_symbol_offset); + if (ret) { + goto mi_error; + } + + /* Name. */ + ret = mi_lttng_writer_write_element_string(writer, + mi_lttng_element_kernel_probe_location_symbol_offset_name, + name); + if (ret) { + goto mi_error; + } + + /* Offset. */ + ret = mi_lttng_writer_write_element_unsigned_int(writer, + mi_lttng_element_kernel_probe_location_symbol_offset_offset, + offset); + if (ret) { + goto mi_error; + } + + /* Close kernel probe location symbol offset element. */ + ret = mi_lttng_writer_close_element(writer); + if (ret) { + goto mi_error; + } + + ret_code = LTTNG_OK; + goto end; + +mi_error: + ret_code = LTTNG_ERR_MI_IO_FAIL; +end: + return ret_code; +} + +LTTNG_HIDDEN +enum lttng_error_code lttng_kernel_probe_location_mi_serialize( + const struct lttng_kernel_probe_location *location, + struct mi_writer *writer) +{ + int ret; + enum lttng_error_code ret_code; + + assert(location); + assert(writer); + + /* Open kernel probe location element. */ + ret = mi_lttng_writer_open_element( + writer, mi_lttng_element_kernel_probe_location); + if (ret) { + goto mi_error; + } + + /* Serialize the location sub type. */ + ret_code = location->mi_serialize(location, writer); + if (ret_code != LTTNG_OK) { + goto end; + } + + /* Close kernel probe location element. */ + ret = mi_lttng_writer_close_element(writer); + if (ret) { + goto mi_error; + } + + ret_code = LTTNG_OK; + goto end; + +mi_error: + ret_code = LTTNG_ERR_MI_IO_FAIL; +end: + return ret_code; +} diff --git a/src/common/log-level-rule.c b/src/common/log-level-rule.c index ca8e439e7..5c0da4d1a 100644 --- a/src/common/log-level-rule.c +++ b/src/common/log-level-rule.c @@ -8,9 +8,10 @@ #include #include #include -#include #include #include +#include +#include #include #include #include @@ -300,3 +301,75 @@ unsigned long lttng_log_level_rule_hash( return hash; } + +LTTNG_HIDDEN +enum lttng_error_code lttng_log_level_rule_mi_serialize( + const struct lttng_log_level_rule *rule, + struct mi_writer *writer) +{ + int ret; + enum lttng_error_code ret_code; + enum lttng_log_level_rule_status status; + const char *element_str = NULL; + int level; + + assert(rule); + assert(writer); + + switch (lttng_log_level_rule_get_type(rule)) { + case LTTNG_LOG_LEVEL_RULE_TYPE_EXACTLY: + status = lttng_log_level_rule_exactly_get_level(rule, &level); + element_str = mi_lttng_element_log_level_rule_exactly; + break; + case LTTNG_LOG_LEVEL_RULE_TYPE_AT_LEAST_AS_SEVERE_AS: + element_str = mi_lttng_element_log_level_rule_at_least_as_severe_as; + status = lttng_log_level_rule_at_least_as_severe_as_get_level( + rule, &level); + break; + default: + abort(); + break; + } + + assert(status == LTTNG_LOG_LEVEL_RULE_STATUS_OK); + + /* Open log level rule element. */ + ret = mi_lttng_writer_open_element( + writer, mi_lttng_element_log_level_rule); + if (ret) { + goto mi_error; + } + + /* Log level rule type element. */ + ret = mi_lttng_writer_open_element(writer, element_str); + if (ret) { + goto mi_error; + } + + /* Level. */ + ret = mi_lttng_writer_write_element_signed_int( + writer, mi_lttng_element_log_level_rule_level, level); + if (ret) { + goto mi_error; + } + + /* Close log level rule type element. */ + ret = mi_lttng_writer_close_element(writer); + if (ret) { + goto mi_error; + } + + /* Close log level rule element. */ + ret = mi_lttng_writer_close_element(writer); + if (ret) { + goto mi_error; + } + + ret_code = LTTNG_OK; + goto end; + +mi_error: + ret_code = LTTNG_ERR_MI_IO_FAIL; +end: + return ret_code; +} diff --git a/src/common/mi-lttng.c b/src/common/mi-lttng.c index 9031677d7..627d07207 100644 --- a/src/common/mi-lttng.c +++ b/src/common/mi-lttng.c @@ -39,6 +39,7 @@ LTTNG_HIDDEN const char * const mi_lttng_schema_version_value = XSTR(MI_SCHEMA_M const char * const mi_lttng_element_command = "command"; const char * const mi_lttng_element_command_action = "snapshot_action"; const char * const mi_lttng_element_command_add_context = "add-context"; +const char *const mi_lttng_element_command_add_trigger = "add-trigger"; const char * const mi_lttng_element_command_create = "create"; const char * const mi_lttng_element_command_destroy = "destroy"; const char * const mi_lttng_element_command_disable_channel = "disable-channel"; @@ -53,6 +54,7 @@ LTTNG_HIDDEN const char * const mi_lttng_element_command_regenerate = "regenerat LTTNG_HIDDEN const char * const mi_lttng_element_command_regenerate_action = "regenerate_action"; const char * const mi_lttng_element_command_name = "name"; const char * const mi_lttng_element_command_output = "output"; +const char *const mi_lttng_element_command_remove_trigger = "remove-trigger"; const char * const mi_lttng_element_command_save = "save"; const char * const mi_lttng_element_command_set_session = "set-session"; const char * const mi_lttng_element_command_snapshot = "snapshot"; @@ -208,6 +210,227 @@ LTTNG_HIDDEN const char * const mi_lttng_rotation_state_str_error = "ERROR"; /* String related to enum lttng_trace_archive_location_relay_protocol_type */ LTTNG_HIDDEN const char * const mi_lttng_rotation_location_relay_protocol_str_tcp = "TCP"; +/* String related to rate_policy elements */ +LTTNG_HIDDEN const char *const mi_lttng_element_rate_policy = "rate_policy"; +LTTNG_HIDDEN const char *const mi_lttng_element_rate_policy_every_n = + "rate_policy_every_n"; +LTTNG_HIDDEN const char *const mi_lttng_element_rate_policy_once_after_n = + "rate_policy_once_after_n"; + +LTTNG_HIDDEN const char *const mi_lttng_element_rate_policy_every_n_interval = + "interval"; +LTTNG_HIDDEN const char + *const mi_lttng_element_rate_policy_once_after_n_threshold = + "threshold"; + +/* String related to action elements */ +LTTNG_HIDDEN const char *const mi_lttng_element_action = "action"; +LTTNG_HIDDEN const char *const mi_lttng_element_action_list = "action_list"; +LTTNG_HIDDEN const char *const mi_lttng_element_action_notify = "action_notify"; +LTTNG_HIDDEN const char *const mi_lttng_element_action_start_session = + "action_start_session"; +LTTNG_HIDDEN const char *const mi_lttng_element_action_stop_session = + "action_stop_session"; +LTTNG_HIDDEN const char *const mi_lttng_element_action_rotate_session = + "action_rotate_session"; +LTTNG_HIDDEN const char *const mi_lttng_element_action_snapshot_session = + "action_snapshot_session"; +LTTNG_HIDDEN const char *const mi_lttng_element_action_snapshot_session_output = + "output"; + +/* String related to condition */ +LTTNG_HIDDEN const char *const mi_lttng_element_condition = "condition"; +LTTNG_HIDDEN const char *const mi_lttng_element_condition_buffer_usage_high = + "condition_buffer_usage_high"; +LTTNG_HIDDEN const char *const mi_lttng_element_condition_buffer_usage_low = + "condition_buffer_usage_low"; +LTTNG_HIDDEN const char *const mi_lttng_element_condition_event_rule_matches = + "condition_event_rule_matches"; +LTTNG_HIDDEN const char *const mi_lttng_element_condition_session_consumed_size = + "condition_session_consumed_size"; +LTTNG_HIDDEN const char *const mi_lttng_element_condition_session_rotation = + "condition_session_rotation"; +LTTNG_HIDDEN const char + *const mi_lttng_element_condition_session_rotation_completed = + "condition_session_rotation_completed"; +LTTNG_HIDDEN const char + *const mi_lttng_element_condition_session_rotation_ongoing = + "condition_session_rotation_ongoing"; + +LTTNG_HIDDEN const char *const mi_lttng_element_condition_channel_name = + "channel_name"; +LTTNG_HIDDEN const char *const mi_lttng_element_condition_threshold_bytes = + "threshold_bytes"; +LTTNG_HIDDEN const char *const mi_lttng_element_condition_threshold_ratio = + "threshold_ratio"; + +/* String related to capture descriptor */ +LTTNG_HIDDEN const char *const mi_lttng_element_capture_descriptor = + "capture_descriptor"; +LTTNG_HIDDEN const char *const mi_lttng_element_capture_descriptors = + "capture_descriptors"; + +/* String related to event expression */ +LTTNG_HIDDEN const char *const mi_lttng_element_event_expr = "event_expr"; +LTTNG_HIDDEN const char *const mi_lttng_element_event_expr_payload_field = + "event_expr_payload_field"; +LTTNG_HIDDEN const char *const mi_lttng_element_event_expr_channel_context_field = + "event_expr_channel_context_field"; +LTTNG_HIDDEN const char + *const mi_lttng_element_event_expr_app_specific_context_field = + "event_expr_app_specific_context_field"; +LTTNG_HIDDEN const char *const mi_lttng_element_event_expr_array_field_element = + "event_expr_array_field_element"; +LTTNG_HIDDEN const char *const mi_lttng_element_event_expr_provider_name = + "provider_name"; +LTTNG_HIDDEN const char *const mi_lttng_element_event_expr_type_name = + "type_name"; +LTTNG_HIDDEN const char *const mi_lttng_element_event_expr_index = "index"; + +/* String related to event rule */ +LTTNG_HIDDEN const char *const mi_lttng_element_event_rule = "event_rule"; + +/* String related to lttng_event_rule_type */ +LTTNG_HIDDEN const char *const mi_lttng_element_event_rule_event_name = + "event_name"; +LTTNG_HIDDEN const char *const mi_lttng_element_event_rule_name_pattern = + "name_pattern"; +LTTNG_HIDDEN const char *const mi_lttng_element_event_rule_filter_expression = + "filter_expression"; + +LTTNG_HIDDEN const char *const mi_lttng_element_event_rule_jul_logging = + "event_rule_jul_logging"; +LTTNG_HIDDEN const char *const mi_lttng_element_event_rule_kernel_kprobe = + "event_rule_kernel_kprobe"; +LTTNG_HIDDEN const char *const mi_lttng_element_event_rule_kernel_syscall = + "event_rule_kernel_syscall"; +LTTNG_HIDDEN const char *const mi_lttng_element_event_rule_kernel_tracepoint = + "event_rule_kernel_tracepoint"; +LTTNG_HIDDEN const char *const mi_lttng_element_event_rule_kernel_uprobe = + "event_rule_kernel_uprobe"; +LTTNG_HIDDEN const char *const mi_lttng_element_event_rule_log4j_logging = + "event_rule_log4j_logging"; +LTTNG_HIDDEN const char *const mi_lttng_element_event_rule_python_logging = + "event_rule_python_logging"; +LTTNG_HIDDEN const char *const mi_lttng_element_event_rule_user_tracepoint = + "event_rule_user_tracepoint"; + +/* String related to lttng_event_rule_kernel_syscall. */ +LTTNG_HIDDEN const char *const + mi_lttng_element_event_rule_kernel_syscall_emission_site = + "emission_site"; + +/* String related to enum lttng_event_rule_kernel_syscall_emission_site. */ +LTTNG_HIDDEN const char *const + mi_lttng_event_rule_kernel_syscall_emission_site_entry_exit = + "entry+exit"; +LTTNG_HIDDEN const char + *const mi_lttng_event_rule_kernel_syscall_emission_site_entry = + "entry"; +LTTNG_HIDDEN const char *const + mi_lttng_event_rule_kernel_syscall_emission_site_exit = "exit"; + +/* String related to lttng_event_rule_user_tracepoint */ +LTTNG_HIDDEN const char *const + mi_lttng_element_event_rule_user_tracepoint_name_pattern_exclusions = + "name_pattern_exclusions"; +LTTNG_HIDDEN const char *const + mi_lttng_element_event_rule_user_tracepoint_name_pattern_exclusion = + "name_pattern_exclusion"; + +/* String related to log level rule. */ +LTTNG_HIDDEN const char *const mi_lttng_element_log_level_rule = + "log_level_rule"; +LTTNG_HIDDEN const char *const mi_lttng_element_log_level_rule_exactly = + "log_level_rule_exactly"; +LTTNG_HIDDEN const char + *const mi_lttng_element_log_level_rule_at_least_as_severe_as = + "log_level_rule_at_least_as_severe_as"; +LTTNG_HIDDEN const char *const mi_lttng_element_log_level_rule_level = "level"; + +/* String related to kernel probe location. */ +LTTNG_HIDDEN const char *const mi_lttng_element_kernel_probe_location = + "kernel_probe_location"; +LTTNG_HIDDEN const char + *const mi_lttng_element_kernel_probe_location_symbol_offset = + "kernel_probe_location_symbol_offset"; +LTTNG_HIDDEN const char *const + mi_lttng_element_kernel_probe_location_symbol_offset_name = + "name"; +LTTNG_HIDDEN const char *const + mi_lttng_element_kernel_probe_location_symbol_offset_offset = + "offset"; + +LTTNG_HIDDEN const char *const mi_lttng_element_kernel_probe_location_address = + "kernel_probe_location_address"; +LTTNG_HIDDEN const char + *const mi_lttng_element_kernel_probe_location_address_address = + "address"; + +/* String related to userspace probe location. */ +LTTNG_HIDDEN const char *const mi_lttng_element_userspace_probe_location = + "userspace_probe_location"; +LTTNG_HIDDEN const char + *const mi_lttng_element_userspace_probe_location_binary_path = + "binary_path"; +LTTNG_HIDDEN const char + *const mi_lttng_element_userspace_probe_location_function = + "userspace_probe_location_function"; +LTTNG_HIDDEN const char + *const mi_lttng_element_userspace_probe_location_function_name = + "name"; +LTTNG_HIDDEN const char + *const mi_lttng_element_userspace_probe_location_lookup_method = + "userspace_probe_location_lookup_method"; +LTTNG_HIDDEN const char *const + mi_lttng_element_userspace_probe_location_lookup_method_function_default = + "userspace_probe_location_lookup_method_function_default"; +LTTNG_HIDDEN const char *const + mi_lttng_element_userspace_probe_location_lookup_method_function_elf = + "userspace_probe_location_lookup_method_function_elf"; +LTTNG_HIDDEN const char *const + mi_lttng_element_userspace_probe_location_lookup_method_tracepoint_sdt = + "userspace_probe_location_lookup_method_tracepoint_sdt"; +LTTNG_HIDDEN const char + *const mi_lttng_element_userspace_probe_location_tracepoint = + "userspace_probe_location_tracepoint"; +LTTNG_HIDDEN const char *const + mi_lttng_element_userspace_probe_location_tracepoint_probe_name = + "probe_name"; +LTTNG_HIDDEN const char *const + mi_lttng_element_userspace_probe_location_tracepoint_provider_name = + "provider_name"; + +/* String related to enum + * lttng_userspace_probe_location_function_instrumentation_type */ +LTTNG_HIDDEN const char *const + mi_lttng_element_userspace_probe_location_function_instrumentation_type = + "instrumentation_type"; +LTTNG_HIDDEN const char *const + mi_lttng_userspace_probe_location_function_instrumentation_type_entry = + "ENTRY"; + +/* String related to trigger */ +LTTNG_HIDDEN const char *const mi_lttng_element_triggers = "triggers"; +LTTNG_HIDDEN const char *const mi_lttng_element_trigger = "trigger"; +LTTNG_HIDDEN const char *const mi_lttng_element_trigger_owner_uid = "owner_uid"; + +/* String related to error_query. */ +LTTNG_HIDDEN const char *const mi_lttng_element_error_query_result = + "error_query_result"; +LTTNG_HIDDEN const char *const mi_lttng_element_error_query_result_counter = + "error_query_result_counter"; +LTTNG_HIDDEN const char *const + mi_lttng_element_error_query_result_counter_value = "value"; +LTTNG_HIDDEN const char *const mi_lttng_element_error_query_result_description = + "description"; +LTTNG_HIDDEN const char *const mi_lttng_element_error_query_result_name = + "name"; +LTTNG_HIDDEN const char *const mi_lttng_element_error_query_result_type = + "type"; +LTTNG_HIDDEN const char *const mi_lttng_element_error_query_results = + "error_query_results"; + /* String related to add-context command */ LTTNG_HIDDEN const char * const mi_lttng_element_context_symbol = "symbol"; @@ -549,7 +772,7 @@ const char *mi_lttng_trace_archive_location_relay_protocol_type_string( case LTTNG_TRACE_ARCHIVE_LOCATION_RELAY_PROTOCOL_TYPE_TCP: return mi_lttng_rotation_location_relay_protocol_str_tcp; default: - /* Should not have an unknow relay protocol. */ + /* Should not have an unknown relay protocol. */ assert(0); return NULL; } @@ -2036,7 +2259,7 @@ end: LTTNG_HIDDEN int mi_lttng_snapshot_list_output(struct mi_writer *writer, - struct lttng_snapshot_output *output) + const struct lttng_snapshot_output *output) { int ret; diff --git a/src/common/mi-lttng.h b/src/common/mi-lttng.h index ad9283236..d655f6fb8 100644 --- a/src/common/mi-lttng.h +++ b/src/common/mi-lttng.h @@ -39,10 +39,29 @@ struct mi_lttng_version { char package_url[LTTNG_NAME_MAX]; /* Define to the home page for this package. */ }; +/* Error query callbacks. */ +typedef enum lttng_error_code (*mi_lttng_error_query_trigger_cb)( + const struct lttng_trigger *trigger, + struct lttng_error_query_results **results); +typedef enum lttng_error_code (*mi_lttng_error_query_condition_cb)( + const struct lttng_trigger *trigger, + struct lttng_error_query_results **results); +typedef enum lttng_error_code (*mi_lttng_error_query_action_cb)( + const struct lttng_trigger *trigger, + const struct lttng_action_path *action_path, + struct lttng_error_query_results **results); + +struct mi_lttng_error_query_callbacks { + mi_lttng_error_query_trigger_cb trigger_cb; + mi_lttng_error_query_condition_cb condition_cb; + mi_lttng_error_query_action_cb action_cb; +}; + /* Strings related to command */ extern const char * const mi_lttng_element_command; extern const char * const mi_lttng_element_command_action; extern const char * const mi_lttng_element_command_add_context; +extern const char *const mi_lttng_element_command_add_trigger; extern const char * const mi_lttng_element_command_create; extern const char * const mi_lttng_element_command_destroy; extern const char * const mi_lttng_element_command_disable_channel; @@ -57,6 +76,7 @@ extern const char * const mi_lttng_element_command_regenerate; extern const char * const mi_lttng_element_command_regenerate_action; extern const char * const mi_lttng_element_command_name; extern const char * const mi_lttng_element_command_output; +extern const char *const mi_lttng_element_command_remove_trigger; extern const char * const mi_lttng_element_command_save; extern const char * const mi_lttng_element_command_set_session; extern const char * const mi_lttng_element_command_snapshot; @@ -212,6 +232,170 @@ LTTNG_HIDDEN extern const char * const mi_lttng_rotation_state_str_error; /* String related to enum lttng_trace_archive_location_relay_protocol_type */ LTTNG_HIDDEN extern const char * const mi_lttng_rotation_location_relay_protocol_str_tcp; +/* String related to rate_policy elements */ +LTTNG_HIDDEN extern const char *const mi_lttng_element_rate_policy; +LTTNG_HIDDEN extern const char *const mi_lttng_element_rate_policy_every_n; +LTTNG_HIDDEN extern const char *const mi_lttng_element_rate_policy_once_after_n; + +LTTNG_HIDDEN extern const char + *const mi_lttng_element_rate_policy_every_n_interval; +LTTNG_HIDDEN extern const char + *const mi_lttng_element_rate_policy_once_after_n_threshold; + +/* String related to action elements */ +LTTNG_HIDDEN extern const char *const mi_lttng_element_action; +LTTNG_HIDDEN extern const char *const mi_lttng_element_action_list; +LTTNG_HIDDEN extern const char *const mi_lttng_element_action_notify; +LTTNG_HIDDEN extern const char *const mi_lttng_element_action_start_session; +LTTNG_HIDDEN extern const char *const mi_lttng_element_action_stop_session; +LTTNG_HIDDEN extern const char *const mi_lttng_element_action_rotate_session; +LTTNG_HIDDEN extern const char *const mi_lttng_element_action_snapshot_session; +LTTNG_HIDDEN extern const char + *const mi_lttng_element_action_snapshot_session_output; + +/* String related to condition */ +LTTNG_HIDDEN extern const char *const mi_lttng_element_condition; +LTTNG_HIDDEN extern const char + *const mi_lttng_element_condition_buffer_usage_high; +LTTNG_HIDDEN extern const char + *const mi_lttng_element_condition_buffer_usage_low; +LTTNG_HIDDEN extern const char + *const mi_lttng_element_condition_event_rule_matches; +LTTNG_HIDDEN extern const char + *const mi_lttng_element_condition_session_consumed_size; +LTTNG_HIDDEN extern const char + *const mi_lttng_element_condition_session_rotation; +LTTNG_HIDDEN extern const char + *const mi_lttng_element_condition_session_rotation_completed; +LTTNG_HIDDEN extern const char + *const mi_lttng_element_condition_session_rotation_ongoing; +LTTNG_HIDDEN extern const char *const mi_lttng_element_condition_channel_name; +LTTNG_HIDDEN extern const char *const mi_lttng_element_condition_threshold_ratio; +LTTNG_HIDDEN extern const char *const mi_lttng_element_condition_threshold_bytes; + +/* String related to capture descriptor */ +LTTNG_HIDDEN extern const char *const mi_lttng_element_capture_descriptor; +LTTNG_HIDDEN extern const char *const mi_lttng_element_capture_descriptors; + +/* String related to event expression */ +LTTNG_HIDDEN extern const char *const mi_lttng_element_event_expr; +LTTNG_HIDDEN extern const char *const mi_lttng_element_event_expr_payload_field; +LTTNG_HIDDEN extern const char + *const mi_lttng_element_event_expr_channel_context_field; +LTTNG_HIDDEN extern const char + *const mi_lttng_element_event_expr_app_specific_context_field; +LTTNG_HIDDEN extern const char + *const mi_lttng_element_event_expr_array_field_element; + +LTTNG_HIDDEN extern const char *const mi_lttng_element_event_expr_provider_name; +LTTNG_HIDDEN extern const char *const mi_lttng_element_event_expr_type_name; +LTTNG_HIDDEN extern const char *const mi_lttng_element_event_expr_index; + +/* String related to event rule */ +LTTNG_HIDDEN extern const char *const mi_lttng_element_event_rule; + +/* String related to lttng_event_rule */ +LTTNG_HIDDEN extern const char *const mi_lttng_element_event_rule_event_name; +LTTNG_HIDDEN extern const char *const mi_lttng_element_event_rule_name_pattern; +LTTNG_HIDDEN extern const char + *const mi_lttng_element_event_rule_filter_expression; +LTTNG_HIDDEN extern const char *const mi_lttng_element_event_rule_jul_logging; +LTTNG_HIDDEN extern const char *const mi_lttng_element_event_rule_kernel_kprobe; +LTTNG_HIDDEN extern const char *const mi_lttng_element_event_rule_kernel_syscall; +LTTNG_HIDDEN extern const char + *const mi_lttng_element_event_rule_kernel_tracepoint; +LTTNG_HIDDEN extern const char *const mi_lttng_element_event_rule_kernel_uprobe; +LTTNG_HIDDEN extern const char *const mi_lttng_element_event_rule_log4j_logging; +LTTNG_HIDDEN extern const char *const mi_lttng_element_event_rule_python_logging; +LTTNG_HIDDEN extern const char + *const mi_lttng_element_event_rule_user_tracepoint; + +/* String related to lttng_event_rule_kernel_syscall. */ +LTTNG_HIDDEN extern const char + *const mi_lttng_element_event_rule_kernel_syscall_emission_site; + +/* String related to enum lttng_event_rule_kernel_syscall_emission_site. */ +LTTNG_HIDDEN extern const char *const + mi_lttng_event_rule_kernel_syscall_emission_site_entry_exit; +LTTNG_HIDDEN extern const char + *const mi_lttng_event_rule_kernel_syscall_emission_site_entry; +LTTNG_HIDDEN extern const char + *const mi_lttng_event_rule_kernel_syscall_emission_site_exit; + +LTTNG_HIDDEN extern const char *const + mi_lttng_element_event_rule_user_tracepoint_name_pattern_exclusions; +LTTNG_HIDDEN extern const char *const + mi_lttng_element_event_rule_user_tracepoint_name_pattern_exclusion; + +/* String related to log level rule. */ +LTTNG_HIDDEN extern const char *const mi_lttng_element_log_level_rule; +LTTNG_HIDDEN extern const char *const mi_lttng_element_log_level_rule_exactly; +LTTNG_HIDDEN extern const char + *const mi_lttng_element_log_level_rule_at_least_as_severe_as; +LTTNG_HIDDEN extern const char *const + mi_lttng_element_log_level_rule_at_least_as_severe_as_thre; +LTTNG_HIDDEN extern const char *const mi_lttng_element_log_level_rule_level; + +/* String related to kernel probe location. */ +LTTNG_HIDDEN extern const char *const mi_lttng_element_kernel_probe_location; +LTTNG_HIDDEN extern const char + *const mi_lttng_element_kernel_probe_location_symbol_offset; +LTTNG_HIDDEN extern const char *const + mi_lttng_element_kernel_probe_location_symbol_offset_name; +LTTNG_HIDDEN extern const char *const + mi_lttng_element_kernel_probe_location_symbol_offset_offset; +LTTNG_HIDDEN extern const char + *const mi_lttng_element_kernel_probe_location_address; +LTTNG_HIDDEN extern const char + *const mi_lttng_element_kernel_probe_location_address_address; + +/* String related to userspace probe location. */ +LTTNG_HIDDEN extern const char *const mi_lttng_element_userspace_probe_location; +LTTNG_HIDDEN extern const char + *const mi_lttng_element_userspace_probe_location_binary_path; +LTTNG_HIDDEN extern const char + *const mi_lttng_element_userspace_probe_location_function; +LTTNG_HIDDEN extern const char + *const mi_lttng_element_userspace_probe_location_function_name; +LTTNG_HIDDEN extern const char + *const mi_lttng_element_userspace_probe_location_lookup_method; +LTTNG_HIDDEN extern const char *const + mi_lttng_element_userspace_probe_location_lookup_method_function_default; +LTTNG_HIDDEN extern const char *const + mi_lttng_element_userspace_probe_location_lookup_method_function_elf; +LTTNG_HIDDEN extern const char *const + mi_lttng_element_userspace_probe_location_lookup_method_tracepoint_sdt; +LTTNG_HIDDEN extern const char + *const mi_lttng_element_userspace_probe_location_tracepoint; +LTTNG_HIDDEN extern const char *const + mi_lttng_element_userspace_probe_location_tracepoint_probe_name; +LTTNG_HIDDEN extern const char *const + mi_lttng_element_userspace_probe_location_tracepoint_provider_name; + +/* String related to enum + * lttng_userspace_probe_location_function_instrumentation_type */ +LTTNG_HIDDEN extern const char *const + mi_lttng_element_userspace_probe_location_function_instrumentation_type; +LTTNG_HIDDEN extern const char *const + mi_lttng_userspace_probe_location_function_instrumentation_type_entry; + +/* String related to trigger */ +LTTNG_HIDDEN extern const char *const mi_lttng_element_triggers; +LTTNG_HIDDEN extern const char *const mi_lttng_element_trigger; +LTTNG_HIDDEN extern const char *const mi_lttng_element_trigger_owner_uid; + +/* String related to error_query. */ +LTTNG_HIDDEN extern const char *const mi_lttng_element_error_query_result; +LTTNG_HIDDEN extern const char + *const mi_lttng_element_error_query_result_counter; +LTTNG_HIDDEN extern const char + *const mi_lttng_element_error_query_result_counter_value; +LTTNG_HIDDEN extern const char + *const mi_lttng_element_error_query_result_description; +LTTNG_HIDDEN extern const char *const mi_lttng_element_error_query_result_name; +LTTNG_HIDDEN extern const char *const mi_lttng_element_error_query_result_type; +LTTNG_HIDDEN extern const char *const mi_lttng_element_error_query_results; + /* String related to add-context command */ LTTNG_HIDDEN extern const char * const mi_lttng_element_context_symbol; @@ -792,7 +976,7 @@ int mi_lttng_snapshot_output_session_name(struct mi_writer *writer, * Negative values indicate an error. */ int mi_lttng_snapshot_list_output(struct mi_writer *writer, - struct lttng_snapshot_output *output); + const struct lttng_snapshot_output *output); /* * Machine interface of the output of the command snapshot del output diff --git a/src/common/snapshot.c b/src/common/snapshot.c index b0bebc81d..ec10f8d63 100644 --- a/src/common/snapshot.c +++ b/src/common/snapshot.c @@ -5,8 +5,10 @@ * */ -#include +#include +#include #include +#include #include #include #include @@ -177,3 +179,80 @@ end: lttng_snapshot_output_destroy(output); return ret; } + +LTTNG_HIDDEN +enum lttng_error_code lttng_snapshot_output_mi_serialize( + const struct lttng_snapshot_output *output, + struct mi_writer *writer) +{ + int ret; + enum lttng_error_code ret_code; + + assert(output); + assert(writer); + + /* Open output element. */ + ret = mi_lttng_writer_open_element(writer, + mi_lttng_element_action_snapshot_session_output); + if (ret) { + goto mi_error; + } + + /* Name. */ + if (strnlen(output->name, LTTNG_NAME_MAX) != 0) { + ret = mi_lttng_writer_write_element_string( + writer, config_element_name, output->name); + if (ret) { + goto mi_error; + } + } + + /* Control url (always present). */ + ret = mi_lttng_writer_write_element_string(writer, + mi_lttng_element_snapshot_ctrl_url, output->ctrl_url); + if (ret) { + goto mi_error; + } + + /* Data url (optional). */ + if (strnlen(output->data_url, PATH_MAX) != 0) { + ret = mi_lttng_writer_write_element_string(writer, + mi_lttng_element_snapshot_data_url, + output->data_url); + if (ret) { + goto mi_error; + } + } + + /* + * Maximum size in bytes of the snapshot meaning the total size of all + * streams combined. A value of 0 means unlimited. The default value is + * UINT64_MAX which also means unlimited in practice. + * + * The value is not serialized when it is set to either of those values + * to normalize them to '0'. + */ + if (output->max_size > 0 && output->max_size != UINT64_MAX) { + /* Total size of all stream combined. */ + ret = mi_lttng_writer_write_element_unsigned_int(writer, + mi_lttng_element_snapshot_max_size, + output->max_size); + if (ret) { + goto mi_error; + } + } + + /* Close output element. */ + ret = mi_lttng_writer_close_element(writer); + if (ret) { + goto mi_error; + } + + ret_code = LTTNG_OK; + goto end; + +mi_error: + ret_code = LTTNG_ERR_MI_IO_FAIL; +end: + return ret_code; +} diff --git a/src/common/snapshot.h b/src/common/snapshot.h index df02adaf9..3edcf16ae 100644 --- a/src/common/snapshot.h +++ b/src/common/snapshot.h @@ -16,6 +16,7 @@ struct lttng_payload_view; struct lttng_payload; struct lttng_snapshot_output; +struct mi_writer; LTTNG_HIDDEN bool lttng_snapshot_output_validate(const struct lttng_snapshot_output *output); @@ -35,4 +36,9 @@ ssize_t lttng_snapshot_output_create_from_payload( struct lttng_payload_view *view, struct lttng_snapshot_output **output_p); +LTTNG_HIDDEN +enum lttng_error_code lttng_snapshot_output_mi_serialize( + const struct lttng_snapshot_output *output, + struct mi_writer *writer); + #endif /* COMMON_SNAPSHOT_H */ diff --git a/src/common/trigger.c b/src/common/trigger.c index d740c80c7..8a88c6d91 100644 --- a/src/common/trigger.c +++ b/src/common/trigger.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -19,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -1018,3 +1020,201 @@ void lttng_trigger_unlock(struct lttng_trigger *trigger) { pthread_mutex_unlock(&trigger->lock); } + +LTTNG_HIDDEN +enum lttng_error_code lttng_trigger_mi_serialize(const struct lttng_trigger *trigger, + struct mi_writer *writer, + const struct mi_lttng_error_query_callbacks + *error_query_callbacks) +{ + int ret; + enum lttng_error_code ret_code; + enum lttng_trigger_status trigger_status; + const struct lttng_condition *condition = NULL; + const struct lttng_action *action = NULL; + struct lttng_dynamic_array action_path_indexes; + uid_t owner_uid; + + assert(trigger); + assert(writer); + + lttng_dynamic_array_init(&action_path_indexes, sizeof(uint64_t), NULL); + + /* Open trigger element. */ + ret = mi_lttng_writer_open_element(writer, mi_lttng_element_trigger); + if (ret) { + goto mi_error; + } + + trigger_status = lttng_trigger_get_owner_uid(trigger, &owner_uid); + assert(trigger_status == LTTNG_TRIGGER_STATUS_OK); + + /* Name. */ + ret = mi_lttng_writer_write_element_string( + writer, config_element_name, trigger->name); + if (ret) { + goto mi_error; + } + + /* Owner uid. */ + ret = mi_lttng_writer_write_element_signed_int(writer, + mi_lttng_element_trigger_owner_uid, + (int64_t) owner_uid); + if (ret) { + goto mi_error; + } + + /* Condition. */ + condition = lttng_trigger_get_const_condition(trigger); + assert(condition); + ret_code = lttng_condition_mi_serialize( + trigger, condition, writer, error_query_callbacks); + if (ret_code != LTTNG_OK) { + goto end; + } + + /* Action. */ + action = lttng_trigger_get_const_action(trigger); + assert(action); + ret_code = lttng_action_mi_serialize(trigger, action, writer, + error_query_callbacks, &action_path_indexes); + if (ret_code != LTTNG_OK) { + goto end; + } + + if (error_query_callbacks && error_query_callbacks->trigger_cb) { + struct lttng_error_query_results *results = NULL; + + ret_code = error_query_callbacks->trigger_cb(trigger, &results); + if (ret_code != LTTNG_OK) { + goto end; + } + + ret_code = lttng_error_query_results_mi_serialize( + results, writer); + lttng_error_query_results_destroy(results); + if (ret_code != LTTNG_OK) { + goto end; + } + } + + /* Close trigger element. */ + ret = mi_lttng_writer_close_element(writer); + if (ret) { + goto mi_error; + } + + ret_code = LTTNG_OK; + goto end; + +mi_error: + ret_code = LTTNG_ERR_MI_IO_FAIL; +end: + lttng_dynamic_array_reset(&action_path_indexes); + return ret_code; +} + +/* Used by qsort, which expects the semantics of strcmp(). */ +static int compare_triggers_by_name(const void *a, const void *b) +{ + const struct lttng_trigger *trigger_a = + *((const struct lttng_trigger **) a); + const struct lttng_trigger *trigger_b = + *((const struct lttng_trigger **) b); + const char *name_a, *name_b; + enum lttng_trigger_status trigger_status; + + /* Anonymous triggers are not reachable here. */ + trigger_status = lttng_trigger_get_name(trigger_a, &name_a); + assert(trigger_status == LTTNG_TRIGGER_STATUS_OK); + + trigger_status = lttng_trigger_get_name(trigger_b, &name_b); + assert(trigger_status == LTTNG_TRIGGER_STATUS_OK); + + return strcmp(name_a, name_b); +} + +LTTNG_HIDDEN +enum lttng_error_code lttng_triggers_mi_serialize(const struct lttng_triggers *triggers, + struct mi_writer *writer, + const struct mi_lttng_error_query_callbacks + *error_query_callbacks) +{ + int ret; + enum lttng_error_code ret_code; + enum lttng_trigger_status status; + unsigned int count, i; + struct lttng_dynamic_pointer_array sorted_triggers; + + assert(triggers); + assert(writer); + + /* + * Sort trigger by name to ensure an order at the MI level and ignore + * any anonymous trigger present. + */ + lttng_dynamic_pointer_array_init(&sorted_triggers, NULL); + + status = lttng_triggers_get_count(triggers, &count); + assert(status == LTTNG_TRIGGER_STATUS_OK); + + for (i = 0; i < count; i++) { + int add_ret; + const char *unused_name; + const struct lttng_trigger *trigger = + lttng_triggers_get_at_index(triggers, i); + + status = lttng_trigger_get_name(trigger, &unused_name); + switch (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 lttng_trigger to sorting array."); + ret_code = LTTNG_ERR_NOMEM; + goto error; + } + } + + qsort(sorted_triggers.array.buffer.data, count, + sizeof(struct lttng_trigger *), + compare_triggers_by_name); + + /* Open triggers element. */ + ret = mi_lttng_writer_open_element(writer, mi_lttng_element_triggers); + if (ret) { + ret_code = LTTNG_ERR_MI_IO_FAIL; + goto error; + } + + for (i = 0; i < lttng_dynamic_pointer_array_get_count(&sorted_triggers); i++) { + const struct lttng_trigger *trigger = + (const struct lttng_trigger *) + lttng_dynamic_pointer_array_get_pointer( + &sorted_triggers, i); + + lttng_trigger_mi_serialize(trigger, writer, error_query_callbacks); + } + + /* Close triggers element. */ + ret = mi_lttng_writer_close_element(writer); + if (ret) { + ret_code = LTTNG_ERR_MI_IO_FAIL; + goto error; + } + + ret_code = LTTNG_OK; + +error: + lttng_dynamic_pointer_array_reset(&sorted_triggers); + return ret_code; +} diff --git a/src/common/userspace-probe.c b/src/common/userspace-probe.c index a1a4d1fb3..67b0ee698 100644 --- a/src/common/userspace-probe.c +++ b/src/common/userspace-probe.c @@ -9,11 +9,12 @@ #include #include #include -#include -#include -#include #include #include +#include +#include +#include +#include #include #include #include @@ -31,6 +32,22 @@ int lttng_userspace_probe_location_tracepoint_set_binary_fd_handle( struct lttng_userspace_probe_location *location, struct fd_handle *binary_fd_handle); +static +enum lttng_error_code lttng_userspace_probe_location_lookup_method_mi_serialize( + const struct lttng_userspace_probe_location_lookup_method + *method, + struct mi_writer *writer); + +static +enum lttng_error_code lttng_userspace_probe_location_tracepoint_mi_serialize( + const struct lttng_userspace_probe_location *location, + struct mi_writer *writer); + +static +enum lttng_error_code lttng_userspace_probe_location_function_mi_serialize( + const struct lttng_userspace_probe_location *location, + struct mi_writer *writer); + enum lttng_userspace_probe_location_lookup_method_type lttng_userspace_probe_location_lookup_method_get_type( const struct lttng_userspace_probe_location_lookup_method *lookup_method) @@ -1965,3 +1982,284 @@ unsigned long lttng_userspace_probe_location_hash( { return location->hash(location); } + +LTTNG_HIDDEN +enum lttng_error_code lttng_userspace_probe_location_mi_serialize( + const struct lttng_userspace_probe_location *location, + struct mi_writer *writer) +{ + typedef enum lttng_error_code (*mi_fp)( + const struct lttng_userspace_probe_location *, + struct mi_writer *); + + int ret; + enum lttng_error_code ret_code; + mi_fp mi_function = NULL; + + assert(location); + assert(writer); + + switch (lttng_userspace_probe_location_get_type(location)) { + case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION: + mi_function = lttng_userspace_probe_location_function_mi_serialize; + break; + case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT: + mi_function = lttng_userspace_probe_location_tracepoint_mi_serialize; + break; + default: + abort(); + break; + } + + /* Open userspace probe location element. */ + ret = mi_lttng_writer_open_element( + writer, mi_lttng_element_userspace_probe_location); + if (ret) { + goto mi_error; + } + + /* Underlying user space probe location. */ + ret_code = mi_function(location, writer); + if (ret_code != LTTNG_OK) { + goto end; + } + + /* Close userspace probe location element. */ + ret = mi_lttng_writer_close_element(writer); + if (ret) { + goto mi_error; + } + + ret_code = LTTNG_OK; + goto end; + +mi_error: + ret_code = LTTNG_ERR_MI_IO_FAIL; +end: + return ret_code; +} + +enum lttng_error_code lttng_userspace_probe_location_lookup_method_mi_serialize( + const struct lttng_userspace_probe_location_lookup_method + *method, + struct mi_writer *writer) +{ + int ret; + enum lttng_error_code ret_code; + const char *type_element_str; + + assert(method); + assert(writer); + + switch (lttng_userspace_probe_location_lookup_method_get_type(method)) { + case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_DEFAULT: + type_element_str = + mi_lttng_element_userspace_probe_location_lookup_method_function_default; + break; + case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_ELF: + type_element_str = + mi_lttng_element_userspace_probe_location_lookup_method_function_elf; + break; + case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_TRACEPOINT_SDT: + type_element_str = + mi_lttng_element_userspace_probe_location_lookup_method_tracepoint_sdt; + break; + default: + abort(); + break; + } + + /* Open userspace probe location lookup method element. */ + ret = mi_lttng_writer_open_element(writer, + mi_lttng_element_userspace_probe_location_lookup_method); + if (ret) { + goto mi_error; + } + + /* User space probe location lookup method empty element. */ + ret = mi_lttng_writer_open_element(writer, type_element_str); + if (ret) { + goto mi_error; + } + + /* Close userspace probe location lookup method element. */ + ret = mi_lttng_close_multi_element(writer, 2); + if (ret) { + goto mi_error; + } + + ret_code = LTTNG_OK; + goto end; + +mi_error: + ret_code = LTTNG_ERR_MI_IO_FAIL; +end: + return ret_code; +} + +static enum lttng_error_code lttng_userspace_probe_location_tracepoint_mi_serialize( + const struct lttng_userspace_probe_location *location, + struct mi_writer *writer) +{ + int ret; + enum lttng_error_code ret_code; + const char *probe_name = NULL; + const char *provider_name = NULL; + const char *binary_path = NULL; + const struct lttng_userspace_probe_location_lookup_method + *lookup_method = NULL; + + assert(location); + assert(writer); + + probe_name = lttng_userspace_probe_location_tracepoint_get_probe_name( + location); + provider_name = lttng_userspace_probe_location_tracepoint_get_provider_name( + location); + binary_path = lttng_userspace_probe_location_tracepoint_get_binary_path( + location); + lookup_method = lttng_userspace_probe_location_tracepoint_get_lookup_method( + location); + + /* Open userspace probe location tracepoint element. */ + ret = mi_lttng_writer_open_element(writer, + mi_lttng_element_userspace_probe_location_tracepoint); + if (ret) { + goto mi_error; + } + + /* Probe name. */ + ret = mi_lttng_writer_write_element_string(writer, + mi_lttng_element_userspace_probe_location_tracepoint_probe_name, + probe_name); + if (ret) { + goto mi_error; + } + + /* Provider name. */ + ret = mi_lttng_writer_write_element_string(writer, + mi_lttng_element_userspace_probe_location_tracepoint_provider_name, + provider_name); + if (ret) { + goto mi_error; + } + + /* Binary path. */ + ret = mi_lttng_writer_write_element_string(writer, + mi_lttng_element_userspace_probe_location_binary_path, + binary_path); + if (ret) { + goto mi_error; + } + + /* The lookup method. */ + ret_code = lttng_userspace_probe_location_lookup_method_mi_serialize( + lookup_method, writer); + if (ret_code != LTTNG_OK) { + goto end; + } + + /* Close userspace probe location tracepoint. */ + ret = mi_lttng_writer_close_element(writer); + if (ret) { + goto mi_error; + } + + ret_code = LTTNG_OK; + goto end; + +mi_error: + ret_code = LTTNG_ERR_MI_IO_FAIL; +end: + return ret_code; +} + +static enum lttng_error_code lttng_userspace_probe_location_function_mi_serialize( + const struct lttng_userspace_probe_location *location, + struct mi_writer *writer) +{ + int ret; + enum lttng_error_code ret_code; + const char *function_name = NULL; + const char *binary_path = NULL; + const char *instrumentation_type_str = NULL; + enum lttng_userspace_probe_location_function_instrumentation_type + instrumentation_type; + const struct lttng_userspace_probe_location_lookup_method + *lookup_method = NULL; + + assert(location); + assert(writer); + + function_name = lttng_userspace_probe_location_function_get_function_name( + location); + binary_path = lttng_userspace_probe_location_function_get_binary_path( + location); + instrumentation_type = + lttng_userspace_probe_location_function_get_instrumentation_type( + location); + lookup_method = lttng_userspace_probe_location_function_get_lookup_method( + location); + + switch (instrumentation_type) { + case LTTNG_USERSPACE_PROBE_LOCATION_FUNCTION_INSTRUMENTATION_TYPE_ENTRY: + instrumentation_type_str = + mi_lttng_userspace_probe_location_function_instrumentation_type_entry; + break; + default: + abort(); + break; + } + + /* Open userspace probe location function element. */ + ret = mi_lttng_writer_open_element(writer, + mi_lttng_element_userspace_probe_location_function); + if (ret) { + goto mi_error; + } + + /* Function name. */ + ret = mi_lttng_writer_write_element_string(writer, + mi_lttng_element_userspace_probe_location_function_name, + function_name); + if (ret) { + goto mi_error; + } + + /* Binary path. */ + ret = mi_lttng_writer_write_element_string(writer, + mi_lttng_element_userspace_probe_location_binary_path, + binary_path); + if (ret) { + goto mi_error; + } + + /* Instrumentation type. */ + ret = mi_lttng_writer_write_element_string(writer, + mi_lttng_element_userspace_probe_location_function_instrumentation_type, + instrumentation_type_str); + if (ret) { + goto mi_error; + } + + /* The lookup method. */ + ret_code = lttng_userspace_probe_location_lookup_method_mi_serialize( + lookup_method, writer); + if (ret_code != LTTNG_OK) { + goto end; + } + + /* Close userspace probe location function element. */ + ret = mi_lttng_writer_close_element(writer); + if (ret) { + goto mi_error; + } + + ret_code = LTTNG_OK; + goto end; + +mi_error: + ret_code = LTTNG_ERR_MI_IO_FAIL; +end: + return ret_code; +} -- 2.34.1