2 * Copyright (C) 2021 Simon Marchi <simon.marchi@efficios.com>
4 * SPDX-License-Identifier: GPL-2.0-only
10 #include "../command.h"
12 #include "common/argpar/argpar.h"
13 #include "common/dynamic-array.h"
14 #include "common/mi-lttng.h"
15 /* For lttng_condition_type_str(). */
16 #include "lttng/condition/condition-internal.h"
17 /* For lttng_domain_type_str(). */
18 #include "lttng/domain-internal.h"
20 #ifdef LTTNG_EMBED_HELP
21 static const char help_msg
[] =
22 #include <lttng-list-triggers.1.h>
32 struct argpar_opt_descr list_trigger_options
[] = {
33 { OPT_HELP
, 'h', "help", false },
34 { OPT_LIST_OPTIONS
, '\0', "list-options", false },
35 ARGPAR_OPT_DESCR_SENTINEL
,
39 void print_event_rule_tracepoint(const struct lttng_event_rule
*event_rule
)
41 enum lttng_event_rule_status event_rule_status
;
42 enum lttng_domain_type domain_type
;
46 unsigned int exclusions_count
;
49 event_rule_status
= lttng_event_rule_tracepoint_get_pattern(
50 event_rule
, &pattern
);
51 assert(event_rule_status
== LTTNG_EVENT_RULE_STATUS_OK
);
53 event_rule_status
= lttng_event_rule_tracepoint_get_domain_type(
54 event_rule
, &domain_type
);
55 assert(event_rule_status
== LTTNG_EVENT_RULE_STATUS_OK
);
57 _MSG(" rule: %s (type: tracepoint, domain: %s", pattern
,
58 lttng_domain_type_str(domain_type
));
60 event_rule_status
= lttng_event_rule_tracepoint_get_filter(
62 if (event_rule_status
== LTTNG_EVENT_RULE_STATUS_OK
) {
63 _MSG(", filter: %s", filter
);
65 assert(event_rule_status
== LTTNG_EVENT_RULE_STATUS_UNSET
);
68 event_rule_status
= lttng_event_rule_tracepoint_get_log_level(
69 event_rule
, &log_level
);
70 if (event_rule_status
== LTTNG_EVENT_RULE_STATUS_OK
) {
71 enum lttng_loglevel_type log_level_type
;
72 const char *log_level_op
;
74 event_rule_status
= lttng_event_rule_tracepoint_get_log_level_type(
75 event_rule
, &log_level_type
);
76 assert(event_rule_status
== LTTNG_EVENT_RULE_STATUS_OK
);
77 assert(log_level_type
== LTTNG_EVENT_LOGLEVEL_RANGE
||
78 log_level_type
== LTTNG_EVENT_LOGLEVEL_SINGLE
);
80 log_level_op
= (log_level_type
== LTTNG_EVENT_LOGLEVEL_RANGE
? "<=" : "==");
82 _MSG(", log level %s %s", log_level_op
,
83 mi_lttng_loglevel_string(
84 log_level
, domain_type
));
86 assert(event_rule_status
== LTTNG_EVENT_RULE_STATUS_UNSET
);
89 event_rule_status
= lttng_event_rule_tracepoint_get_exclusions_count(
90 event_rule
, &exclusions_count
);
91 assert(event_rule_status
== LTTNG_EVENT_RULE_STATUS_OK
);
92 if (exclusions_count
> 0) {
93 _MSG(", exclusions: ");
94 for (i
= 0; i
< exclusions_count
; i
++) {
95 const char *exclusion
;
97 event_rule_status
= lttng_event_rule_tracepoint_get_exclusion_at_index(
98 event_rule
, i
, &exclusion
);
99 assert(event_rule_status
== LTTNG_EVENT_RULE_STATUS_OK
);
101 _MSG("%s%s", i
> 0 ? "," : "", exclusion
);
108 static void print_kernel_probe_location(
109 const struct lttng_kernel_probe_location
*location
)
111 enum lttng_kernel_probe_location_status status
;
112 switch (lttng_kernel_probe_location_get_type(location
)) {
113 case LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS
:
117 status
= lttng_kernel_probe_location_address_get_address(
119 if (status
!= LTTNG_KERNEL_PROBE_LOCATION_STATUS_OK
) {
120 ERR("Getting kernel probe location address failed.");
124 _MSG("0x%" PRIx64
, address
);
128 case LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET
:
131 const char *symbol_name
;
133 symbol_name
= lttng_kernel_probe_location_symbol_get_name(
136 ERR("Getting kernel probe location symbol name failed.");
140 status
= lttng_kernel_probe_location_symbol_get_offset(
142 if (status
!= LTTNG_KERNEL_PROBE_LOCATION_STATUS_OK
) {
143 ERR("Getting kernel probe location address failed.");
148 _MSG("%s", symbol_name
);
150 _MSG("%s+0x%" PRIx64
, symbol_name
, offset
);
163 void print_event_rule_kernel_probe(const struct lttng_event_rule
*event_rule
)
165 enum lttng_event_rule_status event_rule_status
;
167 const struct lttng_kernel_probe_location
*location
;
169 assert(lttng_event_rule_get_type(event_rule
) == LTTNG_EVENT_RULE_TYPE_KERNEL_PROBE
);
171 event_rule_status
= lttng_event_rule_kernel_probe_get_event_name(event_rule
, &name
);
172 if (event_rule_status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
173 ERR("Failed to get kprobe event rule's name.");
177 event_rule_status
= lttng_event_rule_kernel_probe_get_location(
178 event_rule
, &location
);
179 if (event_rule_status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
180 ERR("Failed to get kprobe event rule's location.");
184 _MSG(" rule: %s (type: probe, location: ", name
);
186 print_kernel_probe_location(location
);
195 void print_event_rule_userspace_probe(const struct lttng_event_rule
*event_rule
)
197 enum lttng_event_rule_status event_rule_status
;
199 const struct lttng_userspace_probe_location
*location
;
200 enum lttng_userspace_probe_location_type userspace_probe_location_type
;
202 assert(lttng_event_rule_get_type(event_rule
) == LTTNG_EVENT_RULE_TYPE_USERSPACE_PROBE
);
204 event_rule_status
= lttng_event_rule_userspace_probe_get_event_name(
206 if (event_rule_status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
207 ERR("Failed to get uprobe event rule's name.");
211 event_rule_status
= lttng_event_rule_userspace_probe_get_location(
212 event_rule
, &location
);
213 if (event_rule_status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
214 ERR("Failed to get uprobe event rule's location.");
218 _MSG(" rule: %s (type: userspace probe, location: ", name
);
220 userspace_probe_location_type
=
221 lttng_userspace_probe_location_get_type(location
);
223 switch (userspace_probe_location_type
) {
224 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION
:
226 const char *binary_path
, *function_name
;
228 binary_path
= lttng_userspace_probe_location_function_get_binary_path(
230 function_name
= lttng_userspace_probe_location_function_get_function_name(
233 _MSG("%s:%s", binary_path
, function_name
);
236 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT
:
237 _MSG("SDT not implemented yet");
250 void print_event_rule_syscall(const struct lttng_event_rule
*event_rule
)
252 const char *pattern
, *filter
;
253 enum lttng_event_rule_status event_rule_status
;
255 assert(lttng_event_rule_get_type(event_rule
) == LTTNG_EVENT_RULE_TYPE_SYSCALL
);
257 event_rule_status
= lttng_event_rule_syscall_get_pattern(
258 event_rule
, &pattern
);
259 assert(event_rule_status
== LTTNG_EVENT_RULE_STATUS_OK
);
261 _MSG(" rule: %s (type: syscall", pattern
);
263 event_rule_status
= lttng_event_rule_syscall_get_filter(
264 event_rule
, &filter
);
265 if (event_rule_status
== LTTNG_EVENT_RULE_STATUS_OK
) {
266 _MSG(", filter: %s", filter
);
268 assert(event_rule_status
== LTTNG_EVENT_RULE_STATUS_UNSET
);
275 void print_event_rule(const struct lttng_event_rule
*event_rule
)
277 const enum lttng_event_rule_type event_rule_type
=
278 lttng_event_rule_get_type(event_rule
);
280 switch (event_rule_type
) {
281 case LTTNG_EVENT_RULE_TYPE_TRACEPOINT
:
282 print_event_rule_tracepoint(event_rule
);
284 case LTTNG_EVENT_RULE_TYPE_KERNEL_PROBE
:
285 print_event_rule_kernel_probe(event_rule
);
287 case LTTNG_EVENT_RULE_TYPE_USERSPACE_PROBE
:
288 print_event_rule_userspace_probe(event_rule
);
290 case LTTNG_EVENT_RULE_TYPE_SYSCALL
:
291 print_event_rule_syscall(event_rule
);
299 void print_one_event_expr(const struct lttng_event_expr
*event_expr
)
301 enum lttng_event_expr_type type
;
303 type
= lttng_event_expr_get_type(event_expr
);
306 case LTTNG_EVENT_EXPR_TYPE_EVENT_PAYLOAD_FIELD
:
310 name
= lttng_event_expr_event_payload_field_get_name(
316 case LTTNG_EVENT_EXPR_TYPE_CHANNEL_CONTEXT_FIELD
:
320 name
= lttng_event_expr_channel_context_field_get_name(
322 _MSG("$ctx.%s", name
);
326 case LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD
:
328 const char *provider_name
;
329 const char *type_name
;
331 provider_name
= lttng_event_expr_app_specific_context_field_get_provider_name(
333 type_name
= lttng_event_expr_app_specific_context_field_get_type_name(
336 _MSG("$app.%s:%s", provider_name
, type_name
);
340 case LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT
:
343 const struct lttng_event_expr
*parent_expr
;
344 enum lttng_event_expr_status status
;
346 parent_expr
= lttng_event_expr_array_field_element_get_parent_expr(
348 assert(parent_expr
!= NULL
);
350 print_one_event_expr(parent_expr
);
352 status
= lttng_event_expr_array_field_element_get_index(
354 assert(status
== LTTNG_EVENT_EXPR_STATUS_OK
);
366 void print_condition_on_event(const struct lttng_condition
*condition
)
368 const struct lttng_event_rule
*event_rule
;
369 enum lttng_condition_status condition_status
;
370 unsigned int cap_desc_count
, i
;
373 lttng_condition_on_event_get_rule(condition
, &event_rule
);
374 assert(condition_status
== LTTNG_CONDITION_STATUS_OK
);
376 print_event_rule(event_rule
);
379 lttng_condition_on_event_get_capture_descriptor_count(
380 condition
, &cap_desc_count
);
381 assert(condition_status
== LTTNG_CONDITION_STATUS_OK
);
383 if (cap_desc_count
> 0) {
386 for (i
= 0; i
< cap_desc_count
; i
++) {
387 const struct lttng_event_expr
*cap_desc
=
388 lttng_condition_on_event_get_capture_descriptor_at_index(
392 print_one_event_expr(cap_desc
);
399 void print_one_action(const struct lttng_action
*action
)
401 enum lttng_action_type action_type
;
402 enum lttng_action_status action_status
;
405 action_type
= lttng_action_get_type(action
);
406 assert(action_type
!= LTTNG_ACTION_TYPE_GROUP
);
408 switch (action_type
) {
409 case LTTNG_ACTION_TYPE_NOTIFY
:
412 case LTTNG_ACTION_TYPE_START_SESSION
:
413 action_status
= lttng_action_start_session_get_session_name(
415 assert(action_status
== LTTNG_ACTION_STATUS_OK
);
416 MSG("start session `%s`", value
);
418 case LTTNG_ACTION_TYPE_STOP_SESSION
:
419 action_status
= lttng_action_stop_session_get_session_name(
421 assert(action_status
== LTTNG_ACTION_STATUS_OK
);
422 MSG("stop session `%s`", value
);
424 case LTTNG_ACTION_TYPE_ROTATE_SESSION
:
425 action_status
= lttng_action_rotate_session_get_session_name(
427 assert(action_status
== LTTNG_ACTION_STATUS_OK
);
428 MSG("rotate session `%s`", value
);
430 case LTTNG_ACTION_TYPE_SNAPSHOT_SESSION
:
432 const struct lttng_snapshot_output
*output
;
434 action_status
= lttng_action_snapshot_session_get_session_name(
436 assert(action_status
== LTTNG_ACTION_STATUS_OK
);
437 _MSG("snapshot session `%s`", value
);
439 action_status
= lttng_action_snapshot_session_get_output(
441 if (action_status
== LTTNG_ACTION_STATUS_OK
) {
444 const char *ctrl_url
, *data_url
;
445 bool starts_with_file
, starts_with_net
, starts_with_net6
;
447 ctrl_url
= lttng_snapshot_output_get_ctrl_url(output
);
448 assert(ctrl_url
&& strlen(ctrl_url
) > 0);
450 data_url
= lttng_snapshot_output_get_data_url(output
);
453 starts_with_file
= strncmp(ctrl_url
, "file://", strlen("file://")) == 0;
454 starts_with_net
= strncmp(ctrl_url
, "net://", strlen("net://")) == 0;
455 starts_with_net6
= strncmp(ctrl_url
, "net6://", strlen("net6://")) == 0;
457 if (ctrl_url
[0] == '/' || starts_with_file
) {
458 if (starts_with_file
) {
459 ctrl_url
+= strlen("file://");
462 _MSG(", path: %s", ctrl_url
);
463 } else if (starts_with_net
|| starts_with_net6
) {
464 _MSG(", url: %s", ctrl_url
);
466 assert(strlen(data_url
) > 0);
468 _MSG(", control url: %s, data url: %s", ctrl_url
, data_url
);
471 name
= lttng_snapshot_output_get_name(output
);
473 if (strlen(name
) > 0) {
474 _MSG(", name: %s", name
);
477 max_size
= lttng_snapshot_output_get_maxsize(output
);
478 if (max_size
!= -1ULL) {
479 _MSG(", max size: %" PRIu64
, max_size
);
493 void print_one_trigger(const struct lttng_trigger
*trigger
)
495 const struct lttng_condition
*condition
;
496 enum lttng_condition_type condition_type
;
497 const struct lttng_action
*action
;
498 enum lttng_action_type action_type
;
499 enum lttng_trigger_status trigger_status
;
501 enum lttng_trigger_firing_policy firing_policy_type
;
505 trigger_status
= lttng_trigger_get_name(trigger
, &name
);
506 assert(trigger_status
== LTTNG_TRIGGER_STATUS_OK
);
508 trigger_status
= lttng_trigger_get_owner_uid(trigger
, &trigger_uid
);
509 assert(trigger_status
== LTTNG_TRIGGER_STATUS_OK
);
511 MSG("- id: %s", name
);
512 MSG(" user id: %d", trigger_uid
);
514 trigger_status
= lttng_trigger_get_firing_policy(
515 trigger
, &firing_policy_type
, &threshold
);
516 if (trigger_status
!= LTTNG_TRIGGER_STATUS_OK
) {
517 ERR("Failed to get trigger's policy.");
521 switch (firing_policy_type
) {
522 case LTTNG_TRIGGER_FIRING_POLICY_EVERY_N
:
524 MSG(" firing policy: after every %" PRIu64
" occurences", threshold
);
527 case LTTNG_TRIGGER_FIRING_POLICY_ONCE_AFTER_N
:
528 MSG(" firing policy: once after %" PRIu64
" occurences", threshold
);
534 condition
= lttng_trigger_get_const_condition(trigger
);
535 condition_type
= lttng_condition_get_type(condition
);
536 MSG(" condition: %s", lttng_condition_type_str(condition_type
));
537 switch (condition_type
) {
538 case LTTNG_CONDITION_TYPE_ON_EVENT
:
539 print_condition_on_event(condition
);
542 MSG(" (condition type not handled in %s)", __func__
);
546 action
= lttng_trigger_get_const_action(trigger
);
547 action_type
= lttng_action_get_type(action
);
548 if (action_type
== LTTNG_ACTION_TYPE_GROUP
) {
549 unsigned int count
, i
;
550 enum lttng_action_status action_status
;
554 action_status
= lttng_action_group_get_count(action
, &count
);
555 assert(action_status
== LTTNG_ACTION_STATUS_OK
);
557 for (i
= 0; i
< count
; i
++) {
558 const struct lttng_action
*subaction
=
559 lttng_action_group_get_at_index(
563 print_one_action(subaction
);
567 print_one_action(action
);
575 int compare_triggers_by_name(const void *a
, const void *b
)
577 const struct lttng_trigger
*trigger_a
= *((const struct lttng_trigger
**) a
);
578 const struct lttng_trigger
*trigger_b
= *((const struct lttng_trigger
**) b
);
579 const char *name_a
, *name_b
;
580 enum lttng_trigger_status trigger_status
;
582 trigger_status
= lttng_trigger_get_name(trigger_a
, &name_a
);
583 assert(trigger_status
== LTTNG_TRIGGER_STATUS_OK
);
585 trigger_status
= lttng_trigger_get_name(trigger_b
, &name_b
);
586 assert(trigger_status
== LTTNG_TRIGGER_STATUS_OK
);
588 return strcmp(name_a
, name_b
);
591 int cmd_list_triggers(int argc
, const char **argv
)
594 struct argpar_parse_ret argpar_parse_ret
= {};
595 struct lttng_triggers
*triggers
= NULL
;
597 struct lttng_dynamic_pointer_array sorted_triggers
;
598 enum lttng_trigger_status trigger_status
;
599 unsigned int num_triggers
;
601 lttng_dynamic_pointer_array_init(&sorted_triggers
, NULL
);
603 argpar_parse_ret
= argpar_parse(
604 argc
- 1, argv
+ 1, list_trigger_options
, true);
605 if (!argpar_parse_ret
.items
) {
606 ERR("%s", argpar_parse_ret
.error
);
610 for (i
= 0; i
< argpar_parse_ret
.items
->n_items
; i
++) {
611 const struct argpar_item
*item
=
612 argpar_parse_ret
.items
->items
[i
];
614 if (item
->type
== ARGPAR_ITEM_TYPE_OPT
) {
615 const struct argpar_item_opt
*item_opt
=
616 (const struct argpar_item_opt
*) item
;
618 switch (item_opt
->descr
->id
) {
624 case OPT_LIST_OPTIONS
:
625 list_cmd_options_argpar(stdout
,
626 list_trigger_options
);
635 const struct argpar_item_non_opt
*item_non_opt
=
636 (const struct argpar_item_non_opt
*) item
;
638 ERR("Unexpected argument: %s", item_non_opt
->arg
);
642 ret
= lttng_list_triggers(&triggers
);
643 if (ret
!= LTTNG_OK
) {
644 ERR("Error listing triggers: %s.", lttng_strerror(-ret
));
648 trigger_status
= lttng_triggers_get_count(triggers
, &num_triggers
);
649 if (trigger_status
!= LTTNG_TRIGGER_STATUS_OK
) {
650 ERR("Failed to get trigger count.");
654 for (i
= 0; i
< num_triggers
; i
++) {
655 const int add_ret
= lttng_dynamic_pointer_array_add_pointer(
657 (void *) lttng_triggers_get_at_index(triggers
, i
));
660 ERR("Failed to allocate array of struct lttng_trigger *.");
665 qsort(sorted_triggers
.array
.buffer
.data
, num_triggers
,
666 sizeof(struct lttng_trigger
*),
667 compare_triggers_by_name
);
669 for (i
= 0; i
< num_triggers
; i
++) {
670 const struct lttng_trigger
*trigger_to_print
=
671 (const struct lttng_trigger
*)
672 lttng_dynamic_pointer_array_get_pointer(
673 &sorted_triggers
, i
);
675 print_one_trigger(trigger_to_print
);
685 argpar_parse_ret_fini(&argpar_parse_ret
);
686 lttng_triggers_destroy(triggers
);
687 lttng_dynamic_pointer_array_reset(&sorted_triggers
);