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 #include "lttng/condition/on-event.h"
18 #include "lttng/condition/on-event-internal.h"
19 /* For lttng_domain_type_str(). */
20 #include "lttng/domain-internal.h"
21 #include "../loglevel.h"
23 #ifdef LTTNG_EMBED_HELP
24 static const char help_msg
[] =
25 #include <lttng-list-triggers.1.h>
35 struct argpar_opt_descr list_trigger_options
[] = {
36 { OPT_HELP
, 'h', "help", false },
37 { OPT_LIST_OPTIONS
, '\0', "list-options", false },
38 ARGPAR_OPT_DESCR_SENTINEL
,
42 * Returns the human-readable log level name associated with a numerical value
43 * if there is one. The Log4j and JUL domains have discontinuous log level
44 * values (a value can fall between two labels). In those cases, NULL is
47 static const char *get_pretty_loglevel_name(
48 enum lttng_domain_type domain
, int loglevel
)
50 const char *name
= NULL
;
53 case LTTNG_DOMAIN_UST
:
54 name
= loglevel_value_to_name(loglevel
);
56 case LTTNG_DOMAIN_LOG4J
:
57 name
= loglevel_log4j_value_to_name(loglevel
);
59 case LTTNG_DOMAIN_JUL
:
60 name
= loglevel_jul_value_to_name(loglevel
);
62 case LTTNG_DOMAIN_PYTHON
:
63 name
= loglevel_python_value_to_name(loglevel
);
73 void print_event_rule_tracepoint(const struct lttng_event_rule
*event_rule
)
75 enum lttng_event_rule_status event_rule_status
;
76 enum lttng_domain_type domain_type
;
80 const struct lttng_log_level_rule
*log_level_rule
= NULL
;
81 unsigned int exclusions_count
;
84 event_rule_status
= lttng_event_rule_tracepoint_get_pattern(
85 event_rule
, &pattern
);
86 assert(event_rule_status
== LTTNG_EVENT_RULE_STATUS_OK
);
88 event_rule_status
= lttng_event_rule_tracepoint_get_domain_type(
89 event_rule
, &domain_type
);
90 assert(event_rule_status
== LTTNG_EVENT_RULE_STATUS_OK
);
92 _MSG(" rule: %s (type: tracepoint, domain: %s", pattern
,
93 lttng_domain_type_str(domain_type
));
95 event_rule_status
= lttng_event_rule_tracepoint_get_filter(
97 if (event_rule_status
== LTTNG_EVENT_RULE_STATUS_OK
) {
98 _MSG(", filter: %s", filter
);
100 assert(event_rule_status
== LTTNG_EVENT_RULE_STATUS_UNSET
);
103 event_rule_status
= lttng_event_rule_tracepoint_get_log_level_rule(
104 event_rule
, &log_level_rule
);
105 if (event_rule_status
== LTTNG_EVENT_RULE_STATUS_OK
) {
106 enum lttng_log_level_rule_status llr_status
;
107 const char *log_level_op
;
108 const char *pretty_loglevel_name
;
110 switch (lttng_log_level_rule_get_type(log_level_rule
)) {
111 case LTTNG_LOG_LEVEL_RULE_TYPE_EXACTLY
:
113 llr_status
= lttng_log_level_rule_exactly_get_level(
114 log_level_rule
, &log_level
);
116 case LTTNG_LOG_LEVEL_RULE_TYPE_AT_LEAST_AS_SEVERE_AS
:
117 log_level_op
= "at least";
118 llr_status
= lttng_log_level_rule_at_least_as_severe_as_get_level(
119 log_level_rule
, &log_level
);
125 assert(llr_status
== LTTNG_LOG_LEVEL_RULE_STATUS_OK
);
127 pretty_loglevel_name
= get_pretty_loglevel_name(
128 domain_type
, log_level
);
129 if (pretty_loglevel_name
) {
130 _MSG(", log level %s %s", log_level_op
,
131 pretty_loglevel_name
);
133 _MSG(", log level %s %d", log_level_op
, log_level
);
136 assert(event_rule_status
== LTTNG_EVENT_RULE_STATUS_UNSET
);
139 event_rule_status
= lttng_event_rule_tracepoint_get_exclusions_count(
140 event_rule
, &exclusions_count
);
141 assert(event_rule_status
== LTTNG_EVENT_RULE_STATUS_OK
);
142 if (exclusions_count
> 0) {
143 _MSG(", exclusions: ");
144 for (i
= 0; i
< exclusions_count
; i
++) {
145 const char *exclusion
;
147 event_rule_status
= lttng_event_rule_tracepoint_get_exclusion_at_index(
148 event_rule
, i
, &exclusion
);
149 assert(event_rule_status
== LTTNG_EVENT_RULE_STATUS_OK
);
151 _MSG("%s%s", i
> 0 ? "," : "", exclusion
);
158 static void print_kernel_probe_location(
159 const struct lttng_kernel_probe_location
*location
)
161 enum lttng_kernel_probe_location_status status
;
162 switch (lttng_kernel_probe_location_get_type(location
)) {
163 case LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS
:
167 status
= lttng_kernel_probe_location_address_get_address(
169 if (status
!= LTTNG_KERNEL_PROBE_LOCATION_STATUS_OK
) {
170 ERR("Getting kernel probe location address failed.");
174 _MSG("0x%" PRIx64
, address
);
178 case LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET
:
181 const char *symbol_name
;
183 symbol_name
= lttng_kernel_probe_location_symbol_get_name(
186 ERR("Getting kernel probe location symbol name failed.");
190 status
= lttng_kernel_probe_location_symbol_get_offset(
192 if (status
!= LTTNG_KERNEL_PROBE_LOCATION_STATUS_OK
) {
193 ERR("Getting kernel probe location address failed.");
198 _MSG("%s", symbol_name
);
200 _MSG("%s+0x%" PRIx64
, symbol_name
, offset
);
213 void print_event_rule_kernel_probe(const struct lttng_event_rule
*event_rule
)
215 enum lttng_event_rule_status event_rule_status
;
217 const struct lttng_kernel_probe_location
*location
;
219 assert(lttng_event_rule_get_type(event_rule
) == LTTNG_EVENT_RULE_TYPE_KERNEL_PROBE
);
221 event_rule_status
= lttng_event_rule_kernel_probe_get_event_name(event_rule
, &name
);
222 if (event_rule_status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
223 ERR("Failed to get kprobe event rule's name.");
227 event_rule_status
= lttng_event_rule_kernel_probe_get_location(
228 event_rule
, &location
);
229 if (event_rule_status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
230 ERR("Failed to get kprobe event rule's location.");
234 _MSG(" rule: %s (type: probe, location: ", name
);
236 print_kernel_probe_location(location
);
245 void print_event_rule_userspace_probe(const struct lttng_event_rule
*event_rule
)
247 enum lttng_event_rule_status event_rule_status
;
249 const struct lttng_userspace_probe_location
*location
;
250 enum lttng_userspace_probe_location_type userspace_probe_location_type
;
252 assert(lttng_event_rule_get_type(event_rule
) == LTTNG_EVENT_RULE_TYPE_USERSPACE_PROBE
);
254 event_rule_status
= lttng_event_rule_userspace_probe_get_event_name(
256 if (event_rule_status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
257 ERR("Failed to get uprobe event rule's name.");
261 event_rule_status
= lttng_event_rule_userspace_probe_get_location(
262 event_rule
, &location
);
263 if (event_rule_status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
264 ERR("Failed to get uprobe event rule's location.");
268 _MSG(" rule: %s (type: userspace probe, location: ", name
);
270 userspace_probe_location_type
=
271 lttng_userspace_probe_location_get_type(location
);
273 switch (userspace_probe_location_type
) {
274 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION
:
276 const char *binary_path
, *function_name
;
278 binary_path
= lttng_userspace_probe_location_function_get_binary_path(
280 function_name
= lttng_userspace_probe_location_function_get_function_name(
283 _MSG("%s:%s", binary_path
, function_name
);
286 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT
:
287 _MSG("SDT not implemented yet");
300 void print_event_rule_syscall(const struct lttng_event_rule
*event_rule
)
302 const char *pattern
, *filter
;
303 enum lttng_event_rule_status event_rule_status
;
305 assert(lttng_event_rule_get_type(event_rule
) == LTTNG_EVENT_RULE_TYPE_SYSCALL
);
307 event_rule_status
= lttng_event_rule_syscall_get_pattern(
308 event_rule
, &pattern
);
309 assert(event_rule_status
== LTTNG_EVENT_RULE_STATUS_OK
);
311 _MSG(" rule: %s (type: syscall", pattern
);
313 event_rule_status
= lttng_event_rule_syscall_get_filter(
314 event_rule
, &filter
);
315 if (event_rule_status
== LTTNG_EVENT_RULE_STATUS_OK
) {
316 _MSG(", filter: %s", filter
);
318 assert(event_rule_status
== LTTNG_EVENT_RULE_STATUS_UNSET
);
325 void print_event_rule(const struct lttng_event_rule
*event_rule
)
327 const enum lttng_event_rule_type event_rule_type
=
328 lttng_event_rule_get_type(event_rule
);
330 switch (event_rule_type
) {
331 case LTTNG_EVENT_RULE_TYPE_TRACEPOINT
:
332 print_event_rule_tracepoint(event_rule
);
334 case LTTNG_EVENT_RULE_TYPE_KERNEL_PROBE
:
335 print_event_rule_kernel_probe(event_rule
);
337 case LTTNG_EVENT_RULE_TYPE_USERSPACE_PROBE
:
338 print_event_rule_userspace_probe(event_rule
);
340 case LTTNG_EVENT_RULE_TYPE_SYSCALL
:
341 print_event_rule_syscall(event_rule
);
349 void print_one_event_expr(const struct lttng_event_expr
*event_expr
)
351 enum lttng_event_expr_type type
;
353 type
= lttng_event_expr_get_type(event_expr
);
356 case LTTNG_EVENT_EXPR_TYPE_EVENT_PAYLOAD_FIELD
:
360 name
= lttng_event_expr_event_payload_field_get_name(
366 case LTTNG_EVENT_EXPR_TYPE_CHANNEL_CONTEXT_FIELD
:
370 name
= lttng_event_expr_channel_context_field_get_name(
372 _MSG("$ctx.%s", name
);
376 case LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD
:
378 const char *provider_name
;
379 const char *type_name
;
381 provider_name
= lttng_event_expr_app_specific_context_field_get_provider_name(
383 type_name
= lttng_event_expr_app_specific_context_field_get_type_name(
386 _MSG("$app.%s:%s", provider_name
, type_name
);
390 case LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT
:
393 const struct lttng_event_expr
*parent_expr
;
394 enum lttng_event_expr_status status
;
396 parent_expr
= lttng_event_expr_array_field_element_get_parent_expr(
398 assert(parent_expr
!= NULL
);
400 print_one_event_expr(parent_expr
);
402 status
= lttng_event_expr_array_field_element_get_index(
404 assert(status
== LTTNG_EVENT_EXPR_STATUS_OK
);
416 void print_condition_on_event(const struct lttng_condition
*condition
)
418 const struct lttng_event_rule
*event_rule
;
419 enum lttng_condition_status condition_status
;
420 unsigned int cap_desc_count
, i
;
421 uint64_t error_count
;
424 lttng_condition_on_event_get_rule(condition
, &event_rule
);
425 assert(condition_status
== LTTNG_CONDITION_STATUS_OK
);
427 print_event_rule(event_rule
);
430 lttng_condition_on_event_get_capture_descriptor_count(
431 condition
, &cap_desc_count
);
432 assert(condition_status
== LTTNG_CONDITION_STATUS_OK
);
434 error_count
= lttng_condition_on_event_get_error_count(condition
);
435 MSG(" tracer notifications discarded: %" PRIu64
, error_count
);
437 if (cap_desc_count
> 0) {
440 for (i
= 0; i
< cap_desc_count
; i
++) {
441 const struct lttng_event_expr
*cap_desc
=
442 lttng_condition_on_event_get_capture_descriptor_at_index(
446 print_one_event_expr(cap_desc
);
453 void print_one_action(const struct lttng_action
*action
)
455 enum lttng_action_type action_type
;
456 enum lttng_action_status action_status
;
459 action_type
= lttng_action_get_type(action
);
460 assert(action_type
!= LTTNG_ACTION_TYPE_GROUP
);
462 switch (action_type
) {
463 case LTTNG_ACTION_TYPE_NOTIFY
:
466 case LTTNG_ACTION_TYPE_START_SESSION
:
467 action_status
= lttng_action_start_session_get_session_name(
469 assert(action_status
== LTTNG_ACTION_STATUS_OK
);
470 MSG("start session `%s`", value
);
472 case LTTNG_ACTION_TYPE_STOP_SESSION
:
473 action_status
= lttng_action_stop_session_get_session_name(
475 assert(action_status
== LTTNG_ACTION_STATUS_OK
);
476 MSG("stop session `%s`", value
);
478 case LTTNG_ACTION_TYPE_ROTATE_SESSION
:
479 action_status
= lttng_action_rotate_session_get_session_name(
481 assert(action_status
== LTTNG_ACTION_STATUS_OK
);
482 MSG("rotate session `%s`", value
);
484 case LTTNG_ACTION_TYPE_SNAPSHOT_SESSION
:
486 const struct lttng_snapshot_output
*output
;
488 action_status
= lttng_action_snapshot_session_get_session_name(
490 assert(action_status
== LTTNG_ACTION_STATUS_OK
);
491 _MSG("snapshot session `%s`", value
);
493 action_status
= lttng_action_snapshot_session_get_output(
495 if (action_status
== LTTNG_ACTION_STATUS_OK
) {
498 const char *ctrl_url
, *data_url
;
499 bool starts_with_file
, starts_with_net
, starts_with_net6
;
501 ctrl_url
= lttng_snapshot_output_get_ctrl_url(output
);
502 assert(ctrl_url
&& strlen(ctrl_url
) > 0);
504 data_url
= lttng_snapshot_output_get_data_url(output
);
507 starts_with_file
= strncmp(ctrl_url
, "file://", strlen("file://")) == 0;
508 starts_with_net
= strncmp(ctrl_url
, "net://", strlen("net://")) == 0;
509 starts_with_net6
= strncmp(ctrl_url
, "net6://", strlen("net6://")) == 0;
511 if (ctrl_url
[0] == '/' || starts_with_file
) {
512 if (starts_with_file
) {
513 ctrl_url
+= strlen("file://");
516 _MSG(", path: %s", ctrl_url
);
517 } else if (starts_with_net
|| starts_with_net6
) {
518 _MSG(", url: %s", ctrl_url
);
520 assert(strlen(data_url
) > 0);
522 _MSG(", control url: %s, data url: %s", ctrl_url
, data_url
);
525 name
= lttng_snapshot_output_get_name(output
);
527 if (strlen(name
) > 0) {
528 _MSG(", name: %s", name
);
531 max_size
= lttng_snapshot_output_get_maxsize(output
);
532 if (max_size
!= -1ULL) {
533 _MSG(", max size: %" PRIu64
, max_size
);
547 void print_one_trigger(const struct lttng_trigger
*trigger
)
549 const struct lttng_condition
*condition
;
550 enum lttng_condition_type condition_type
;
551 const struct lttng_action
*action
;
552 enum lttng_action_type action_type
;
553 enum lttng_trigger_status trigger_status
;
555 enum lttng_trigger_firing_policy firing_policy_type
;
559 trigger_status
= lttng_trigger_get_name(trigger
, &name
);
560 assert(trigger_status
== LTTNG_TRIGGER_STATUS_OK
);
562 trigger_status
= lttng_trigger_get_owner_uid(trigger
, &trigger_uid
);
563 assert(trigger_status
== LTTNG_TRIGGER_STATUS_OK
);
565 MSG("- id: %s", name
);
566 MSG(" user id: %d", trigger_uid
);
568 trigger_status
= lttng_trigger_get_firing_policy(
569 trigger
, &firing_policy_type
, &threshold
);
570 if (trigger_status
!= LTTNG_TRIGGER_STATUS_OK
) {
571 ERR("Failed to get trigger's policy.");
575 switch (firing_policy_type
) {
576 case LTTNG_TRIGGER_FIRING_POLICY_EVERY_N
:
578 MSG(" firing policy: after every %" PRIu64
" occurences", threshold
);
581 case LTTNG_TRIGGER_FIRING_POLICY_ONCE_AFTER_N
:
582 MSG(" firing policy: once after %" PRIu64
" occurences", threshold
);
588 condition
= lttng_trigger_get_const_condition(trigger
);
589 condition_type
= lttng_condition_get_type(condition
);
590 MSG(" condition: %s", lttng_condition_type_str(condition_type
));
591 switch (condition_type
) {
592 case LTTNG_CONDITION_TYPE_ON_EVENT
:
593 print_condition_on_event(condition
);
596 MSG(" (condition type not handled in %s)", __func__
);
600 action
= lttng_trigger_get_const_action(trigger
);
601 action_type
= lttng_action_get_type(action
);
602 if (action_type
== LTTNG_ACTION_TYPE_GROUP
) {
603 unsigned int count
, i
;
604 enum lttng_action_status action_status
;
608 action_status
= lttng_action_group_get_count(action
, &count
);
609 assert(action_status
== LTTNG_ACTION_STATUS_OK
);
611 for (i
= 0; i
< count
; i
++) {
612 const struct lttng_action
*subaction
=
613 lttng_action_group_get_at_index(
617 print_one_action(subaction
);
621 print_one_action(action
);
629 int compare_triggers_by_name(const void *a
, const void *b
)
631 const struct lttng_trigger
*trigger_a
= *((const struct lttng_trigger
**) a
);
632 const struct lttng_trigger
*trigger_b
= *((const struct lttng_trigger
**) b
);
633 const char *name_a
, *name_b
;
634 enum lttng_trigger_status trigger_status
;
636 trigger_status
= lttng_trigger_get_name(trigger_a
, &name_a
);
637 assert(trigger_status
== LTTNG_TRIGGER_STATUS_OK
);
639 trigger_status
= lttng_trigger_get_name(trigger_b
, &name_b
);
640 assert(trigger_status
== LTTNG_TRIGGER_STATUS_OK
);
642 return strcmp(name_a
, name_b
);
645 int cmd_list_triggers(int argc
, const char **argv
)
648 struct argpar_parse_ret argpar_parse_ret
= {};
649 struct lttng_triggers
*triggers
= NULL
;
651 struct lttng_dynamic_pointer_array sorted_triggers
;
652 enum lttng_trigger_status trigger_status
;
653 unsigned int num_triggers
;
655 lttng_dynamic_pointer_array_init(&sorted_triggers
, NULL
);
657 argpar_parse_ret
= argpar_parse(
658 argc
- 1, argv
+ 1, list_trigger_options
, true);
659 if (!argpar_parse_ret
.items
) {
660 ERR("%s", argpar_parse_ret
.error
);
664 for (i
= 0; i
< argpar_parse_ret
.items
->n_items
; i
++) {
665 const struct argpar_item
*item
=
666 argpar_parse_ret
.items
->items
[i
];
668 if (item
->type
== ARGPAR_ITEM_TYPE_OPT
) {
669 const struct argpar_item_opt
*item_opt
=
670 (const struct argpar_item_opt
*) item
;
672 switch (item_opt
->descr
->id
) {
678 case OPT_LIST_OPTIONS
:
679 list_cmd_options_argpar(stdout
,
680 list_trigger_options
);
689 const struct argpar_item_non_opt
*item_non_opt
=
690 (const struct argpar_item_non_opt
*) item
;
692 ERR("Unexpected argument: %s", item_non_opt
->arg
);
696 ret
= lttng_list_triggers(&triggers
);
697 if (ret
!= LTTNG_OK
) {
698 ERR("Error listing triggers: %s.", lttng_strerror(-ret
));
702 trigger_status
= lttng_triggers_get_count(triggers
, &num_triggers
);
703 if (trigger_status
!= LTTNG_TRIGGER_STATUS_OK
) {
704 ERR("Failed to get trigger count.");
708 for (i
= 0; i
< num_triggers
; i
++) {
709 const int add_ret
= lttng_dynamic_pointer_array_add_pointer(
711 (void *) lttng_triggers_get_at_index(triggers
, i
));
714 ERR("Failed to allocate array of struct lttng_trigger *.");
719 qsort(sorted_triggers
.array
.buffer
.data
, num_triggers
,
720 sizeof(struct lttng_trigger
*),
721 compare_triggers_by_name
);
723 for (i
= 0; i
< num_triggers
; i
++) {
724 const struct lttng_trigger
*trigger_to_print
=
725 (const struct lttng_trigger
*)
726 lttng_dynamic_pointer_array_get_pointer(
727 &sorted_triggers
, i
);
729 print_one_trigger(trigger_to_print
);
739 argpar_parse_ret_fini(&argpar_parse_ret
);
740 lttng_triggers_destroy(triggers
);
741 lttng_dynamic_pointer_array_reset(&sorted_triggers
);