2 * Copyright (C) 2011 EfficiOS Inc.
4 * SPDX-License-Identifier: GPL-2.0-only
9 #include <common/compat/getenv.hpp>
10 #include <common/compat/string.hpp>
11 #include <common/make-unique-wrapper.hpp>
12 #include <common/sessiond-comm/sessiond-comm.hpp>
13 #include <common/string-utils/string-utils.hpp>
14 #include <common/utils.hpp>
24 #include <sys/types.h>
29 #include "../command.hpp"
30 #include "../loglevel.hpp"
31 #include "../uprobe.hpp"
33 #include <common/mi-lttng.hpp>
35 #include <lttng/domain-internal.hpp>
36 #include <lttng/event-internal.hpp>
38 #if (LTTNG_SYMBOL_NAME_LEN == 256)
39 #define LTTNG_SYMBOL_NAME_LEN_SCANF_IS_A_BROKEN_API "255"
43 void _mi_lttng_writer_deleter_func(mi_writer
*writer
)
45 if (writer
&& mi_lttng_writer_destroy(writer
)) {
46 LTTNG_THROW_ERROR("Failed to destroy mi_writer instance");
50 using mi_writer_uptr
= std::unique_ptr
<
52 lttng::memory::create_deleter_class
<mi_writer
, _mi_lttng_writer_deleter_func
>::deleter
>;
53 using event_rule_patterns
= std::vector
<std::string
>;
56 const char *opt_loglevel
;
57 int opt_loglevel_type
;
59 char *opt_session_name
;
66 char *opt_userspace_probe
;
68 char *opt_channel_name
;
72 struct lttng_handle
*handle
;
73 mi_writer_uptr writer
;
75 #ifdef LTTNG_EMBED_HELP
76 static const char help_msg
[] =
77 #include <lttng-enable-event.1.h>
96 struct poptOption long_options
[] = {
97 /* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
98 { "help", 'h', POPT_ARG_NONE
, nullptr, OPT_HELP
, nullptr, nullptr },
99 { "session", 's', POPT_ARG_STRING
, &opt_session_name
, 0, nullptr, nullptr },
100 { "all", 'a', POPT_ARG_VAL
, &opt_enable_all
, 1, nullptr, nullptr },
101 { "channel", 'c', POPT_ARG_STRING
, &opt_channel_name
, 0, nullptr, nullptr },
102 { "kernel", 'k', POPT_ARG_VAL
, &opt_kernel
, 1, nullptr, nullptr },
103 { "userspace", 'u', POPT_ARG_NONE
, nullptr, OPT_USERSPACE
, nullptr, nullptr },
104 { "jul", 'j', POPT_ARG_VAL
, &opt_jul
, 1, nullptr, nullptr },
105 { "log4j", 'l', POPT_ARG_VAL
, &opt_log4j
, 1, nullptr, nullptr },
106 { "python", 'p', POPT_ARG_VAL
, &opt_python
, 1, nullptr, nullptr },
107 { "tracepoint", 0, POPT_ARG_NONE
, nullptr, OPT_TRACEPOINT
, nullptr, nullptr },
108 { "probe", 0, POPT_ARG_STRING
, &opt_probe
, OPT_PROBE
, nullptr, nullptr },
112 &opt_userspace_probe
,
116 { "function", 0, POPT_ARG_STRING
, &opt_function
, OPT_FUNCTION
, nullptr, nullptr },
117 { "syscall", 0, POPT_ARG_NONE
, nullptr, OPT_SYSCALL
, nullptr, nullptr },
118 { "loglevel", 0, POPT_ARG_STRING
, nullptr, OPT_LOGLEVEL
, nullptr, nullptr },
119 { "loglevel-only", 0, POPT_ARG_STRING
, nullptr, OPT_LOGLEVEL_ONLY
, nullptr, nullptr },
120 { "list-options", 0, POPT_ARG_NONE
, nullptr, OPT_LIST_OPTIONS
, nullptr, nullptr },
121 { "filter", 'f', POPT_ARG_STRING
, &opt_filter
, OPT_FILTER
, nullptr, nullptr },
122 { "exclude", 'x', POPT_ARG_STRING
, &opt_exclude
, OPT_EXCLUDE
, nullptr, nullptr },
123 { nullptr, 0, 0, nullptr, 0, nullptr, nullptr }
127 * Parse probe options.
129 int parse_probe_opts(struct lttng_event
*ev
, char *opt
)
131 int ret
= CMD_SUCCESS
;
134 #define S_HEX_LEN_SCANF_IS_A_BROKEN_API "18" /* 18 is (19 - 1) (\0 is extra) */
135 char name
[LTTNG_SYMBOL_NAME_LEN
];
137 if (opt
== nullptr) {
142 /* Check for symbol+offset */
144 "%" LTTNG_SYMBOL_NAME_LEN_SCANF_IS_A_BROKEN_API
145 "[^'+']+%" S_HEX_LEN_SCANF_IS_A_BROKEN_API
"s",
149 strncpy(ev
->attr
.probe
.symbol_name
, name
, LTTNG_SYMBOL_NAME_LEN
);
150 ev
->attr
.probe
.symbol_name
[LTTNG_SYMBOL_NAME_LEN
- 1] = '\0';
151 DBG("probe symbol %s", ev
->attr
.probe
.symbol_name
);
152 if (*s_hex
== '\0') {
153 ERR("Invalid probe offset %s", s_hex
);
157 ev
->attr
.probe
.offset
= strtoull(s_hex
, nullptr, 0);
158 DBG("probe offset %" PRIu64
, ev
->attr
.probe
.offset
);
159 ev
->attr
.probe
.addr
= 0;
163 /* Check for symbol */
164 if (isalpha(name
[0]) || name
[0] == '_') {
165 match
= sscanf(opt
, "%" LTTNG_SYMBOL_NAME_LEN_SCANF_IS_A_BROKEN_API
"s", name
);
167 strncpy(ev
->attr
.probe
.symbol_name
, name
, LTTNG_SYMBOL_NAME_LEN
);
168 ev
->attr
.probe
.symbol_name
[LTTNG_SYMBOL_NAME_LEN
- 1] = '\0';
169 DBG("probe symbol %s", ev
->attr
.probe
.symbol_name
);
170 ev
->attr
.probe
.offset
= 0;
171 DBG("probe offset %" PRIu64
, ev
->attr
.probe
.offset
);
172 ev
->attr
.probe
.addr
= 0;
177 /* Check for address */
178 match
= sscanf(opt
, "%" S_HEX_LEN_SCANF_IS_A_BROKEN_API
"s", s_hex
);
181 * Return an error if the first character of the tentative
182 * address is NULL or not a digit. It can be "0" if the address
183 * is in hexadecimal and can be 1 to 9 if it's in decimal.
185 if (*s_hex
== '\0' || !isdigit(*s_hex
)) {
186 ERR("Invalid probe description %s", s_hex
);
190 ev
->attr
.probe
.addr
= strtoull(s_hex
, nullptr, 0);
191 DBG("probe addr %" PRIu64
, ev
->attr
.probe
.addr
);
192 ev
->attr
.probe
.offset
= 0;
193 memset(ev
->attr
.probe
.symbol_name
, 0, LTTNG_SYMBOL_NAME_LEN
);
204 const char *print_channel_name(const char *name
)
206 return name
?: DEFAULT_CHANNEL_NAME
;
209 const char *print_raw_channel_name(const char *name
)
211 return name
?: "<default>";
215 * Mi print exlcusion list
217 int mi_print_exclusion(const struct lttng_dynamic_pointer_array
*exclusions
)
221 const size_t count
= lttng_dynamic_pointer_array_get_count(exclusions
);
223 LTTNG_ASSERT(writer
);
230 ret
= mi_lttng_writer_open_element(writer
.get(), config_element_exclusions
);
235 for (i
= 0; i
< count
; i
++) {
236 const char *exclusion
=
237 (const char *) lttng_dynamic_pointer_array_get_pointer(exclusions
, i
);
239 ret
= mi_lttng_writer_write_element_string(
240 writer
.get(), config_element_exclusion
, exclusion
);
246 /* Close exclusions element */
247 ret
= mi_lttng_writer_close_element(writer
.get());
254 * Return allocated string for pretty-printing exclusion names.
256 char *print_exclusions(const struct lttng_dynamic_pointer_array
*exclusions
)
260 const char preamble
[] = " excluding ";
262 const size_t count
= lttng_dynamic_pointer_array_get_count(exclusions
);
268 /* Calculate total required length. */
269 for (i
= 0; i
< count
; i
++) {
270 const char *exclusion
=
271 (const char *) lttng_dynamic_pointer_array_get_pointer(exclusions
, i
);
273 length
+= strlen(exclusion
) + 4;
276 length
+= sizeof(preamble
);
277 ret
= calloc
<char>(length
);
282 strncpy(ret
, preamble
, length
);
283 for (i
= 0; i
< count
; i
++) {
284 const char *exclusion
=
285 (const char *) lttng_dynamic_pointer_array_get_pointer(exclusions
, i
);
288 strcat(ret
, exclusion
);
290 if (i
!= count
- 1) {
298 int check_exclusion_subsets(const char *pattern
, const char *exclusion
)
302 const char *e
= pattern
;
303 const char *x
= exclusion
;
305 /* Scan both the excluder and the event letter by letter */
319 /* Event is a subset of the excluder */
320 ERR("Event %s: %s excludes all events from %s", pattern
, exclusion
, pattern
);
326 * Reached the end of the event name before the
327 * end of the exclusion: this is valid.
349 WARN("Event %s: %s does not exclude any events from %s",
358 int create_exclusion_list_and_validate(const char *pattern
,
359 const char *exclusions_arg
,
360 struct lttng_dynamic_pointer_array
*exclusions
)
364 /* Split exclusions. */
365 ret
= strutils_split(exclusions_arg
, ',', true, exclusions
);
370 if (validate_exclusion_list(pattern
, exclusions
) != 0) {
378 lttng_dynamic_pointer_array_reset(exclusions
);
384 void warn_on_truncated_exclusion_names(const struct lttng_dynamic_pointer_array
*exclusions
,
388 const size_t num_exclusions
= lttng_dynamic_pointer_array_get_count(exclusions
);
390 for (i
= 0; i
< num_exclusions
; i
++) {
391 const char *const exclusion
=
392 (const char *) lttng_dynamic_pointer_array_get_pointer(exclusions
, i
);
394 if (strlen(exclusion
) >= LTTNG_SYMBOL_NAME_LEN
) {
395 WARN("Event exclusion \"%s\" will be truncated", exclusion
);
402 * Enabling event using the lttng API.
403 * Note: in case of error only the last error code will be return.
405 int enable_events(const std::string
& session_name
, const event_rule_patterns
& patterns
)
407 int ret
= CMD_SUCCESS
, command_ret
= CMD_SUCCESS
;
408 int error_holder
= CMD_SUCCESS
, warn
= 0, error
= 0, success
= 1;
409 char *channel_name
= nullptr;
410 struct lttng_event
*ev
;
411 struct lttng_domain dom
= {};
412 struct lttng_dynamic_pointer_array exclusions
;
413 struct lttng_userspace_probe_location
*uprobe_loc
= nullptr;
415 lttng_dynamic_pointer_array_init(&exclusions
, nullptr);
417 ev
= lttng_event_create();
425 WARN("Kernel loglevels are not supported.");
429 /* Create lttng domain */
431 dom
.type
= LTTNG_DOMAIN_KERNEL
;
432 dom
.buf_type
= LTTNG_BUFFER_GLOBAL
;
433 } else if (opt_userspace
) {
434 dom
.type
= LTTNG_DOMAIN_UST
;
436 dom
.buf_type
= LTTNG_BUFFER_PER_UID
;
437 } else if (opt_jul
) {
438 dom
.type
= LTTNG_DOMAIN_JUL
;
440 dom
.buf_type
= LTTNG_BUFFER_PER_UID
;
441 } else if (opt_log4j
) {
442 dom
.type
= LTTNG_DOMAIN_LOG4J
;
444 dom
.buf_type
= LTTNG_BUFFER_PER_UID
;
445 } else if (opt_python
) {
446 dom
.type
= LTTNG_DOMAIN_PYTHON
;
448 dom
.buf_type
= LTTNG_BUFFER_PER_UID
;
450 /* Checked by the caller. */
456 case LTTNG_DOMAIN_KERNEL
:
457 case LTTNG_DOMAIN_JUL
:
458 case LTTNG_DOMAIN_LOG4J
:
459 case LTTNG_DOMAIN_PYTHON
:
460 ERR("Event name exclusions are not yet implemented for %s events",
461 lttng_domain_type_str(dom
.type
));
464 case LTTNG_DOMAIN_UST
:
465 /* Exclusions supported */
473 * Adding a filter to a probe, function or userspace-probe would be
474 * denied by the kernel tracer as it's not supported at the moment. We
475 * do an early check here to warn the user.
477 if (opt_filter
&& opt_kernel
) {
478 switch (opt_event_type
) {
479 case LTTNG_EVENT_ALL
:
480 case LTTNG_EVENT_TRACEPOINT
:
481 case LTTNG_EVENT_SYSCALL
:
483 case LTTNG_EVENT_PROBE
:
484 case LTTNG_EVENT_USERSPACE_PROBE
:
485 case LTTNG_EVENT_FUNCTION
:
486 ERR("Filter expressions are not supported for %s events",
487 get_event_type_str((lttng_event_type
) opt_event_type
));
496 channel_name
= opt_channel_name
;
498 handle
= lttng_create_handle(session_name
.c_str(), &dom
);
499 if (handle
== nullptr) {
506 /* Open a events element */
507 ret
= mi_lttng_writer_open_element(writer
.get(), config_element_events
);
514 if (opt_enable_all
) {
515 /* Default setup for enable all */
517 ev
->type
= (lttng_event_type
) opt_event_type
;
518 strcpy(ev
->name
, "*");
519 /* kernel loglevels not implemented */
520 ev
->loglevel_type
= LTTNG_EVENT_LOGLEVEL_ALL
;
522 ev
->type
= LTTNG_EVENT_TRACEPOINT
;
523 strcpy(ev
->name
, "*");
524 ev
->loglevel_type
= (lttng_loglevel_type
) opt_loglevel_type
;
528 LTTNG_ASSERT(opt_userspace
|| opt_jul
|| opt_log4j
|| opt_python
);
531 enum lttng_loglevel loglevel
;
534 loglevel_name_to_value(opt_loglevel
, &loglevel
);
535 ev
->loglevel
= (int) loglevel
;
536 } else if (opt_jul
) {
537 enum lttng_loglevel_jul loglevel
;
540 loglevel_jul_name_to_value(opt_loglevel
, &loglevel
);
541 ev
->loglevel
= (int) loglevel
;
542 } else if (opt_log4j
) {
543 enum lttng_loglevel_log4j loglevel
;
545 name_search_ret
= loglevel_log4j_name_to_value(opt_loglevel
,
547 ev
->loglevel
= (int) loglevel
;
550 enum lttng_loglevel_python loglevel
;
552 name_search_ret
= loglevel_python_name_to_value(
553 opt_loglevel
, &loglevel
);
554 ev
->loglevel
= (int) loglevel
;
557 if (name_search_ret
== -1) {
558 ERR("Unknown loglevel %s", opt_loglevel
);
559 ret
= -LTTNG_ERR_INVALID
;
563 LTTNG_ASSERT(opt_userspace
|| opt_jul
|| opt_log4j
|| opt_python
);
566 } else if (opt_jul
) {
567 ev
->loglevel
= LTTNG_LOGLEVEL_JUL_ALL
;
568 } else if (opt_log4j
) {
569 ev
->loglevel
= LTTNG_LOGLEVEL_LOG4J_ALL
;
570 } else if (opt_python
) {
571 ev
->loglevel
= LTTNG_LOGLEVEL_PYTHON_DEBUG
;
577 ret
= create_exclusion_list_and_validate("*", opt_exclude
, &exclusions
);
584 warn_on_truncated_exclusion_names(&exclusions
, &warn
);
587 ret
= lttng_enable_event_with_exclusions(
592 lttng_dynamic_pointer_array_get_count(&exclusions
),
593 (char **) exclusions
.array
.buffer
.data
);
596 case LTTNG_ERR_KERN_EVENT_EXIST
:
597 WARN("Kernel events already enabled (channel %s, session %s)",
598 print_channel_name(channel_name
),
599 session_name
.c_str());
602 case LTTNG_ERR_TRACE_ALREADY_STARTED
:
605 "The command tried to enable an event in a new domain for a session that has already been started once.";
606 ERR("Events: %s (channel %s, session %s)",
608 print_channel_name(channel_name
),
609 session_name
.c_str());
614 ERR("Events: %s (channel %s, session %s)",
616 ret
== -LTTNG_ERR_NEED_CHANNEL_NAME
?
617 print_raw_channel_name(channel_name
) :
618 print_channel_name(channel_name
),
619 session_name
.c_str());
626 switch (opt_event_type
) {
627 case LTTNG_EVENT_TRACEPOINT
:
628 if (opt_loglevel
&& dom
.type
!= LTTNG_DOMAIN_KERNEL
) {
629 char *exclusion_string
= print_exclusions(&exclusions
);
631 if (!exclusion_string
) {
632 PERROR("Cannot allocate exclusion_string");
636 MSG("All %s tracepoints%s are enabled in channel %s for loglevel %s",
637 lttng_domain_type_str(dom
.type
),
639 print_channel_name(channel_name
),
641 free(exclusion_string
);
643 char *exclusion_string
= print_exclusions(&exclusions
);
645 if (!exclusion_string
) {
646 PERROR("Cannot allocate exclusion_string");
650 MSG("All %s tracepoints%s are enabled in channel %s",
651 lttng_domain_type_str(dom
.type
),
653 print_channel_name(channel_name
));
654 free(exclusion_string
);
657 case LTTNG_EVENT_SYSCALL
:
659 MSG("All %s system calls are enabled in channel %s",
660 lttng_domain_type_str(dom
.type
),
661 print_channel_name(channel_name
));
664 case LTTNG_EVENT_ALL
:
665 if (opt_loglevel
&& dom
.type
!= LTTNG_DOMAIN_KERNEL
) {
666 char *exclusion_string
= print_exclusions(&exclusions
);
668 if (!exclusion_string
) {
669 PERROR("Cannot allocate exclusion_string");
673 MSG("All %s events%s are enabled in channel %s for loglevel %s",
674 lttng_domain_type_str(dom
.type
),
676 print_channel_name(channel_name
),
678 free(exclusion_string
);
680 char *exclusion_string
= print_exclusions(&exclusions
);
682 if (!exclusion_string
) {
683 PERROR("Cannot allocate exclusion_string");
687 MSG("All %s events%s are enabled in channel %s",
688 lttng_domain_type_str(dom
.type
),
690 print_channel_name(channel_name
));
691 free(exclusion_string
);
696 * We should not be here since lttng_enable_event should have
697 * failed on the event type.
704 command_ret
= lttng_enable_event_with_exclusions(
709 lttng_dynamic_pointer_array_get_count(&exclusions
),
710 (char **) exclusions
.array
.buffer
.data
);
711 if (command_ret
< 0) {
712 switch (-command_ret
) {
713 case LTTNG_ERR_FILTER_EXIST
:
714 WARN("Filter on all events is already enabled"
715 " (channel %s, session %s)",
716 print_channel_name(channel_name
),
717 session_name
.c_str());
720 case LTTNG_ERR_TRACE_ALREADY_STARTED
:
723 "The command tried to enable an event in a new domain for a session that has already been started once.";
724 ERR("All events: %s (channel %s, session %s, filter \'%s\')",
726 print_channel_name(channel_name
),
727 session_name
.c_str(),
733 ERR("All events: %s (channel %s, session %s, filter \'%s\')",
734 lttng_strerror(command_ret
),
735 command_ret
== -LTTNG_ERR_NEED_CHANNEL_NAME
?
736 print_raw_channel_name(channel_name
) :
737 print_channel_name(channel_name
),
738 session_name
.c_str(),
743 error_holder
= command_ret
;
746 MSG("Filter '%s' successfully set", opt_filter
);
751 /* The wildcard * is used for kernel and ust domain to
752 * represent ALL. We copy * in event name to force the wildcard use
755 * Note: this is strictly for semantic and printing while in
756 * machine interface mode.
758 strcpy(ev
->name
, "*");
760 /* If we reach here the events are enabled */
761 if (!error
&& !warn
) {
767 ret
= mi_lttng_event(writer
.get(), ev
, 1, handle
->domain
.type
);
773 /* print exclusion */
774 ret
= mi_print_exclusion(&exclusions
);
781 ret
= mi_lttng_writer_write_element_bool(
782 writer
.get(), mi_lttng_element_command_success
, success
);
788 /* Close event element */
789 ret
= mi_lttng_writer_close_element(writer
.get());
799 /* Strip event list */
800 for (const auto& pattern
: patterns
) {
801 /* Copy name and type of the event */
802 strncpy(ev
->name
, pattern
.c_str(), LTTNG_SYMBOL_NAME_LEN
);
803 ev
->name
[LTTNG_SYMBOL_NAME_LEN
- 1] = '\0';
804 ev
->type
= (lttng_event_type
) opt_event_type
;
806 /* Kernel tracer action */
808 DBG_FMT("Enabling kernel event: pattern=`{}`, channel_name=`{}`",
810 print_channel_name(channel_name
));
812 switch (opt_event_type
) {
813 case LTTNG_EVENT_ALL
: /* Enable tracepoints and syscalls */
814 /* If event name differs from *, select tracepoint. */
815 if (strcmp(ev
->name
, "*") != 0) {
816 ev
->type
= LTTNG_EVENT_TRACEPOINT
;
819 case LTTNG_EVENT_TRACEPOINT
:
821 case LTTNG_EVENT_PROBE
:
822 ret
= parse_probe_opts(ev
, opt_probe
);
824 ERR("Unable to parse probe options");
829 case LTTNG_EVENT_USERSPACE_PROBE
:
830 LTTNG_ASSERT(ev
->type
== LTTNG_EVENT_USERSPACE_PROBE
);
832 ret
= parse_userspace_probe_opts(opt_userspace_probe
, &uprobe_loc
);
835 case CMD_UNSUPPORTED
:
837 * Error message describing
838 * what is not supported was
839 * printed in the function.
844 ERR("Unable to parse userspace probe options");
850 ret
= lttng_event_set_userspace_probe_location(ev
, uprobe_loc
);
852 WARN("Failed to set probe location on event");
857 /* Ownership of the uprobe location was transferred to the event. */
858 uprobe_loc
= nullptr;
860 case LTTNG_EVENT_FUNCTION
:
861 ret
= parse_probe_opts(ev
, opt_function
);
863 ERR("Unable to parse function probe options");
868 case LTTNG_EVENT_SYSCALL
:
869 ev
->type
= LTTNG_EVENT_SYSCALL
;
876 /* kernel loglevels not implemented */
877 ev
->loglevel_type
= LTTNG_EVENT_LOGLEVEL_ALL
;
878 } else if (opt_userspace
) { /* User-space tracer action */
879 DBG("Enabling UST event %s for channel %s, loglevel %s",
881 print_channel_name(channel_name
),
882 opt_loglevel
?: "<all>");
884 switch (opt_event_type
) {
885 case LTTNG_EVENT_ALL
: /* Default behavior is tracepoint */
887 case LTTNG_EVENT_TRACEPOINT
:
888 /* Copy name and type of the event */
889 ev
->type
= LTTNG_EVENT_TRACEPOINT
;
890 strncpy(ev
->name
, pattern
.c_str(), LTTNG_SYMBOL_NAME_LEN
);
891 ev
->name
[LTTNG_SYMBOL_NAME_LEN
- 1] = '\0';
893 case LTTNG_EVENT_PROBE
:
894 case LTTNG_EVENT_FUNCTION
:
895 case LTTNG_EVENT_SYSCALL
:
896 case LTTNG_EVENT_USERSPACE_PROBE
:
898 ERR("Event type not available for user-space tracing");
899 ret
= CMD_UNSUPPORTED
;
905 if (opt_event_type
!= LTTNG_EVENT_ALL
&&
906 opt_event_type
!= LTTNG_EVENT_TRACEPOINT
) {
907 ERR("Exclusion option can only be used with tracepoint events");
911 /* Free previously allocated items. */
912 lttng_dynamic_pointer_array_reset(&exclusions
);
913 ret
= create_exclusion_list_and_validate(
914 pattern
.c_str(), opt_exclude
, &exclusions
);
920 warn_on_truncated_exclusion_names(&exclusions
, &warn
);
923 ev
->loglevel_type
= (lttng_loglevel_type
) opt_loglevel_type
;
925 enum lttng_loglevel loglevel
;
926 const int name_search_ret
=
927 loglevel_name_to_value(opt_loglevel
, &loglevel
);
929 if (name_search_ret
== -1) {
930 ERR("Unknown loglevel %s", opt_loglevel
);
931 ret
= -LTTNG_ERR_INVALID
;
935 ev
->loglevel
= (int) loglevel
;
939 } else if (opt_jul
|| opt_log4j
|| opt_python
) {
940 if (opt_event_type
!= LTTNG_EVENT_ALL
&&
941 opt_event_type
!= LTTNG_EVENT_TRACEPOINT
) {
942 ERR("Event type not supported for domain.");
943 ret
= CMD_UNSUPPORTED
;
947 ev
->loglevel_type
= (lttng_loglevel_type
) opt_loglevel_type
;
952 enum lttng_loglevel_jul loglevel
;
955 loglevel_jul_name_to_value(opt_loglevel
, &loglevel
);
956 ev
->loglevel
= (int) loglevel
;
957 } else if (opt_log4j
) {
958 enum lttng_loglevel_log4j loglevel
;
960 name_search_ret
= loglevel_log4j_name_to_value(opt_loglevel
,
962 ev
->loglevel
= (int) loglevel
;
965 enum lttng_loglevel_python loglevel
;
967 name_search_ret
= loglevel_python_name_to_value(
968 opt_loglevel
, &loglevel
);
969 ev
->loglevel
= (int) loglevel
;
972 if (name_search_ret
) {
973 ERR("Unknown loglevel %s", opt_loglevel
);
974 ret
= -LTTNG_ERR_INVALID
;
979 ev
->loglevel
= LTTNG_LOGLEVEL_JUL_ALL
;
980 } else if (opt_log4j
) {
981 ev
->loglevel
= LTTNG_LOGLEVEL_LOG4J_ALL
;
982 } else if (opt_python
) {
983 ev
->loglevel
= LTTNG_LOGLEVEL_PYTHON_DEBUG
;
986 ev
->type
= LTTNG_EVENT_TRACEPOINT
;
987 strncpy(ev
->name
, pattern
.c_str(), LTTNG_SYMBOL_NAME_LEN
);
988 ev
->name
[LTTNG_SYMBOL_NAME_LEN
- 1] = '\0';
994 char *exclusion_string
;
996 command_ret
= lttng_enable_event_with_exclusions(
1001 lttng_dynamic_pointer_array_get_count(&exclusions
),
1002 (char **) exclusions
.array
.buffer
.data
);
1003 exclusion_string
= print_exclusions(&exclusions
);
1004 if (!exclusion_string
) {
1005 PERROR("Cannot allocate exclusion_string");
1009 if (command_ret
< 0) {
1010 /* Turn ret to positive value to handle the positive error code */
1011 switch (-command_ret
) {
1012 case LTTNG_ERR_KERN_EVENT_EXIST
:
1013 WARN("Kernel event %s%s already enabled (channel %s, session %s)",
1016 print_channel_name(channel_name
),
1017 session_name
.c_str());
1020 case LTTNG_ERR_TRACE_ALREADY_STARTED
:
1023 "The command tried to enable an event in a new domain for a session that has already been started once.";
1024 ERR("Event %s%s: %s (channel %s, session %s)",
1028 print_channel_name(channel_name
),
1029 session_name
.c_str());
1033 case LTTNG_ERR_SDT_PROBE_SEMAPHORE
:
1034 ERR("SDT probes %s guarded by semaphores are not supported (channel %s, session %s)",
1036 print_channel_name(channel_name
),
1037 session_name
.c_str());
1041 ERR("Event %s%s: %s (channel %s, session %s)",
1044 lttng_strerror(command_ret
),
1045 command_ret
== -LTTNG_ERR_NEED_CHANNEL_NAME
?
1046 print_raw_channel_name(channel_name
) :
1047 print_channel_name(channel_name
),
1048 session_name
.c_str());
1052 error_holder
= command_ret
;
1055 case LTTNG_DOMAIN_KERNEL
:
1056 case LTTNG_DOMAIN_UST
:
1057 MSG("%s event %s%s created in channel %s",
1058 lttng_domain_type_str(dom
.type
),
1061 print_channel_name(channel_name
));
1063 case LTTNG_DOMAIN_JUL
:
1064 case LTTNG_DOMAIN_LOG4J
:
1065 case LTTNG_DOMAIN_PYTHON
:
1067 * Don't print the default channel
1068 * name for agent domains.
1070 MSG("%s event %s%s enabled",
1071 lttng_domain_type_str(dom
.type
),
1079 free(exclusion_string
);
1083 char *exclusion_string
;
1085 /* Filter present */
1088 command_ret
= lttng_enable_event_with_exclusions(
1093 lttng_dynamic_pointer_array_get_count(&exclusions
),
1094 (char **) exclusions
.array
.buffer
.data
);
1095 exclusion_string
= print_exclusions(&exclusions
);
1096 if (!exclusion_string
) {
1097 PERROR("Cannot allocate exclusion_string");
1101 if (command_ret
< 0) {
1102 switch (-command_ret
) {
1103 case LTTNG_ERR_FILTER_EXIST
:
1104 WARN("Filter on event %s%s is already enabled"
1105 " (channel %s, session %s)",
1108 print_channel_name(channel_name
),
1109 session_name
.c_str());
1112 case LTTNG_ERR_TRACE_ALREADY_STARTED
:
1115 "The command tried to enable an event in a new domain for a session that has already been started once.";
1116 ERR("Event %s%s: %s (channel %s, session %s, filter \'%s\')",
1120 print_channel_name(channel_name
),
1121 session_name
.c_str(),
1127 ERR("Event %s%s: %s (channel %s, session %s, filter \'%s\')",
1130 lttng_strerror(command_ret
),
1131 command_ret
== -LTTNG_ERR_NEED_CHANNEL_NAME
?
1132 print_raw_channel_name(channel_name
) :
1133 print_channel_name(channel_name
),
1134 session_name
.c_str(),
1139 error_holder
= command_ret
;
1142 MSG("Event %s%s: Filter '%s' successfully set",
1147 free(exclusion_string
);
1158 ret
= mi_lttng_event(writer
.get(), ev
, 1, handle
->domain
.type
);
1164 /* print exclusion */
1165 ret
= mi_print_exclusion(&exclusions
);
1172 ret
= mi_lttng_writer_write_element_bool(
1173 writer
.get(), mi_lttng_element_command_success
, success
);
1179 /* Close event element */
1180 ret
= mi_lttng_writer_close_element(writer
.get());
1187 /* Reset warn, error and success */
1194 /* Close events element */
1195 ret
= mi_lttng_writer_close_element(writer
.get());
1208 lttng_destroy_handle(handle
);
1209 lttng_dynamic_pointer_array_reset(&exclusions
);
1210 lttng_userspace_probe_location_destroy(uprobe_loc
);
1212 /* Overwrite ret with error_holder if there was an actual error with
1213 * enabling an event.
1215 ret
= error_holder
? error_holder
: ret
;
1217 lttng_event_destroy(ev
);
1221 void _poptContextFree_deleter_func(poptContext ctx
)
1223 poptFreeContext(ctx
);
1228 int validate_exclusion_list(const char *pattern
,
1229 const struct lttng_dynamic_pointer_array
*exclusions
)
1233 /* Event name must be a valid globbing pattern to allow exclusions. */
1234 if (!strutils_is_star_glob_pattern(pattern
)) {
1235 ERR("Event %s: Exclusions can only be used with a globbing pattern", pattern
);
1240 * If the event name is a star-at-end only globbing pattern,
1241 * then we can validate the individual exclusions. Otherwise
1242 * all exclusions are passed to the session daemon.
1244 if (strutils_is_star_at_the_end_only_glob_pattern(pattern
)) {
1245 size_t i
, num_exclusions
;
1247 num_exclusions
= lttng_dynamic_pointer_array_get_count(exclusions
);
1249 for (i
= 0; i
< num_exclusions
; i
++) {
1250 const char *exclusion
=
1251 (const char *) lttng_dynamic_pointer_array_get_pointer(exclusions
,
1254 if (!strutils_is_star_glob_pattern(exclusion
) ||
1255 strutils_is_star_at_the_end_only_glob_pattern(exclusion
)) {
1256 ret
= check_exclusion_subsets(pattern
, exclusion
);
1275 * Add event to trace session
1277 int cmd_enable_events(int argc
, const char **argv
)
1279 int opt
, ret
= CMD_SUCCESS
, command_ret
= CMD_SUCCESS
, success
= 1;
1280 std::string session_name
;
1281 const char *arg_event_list
= nullptr;
1282 const char *leftover
= nullptr;
1283 int event_type
= -1;
1284 event_rule_patterns patterns
;
1285 std::stringstream
event_list_arg_stream(arg_event_list
);
1287 auto pc
= lttng::make_unique_wrapper
<poptContext_s
, _poptContextFree_deleter_func
>(
1288 poptGetContext(nullptr, argc
, argv
, long_options
, 0));
1289 poptReadDefaultConfig(pc
.get(), 0);
1291 /* Default event type */
1292 opt_event_type
= LTTNG_EVENT_ALL
;
1294 while ((opt
= poptGetNextOpt(pc
.get())) != -1) {
1299 case OPT_TRACEPOINT
:
1300 opt_event_type
= LTTNG_EVENT_TRACEPOINT
;
1303 opt_event_type
= LTTNG_EVENT_PROBE
;
1305 case OPT_USERSPACE_PROBE
:
1306 opt_event_type
= LTTNG_EVENT_USERSPACE_PROBE
;
1309 opt_event_type
= LTTNG_EVENT_FUNCTION
;
1312 opt_event_type
= LTTNG_EVENT_SYSCALL
;
1318 opt_loglevel_type
= LTTNG_EVENT_LOGLEVEL_RANGE
;
1319 opt_loglevel
= poptGetOptArg(pc
.get());
1321 case OPT_LOGLEVEL_ONLY
:
1322 opt_loglevel_type
= LTTNG_EVENT_LOGLEVEL_SINGLE
;
1323 opt_loglevel
= poptGetOptArg(pc
.get());
1325 case OPT_LIST_OPTIONS
:
1326 list_cmd_options(stdout
, long_options
);
1333 ret
= CMD_UNDEFINED
;
1337 /* Validate event type. Multiple event type are not supported. */
1338 if (event_type
== -1) {
1339 event_type
= opt_event_type
;
1341 if (event_type
!= opt_event_type
) {
1342 ERR("Multiple event type not supported.");
1349 ret
= print_missing_or_multiple_domains(
1350 opt_kernel
+ opt_userspace
+ opt_jul
+ opt_log4j
+ opt_python
, true);
1358 writer
= mi_writer_uptr(mi_lttng_writer_create(fileno(stdout
), lttng_opt_mi
));
1360 ret
= -LTTNG_ERR_NOMEM
;
1364 /* Open command element */
1365 ret
= mi_lttng_writer_command_open(writer
.get(),
1366 mi_lttng_element_command_enable_event
);
1372 /* Open output element */
1373 ret
= mi_lttng_writer_open_element(writer
.get(), mi_lttng_element_command_output
);
1380 arg_event_list
= poptGetArg(pc
.get());
1381 if (arg_event_list
== nullptr && opt_enable_all
== 0) {
1382 ERR("Missing event name(s).");
1387 for (std::string line
; std::getline(event_list_arg_stream
, line
, ',');) {
1388 patterns
.emplace_back(std::move(line
));
1391 leftover
= poptGetArg(pc
.get());
1393 ERR("Unknown argument: %s", leftover
);
1398 if (!opt_session_name
) {
1399 const auto rc_file_session_name
=
1400 lttng::make_unique_wrapper
<char, lttng::free
>(get_session_name());
1402 if (!rc_file_session_name
) {
1403 command_ret
= CMD_ERROR
;
1408 session_name
= rc_file_session_name
.get();
1410 session_name
= opt_session_name
;
1413 command_ret
= enable_events(session_name
, patterns
);
1422 /* Close output element */
1423 ret
= mi_lttng_writer_close_element(writer
.get());
1429 ret
= mi_lttng_writer_write_element_bool(
1430 writer
.get(), mi_lttng_element_command_success
, success
);
1436 /* Command element close */
1437 ret
= mi_lttng_writer_command_close(writer
.get());
1445 /* Overwrite ret if an error occurred in enable_events */
1446 ret
= command_ret
? command_ret
: ret
;