2 * Copyright (C) 2011 EfficiOS Inc.
3 * Copyright (C) 2020 Jérémie Galarneau <jeremie.galarneau@efficios.com>
5 * SPDX-License-Identifier: GPL-2.0-only
18 #include <common/mi-lttng.h>
19 #include <common/time.h>
20 #include <common/tracker.h>
21 #include <lttng/domain-internal.h>
22 #include <lttng/lttng.h>
24 #include "../command.h"
26 static int opt_userspace
;
27 static int opt_kernel
;
30 static int opt_python
;
31 static char *opt_channel
;
32 static int opt_domain
;
33 static int opt_fields
;
34 static int opt_syscall
;
36 const char *indent4
= " ";
37 const char *indent6
= " ";
38 const char *indent8
= " ";
40 #ifdef LTTNG_EMBED_HELP
41 static const char help_msg
[] =
42 #include <lttng-list.1.h>
52 static struct lttng_handle
*the_handle
;
53 static struct mi_writer
*the_writer
;
55 /* Only set when listing a single session. */
56 static struct lttng_session the_listed_session
;
58 static struct poptOption long_options
[] = {
59 /* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
60 {"help", 'h', POPT_ARG_NONE
, 0, OPT_HELP
, 0, 0},
61 {"kernel", 'k', POPT_ARG_VAL
, &opt_kernel
, 1, 0, 0},
62 {"jul", 'j', POPT_ARG_VAL
, &opt_jul
, 1, 0, 0},
63 {"log4j", 'l', POPT_ARG_VAL
, &opt_log4j
, 1, 0, 0},
64 {"python", 'p', POPT_ARG_VAL
, &opt_python
, 1, 0, 0},
65 {"userspace", 'u', POPT_ARG_NONE
, 0, OPT_USERSPACE
, 0, 0},
66 {"channel", 'c', POPT_ARG_STRING
, &opt_channel
, 0, 0, 0},
67 {"domain", 'd', POPT_ARG_VAL
, &opt_domain
, 1, 0, 0},
68 {"fields", 'f', POPT_ARG_VAL
, &opt_fields
, 1, 0, 0},
69 {"syscall", 'S', POPT_ARG_VAL
, &opt_syscall
, 1, 0, 0},
70 {"list-options", 0, POPT_ARG_NONE
, NULL
, OPT_LIST_OPTIONS
, NULL
, NULL
},
75 * Get command line from /proc for a specific pid.
77 * On success, return an allocated string pointer to the proc cmdline.
78 * On error, return NULL.
80 static char *get_cmdline_by_pid(pid_t pid
)
85 /* Can't go bigger than /proc/LTTNG_MAX_PID/cmdline */
86 char path
[sizeof("/proc//cmdline") + sizeof(LTTNG_MAX_PID_STR
) - 1];
88 snprintf(path
, sizeof(path
), "/proc/%d/cmdline", pid
);
89 fp
= fopen(path
, "r");
94 /* Caller must free() *cmdline */
95 cmdline
= zmalloc(PATH_MAX
);
97 PERROR("malloc cmdline");
100 ret
= fread(cmdline
, 1, PATH_MAX
, fp
);
102 PERROR("fread proc list");
113 const char *active_string(int value
)
116 case 0: return "inactive";
117 case 1: return "active";
119 default: return NULL
;
123 static const char *snapshot_string(int value
)
134 const char *enabled_string(int value
)
137 case 0: return " [disabled]";
138 case 1: return " [enabled]";
140 default: return NULL
;
145 const char *safe_string(const char *str
)
147 return str
? str
: "";
150 static const char *logleveltype_string(enum lttng_loglevel_type value
)
153 case LTTNG_EVENT_LOGLEVEL_ALL
:
155 case LTTNG_EVENT_LOGLEVEL_RANGE
:
157 case LTTNG_EVENT_LOGLEVEL_SINGLE
:
160 return " <<TYPE UNKN>>";
164 static const char *bitness_event(enum lttng_event_flag flags
)
166 if (flags
& LTTNG_EVENT_FLAG_SYSCALL_32
) {
167 if (flags
& LTTNG_EVENT_FLAG_SYSCALL_64
) {
168 return " [32/64-bit]";
172 } else if (flags
& LTTNG_EVENT_FLAG_SYSCALL_64
) {
180 * Get exclusion names message for a single event.
182 * Returned pointer must be freed by caller. Returns NULL on error.
184 static char *get_exclusion_names_msg(struct lttng_event
*event
)
188 char *exclusion_msg
= NULL
;
191 const char * const exclusion_fmt
= " [exclusions: ";
192 const size_t exclusion_fmt_len
= strlen(exclusion_fmt
);
194 exclusion_count
= lttng_event_get_exclusion_name_count(event
);
195 if (exclusion_count
< 0) {
197 } else if (exclusion_count
== 0) {
199 * No exclusions: return copy of empty string so that
200 * it can be freed by caller.
202 exclusion_msg
= strdup("");
207 * exclusion_msg's size is bounded by the exclusion_fmt string,
208 * a comma per entry, the entry count (fixed-size), a closing
209 * bracket, and a trailing \0.
211 exclusion_msg
= malloc(exclusion_count
+
212 exclusion_count
* LTTNG_SYMBOL_NAME_LEN
+
213 exclusion_fmt_len
+ 1);
214 if (!exclusion_msg
) {
218 at
= strcpy(exclusion_msg
, exclusion_fmt
) + exclusion_fmt_len
;
219 for (i
= 0; i
< exclusion_count
; ++i
) {
222 /* Append comma between exclusion names */
228 ret
= lttng_event_get_exclusion_name(event
, i
, &name
);
230 /* Prints '?' on local error; should never happen */
236 /* Append exclusion name */
237 at
+= sprintf(at
, "%s", name
);
240 /* This also puts a final '\0' at the end of exclusion_msg */
244 return exclusion_msg
;
247 static void print_userspace_probe_location(struct lttng_event
*event
)
249 const struct lttng_userspace_probe_location
*location
;
250 const struct lttng_userspace_probe_location_lookup_method
*lookup_method
;
251 enum lttng_userspace_probe_location_lookup_method_type lookup_type
;
253 location
= lttng_event_get_userspace_probe_location(event
);
255 MSG("Event has no userspace probe location");
259 lookup_method
= lttng_userspace_probe_location_get_lookup_method(location
);
260 if (!lookup_method
) {
261 MSG("Event has no userspace probe location lookup method");
265 MSG("%s%s (type: userspace-probe)%s", indent6
, event
->name
, enabled_string(event
->enabled
));
267 lookup_type
= lttng_userspace_probe_location_lookup_method_get_type(lookup_method
);
269 switch (lttng_userspace_probe_location_get_type(location
)) {
270 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_UNKNOWN
:
271 MSG("%sType: Unknown", indent8
);
273 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION
:
275 const char *function_name
;
278 MSG("%sType: Function", indent8
);
279 function_name
= lttng_userspace_probe_location_function_get_function_name(location
);
280 binary_path
= realpath(lttng_userspace_probe_location_function_get_binary_path(location
), NULL
);
282 MSG("%sBinary path: %s", indent8
, binary_path
? binary_path
: "NULL");
283 MSG("%sFunction: %s()", indent8
, function_name
? function_name
: "NULL");
284 switch (lookup_type
) {
285 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_ELF
:
286 MSG("%sLookup method: ELF", indent8
);
288 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_DEFAULT
:
289 MSG("%sLookup method: default", indent8
);
292 MSG("%sLookup method: INVALID LOOKUP TYPE ENCOUNTERED", indent8
);
299 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT
:
301 const char *probe_name
, *provider_name
;
304 MSG("%sType: Tracepoint", indent8
);
305 probe_name
= lttng_userspace_probe_location_tracepoint_get_probe_name(location
);
306 provider_name
= lttng_userspace_probe_location_tracepoint_get_provider_name(location
);
307 binary_path
= realpath(lttng_userspace_probe_location_tracepoint_get_binary_path(location
), NULL
);
308 MSG("%sBinary path: %s", indent8
, binary_path
? binary_path
: "NULL");
309 MSG("%sTracepoint: %s:%s", indent8
, provider_name
? provider_name
: "NULL", probe_name
? probe_name
: "NULL");
310 switch (lookup_type
) {
311 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_TRACEPOINT_SDT
:
312 MSG("%sLookup method: SDT", indent8
);
315 MSG("%sLookup method: INVALID LOOKUP TYPE ENCOUNTERED", indent8
);
323 ERR("Invalid probe type encountered");
328 * Pretty print single event.
330 static void print_events(struct lttng_event
*event
)
333 const char *filter_str
;
334 char *filter_msg
= NULL
;
335 char *exclusion_msg
= NULL
;
337 ret
= lttng_event_get_filter_expression(event
, &filter_str
);
340 filter_msg
= strdup(" [failed to retrieve filter]");
341 } else if (filter_str
) {
342 const char * const filter_fmt
= " [filter: '%s']";
344 filter_msg
= malloc(strlen(filter_str
) +
345 strlen(filter_fmt
) + 1);
347 sprintf(filter_msg
, filter_fmt
,
352 exclusion_msg
= get_exclusion_names_msg(event
);
353 if (!exclusion_msg
) {
354 exclusion_msg
= strdup(" [failed to retrieve exclusions]");
357 switch (event
->type
) {
358 case LTTNG_EVENT_TRACEPOINT
:
360 if (event
->loglevel
!= -1) {
361 MSG("%s%s (loglevel%s %s (%d)) (type: tracepoint)%s%s%s",
362 indent6
, event
->name
,
364 event
->loglevel_type
),
365 mi_lttng_loglevel_string(
367 the_handle
->domain
.type
),
369 enabled_string(event
->enabled
),
370 safe_string(exclusion_msg
),
371 safe_string(filter_msg
));
373 MSG("%s%s (type: tracepoint)%s%s%s",
376 enabled_string(event
->enabled
),
377 safe_string(exclusion_msg
),
378 safe_string(filter_msg
));
382 case LTTNG_EVENT_FUNCTION
:
383 MSG("%s%s (type: function)%s%s", indent6
,
384 event
->name
, enabled_string(event
->enabled
),
385 safe_string(filter_msg
));
386 if (event
->attr
.probe
.addr
!= 0) {
387 MSG("%saddr: 0x%" PRIx64
, indent8
, event
->attr
.probe
.addr
);
389 MSG("%soffset: 0x%" PRIx64
, indent8
, event
->attr
.probe
.offset
);
390 MSG("%ssymbol: %s", indent8
, event
->attr
.probe
.symbol_name
);
393 case LTTNG_EVENT_PROBE
:
394 MSG("%s%s (type: probe)%s%s", indent6
,
395 event
->name
, enabled_string(event
->enabled
),
396 safe_string(filter_msg
));
397 if (event
->attr
.probe
.addr
!= 0) {
398 MSG("%saddr: 0x%" PRIx64
, indent8
, event
->attr
.probe
.addr
);
400 MSG("%soffset: 0x%" PRIx64
, indent8
, event
->attr
.probe
.offset
);
401 MSG("%ssymbol: %s", indent8
, event
->attr
.probe
.symbol_name
);
404 case LTTNG_EVENT_USERSPACE_PROBE
:
405 print_userspace_probe_location(event
);
407 case LTTNG_EVENT_FUNCTION_ENTRY
:
408 MSG("%s%s (type: function)%s%s", indent6
,
409 event
->name
, enabled_string(event
->enabled
),
410 safe_string(filter_msg
));
411 MSG("%ssymbol: \"%s\"", indent8
, event
->attr
.ftrace
.symbol_name
);
413 case LTTNG_EVENT_SYSCALL
:
414 MSG("%s%s%s%s%s%s", indent6
, event
->name
,
415 (opt_syscall
? "" : " (type:syscall)"),
416 enabled_string(event
->enabled
),
417 bitness_event(event
->flags
),
418 safe_string(filter_msg
));
420 case LTTNG_EVENT_NOOP
:
421 MSG("%s (type: noop)%s%s", indent6
,
422 enabled_string(event
->enabled
),
423 safe_string(filter_msg
));
425 case LTTNG_EVENT_ALL
:
428 /* We should never have "all" events in list. */
437 static const char *field_type(struct lttng_event_field
*field
)
439 switch(field
->type
) {
440 case LTTNG_EVENT_FIELD_INTEGER
:
442 case LTTNG_EVENT_FIELD_ENUM
:
444 case LTTNG_EVENT_FIELD_FLOAT
:
446 case LTTNG_EVENT_FIELD_STRING
:
448 case LTTNG_EVENT_FIELD_OTHER
:
449 default: /* fall-through */
455 * Pretty print single event fields.
457 static void print_event_field(struct lttng_event_field
*field
)
459 if (!field
->field_name
[0]) {
462 MSG("%sfield: %s (%s)%s", indent8
, field
->field_name
,
463 field_type(field
), field
->nowrite
? " [no write]" : "");
468 * Jul and ust event listing
470 static int mi_list_agent_ust_events(struct lttng_event
*events
, int count
,
471 struct lttng_domain
*domain
)
475 char *cmdline
= NULL
;
476 int pid_element_open
= 0;
478 /* Open domains element */
479 ret
= mi_lttng_domains_open(the_writer
);
485 ret
= mi_lttng_domain(the_writer
, domain
, 1);
490 /* Open pids element element */
491 ret
= mi_lttng_pids_open(the_writer
);
496 for (i
= 0; i
< count
; i
++) {
497 if (cur_pid
!= events
[i
].pid
) {
498 if (pid_element_open
) {
499 /* Close the previous events and pid element */
500 ret
= mi_lttng_close_multi_element(
505 pid_element_open
= 0;
508 cur_pid
= events
[i
].pid
;
509 cmdline
= get_cmdline_by_pid(cur_pid
);
515 if (!pid_element_open
) {
516 /* Open and write a pid element */
517 ret
= mi_lttng_pid(the_writer
, cur_pid
, cmdline
,
523 /* Open events element */
524 ret
= mi_lttng_events_open(the_writer
);
529 pid_element_open
= 1;
535 ret
= mi_lttng_event(the_writer
, &events
[i
], 0,
536 the_handle
->domain
.type
);
543 ret
= mi_lttng_writer_close_element(the_writer
);
548 /* Close domain, domains */
549 ret
= mi_lttng_close_multi_element(the_writer
, 2);
557 static int list_agent_events(void)
559 int i
, size
, ret
= CMD_SUCCESS
;
560 struct lttng_domain domain
;
561 struct lttng_handle
*handle
= NULL
;
562 struct lttng_event
*event_list
= NULL
;
564 char *cmdline
= NULL
;
565 const char *agent_domain_str
;
567 memset(&domain
, 0, sizeof(domain
));
569 domain
.type
= LTTNG_DOMAIN_JUL
;
570 } else if (opt_log4j
) {
571 domain
.type
= LTTNG_DOMAIN_LOG4J
;
572 } else if (opt_python
) {
573 domain
.type
= LTTNG_DOMAIN_PYTHON
;
575 ERR("Invalid agent domain selected.");
580 agent_domain_str
= lttng_domain_type_str(domain
.type
);
582 DBG("Getting %s tracing events", agent_domain_str
);
584 handle
= lttng_create_handle(NULL
, &domain
);
585 if (handle
== NULL
) {
590 size
= lttng_list_tracepoints(handle
, &event_list
);
592 ERR("Unable to list %s events: %s", agent_domain_str
,
593 lttng_strerror(size
));
600 ret
= mi_list_agent_ust_events(event_list
, size
, &domain
);
607 MSG("%s events (Logger name):\n-------------------------",
614 for (i
= 0; i
< size
; i
++) {
615 if (cur_pid
!= event_list
[i
].pid
) {
616 cur_pid
= event_list
[i
].pid
;
617 cmdline
= get_cmdline_by_pid(cur_pid
);
618 if (cmdline
== NULL
) {
622 MSG("\nPID: %d - Name: %s", cur_pid
, cmdline
);
625 MSG("%s- %s", indent6
, event_list
[i
].name
);
634 lttng_destroy_handle(handle
);
639 * Ask session daemon for all user space tracepoints available.
641 static int list_ust_events(void)
643 int i
, size
, ret
= CMD_SUCCESS
;
644 struct lttng_domain domain
;
645 struct lttng_handle
*handle
;
646 struct lttng_event
*event_list
= NULL
;
648 char *cmdline
= NULL
;
650 memset(&domain
, 0, sizeof(domain
));
652 DBG("Getting UST tracing events");
654 domain
.type
= LTTNG_DOMAIN_UST
;
656 handle
= lttng_create_handle(NULL
, &domain
);
657 if (handle
== NULL
) {
662 size
= lttng_list_tracepoints(handle
, &event_list
);
664 ERR("Unable to list UST events: %s", lttng_strerror(size
));
671 ret
= mi_list_agent_ust_events(event_list
, size
, &domain
);
674 MSG("UST events:\n-------------");
680 for (i
= 0; i
< size
; i
++) {
681 if (cur_pid
!= event_list
[i
].pid
) {
682 cur_pid
= event_list
[i
].pid
;
683 cmdline
= get_cmdline_by_pid(cur_pid
);
684 if (cmdline
== NULL
) {
688 MSG("\nPID: %d - Name: %s", cur_pid
, cmdline
);
691 print_events(&event_list
[i
]);
700 lttng_destroy_handle(handle
);
706 * List all ust event with their fields
708 static int mi_list_ust_event_fields(struct lttng_event_field
*fields
, int count
,
709 struct lttng_domain
*domain
)
713 char *cmdline
= NULL
;
714 int pid_element_open
= 0;
715 int event_element_open
= 0;
716 struct lttng_event cur_event
;
718 memset(&cur_event
, 0, sizeof(cur_event
));
720 /* Open domains element */
721 ret
= mi_lttng_domains_open(the_writer
);
727 ret
= mi_lttng_domain(the_writer
, domain
, 1);
732 /* Open pids element */
733 ret
= mi_lttng_pids_open(the_writer
);
738 for (i
= 0; i
< count
; i
++) {
739 if (cur_pid
!= fields
[i
].event
.pid
) {
740 if (pid_element_open
) {
741 if (event_element_open
) {
742 /* Close the previous field element and event. */
743 ret
= mi_lttng_close_multi_element(
748 event_element_open
= 0;
750 /* Close the previous events, pid element */
751 ret
= mi_lttng_close_multi_element(
756 pid_element_open
= 0;
759 cur_pid
= fields
[i
].event
.pid
;
760 cmdline
= get_cmdline_by_pid(cur_pid
);
761 if (!pid_element_open
) {
762 /* Open and write a pid element */
763 ret
= mi_lttng_pid(the_writer
, cur_pid
, cmdline
,
769 /* Open events element */
770 ret
= mi_lttng_events_open(the_writer
);
774 pid_element_open
= 1;
777 /* Wipe current event since we are about to print a new PID. */
778 memset(&cur_event
, 0, sizeof(cur_event
));
781 if (strcmp(cur_event
.name
, fields
[i
].event
.name
) != 0) {
782 if (event_element_open
) {
783 /* Close the previous fields element and the previous event */
784 ret
= mi_lttng_close_multi_element(
789 event_element_open
= 0;
792 memcpy(&cur_event
, &fields
[i
].event
,
795 if (!event_element_open
) {
796 /* Open and write the event */
797 ret
= mi_lttng_event(the_writer
, &cur_event
, 1,
798 the_handle
->domain
.type
);
803 /* Open a fields element */
804 ret
= mi_lttng_event_fields_open(the_writer
);
808 event_element_open
= 1;
812 /* Print the event_field */
813 ret
= mi_lttng_event_field(the_writer
, &fields
[i
]);
819 /* Close pids, domain, domains */
820 ret
= mi_lttng_close_multi_element(the_writer
, 3);
829 * Ask session daemon for all user space tracepoint fields available.
831 static int list_ust_event_fields(void)
833 int i
, size
, ret
= CMD_SUCCESS
;
834 struct lttng_domain domain
;
835 struct lttng_handle
*handle
;
836 struct lttng_event_field
*event_field_list
;
838 char *cmdline
= NULL
;
840 struct lttng_event cur_event
;
842 memset(&domain
, 0, sizeof(domain
));
843 memset(&cur_event
, 0, sizeof(cur_event
));
845 DBG("Getting UST tracing event fields");
847 domain
.type
= LTTNG_DOMAIN_UST
;
849 handle
= lttng_create_handle(NULL
, &domain
);
850 if (handle
== NULL
) {
855 size
= lttng_list_tracepoint_fields(handle
, &event_field_list
);
857 ERR("Unable to list UST event fields: %s", lttng_strerror(size
));
864 ret
= mi_list_ust_event_fields(event_field_list
, size
, &domain
);
871 MSG("UST events:\n-------------");
877 for (i
= 0; i
< size
; i
++) {
878 if (cur_pid
!= event_field_list
[i
].event
.pid
) {
879 cur_pid
= event_field_list
[i
].event
.pid
;
880 cmdline
= get_cmdline_by_pid(cur_pid
);
881 if (cmdline
== NULL
) {
885 MSG("\nPID: %d - Name: %s", cur_pid
, cmdline
);
887 /* Wipe current event since we are about to print a new PID. */
888 memset(&cur_event
, 0, sizeof(cur_event
));
890 if (strcmp(cur_event
.name
, event_field_list
[i
].event
.name
) != 0) {
891 print_events(&event_field_list
[i
].event
);
892 memcpy(&cur_event
, &event_field_list
[i
].event
,
895 print_event_field(&event_field_list
[i
]);
902 free(event_field_list
);
904 lttng_destroy_handle(handle
);
910 * Print a list of kernel events
912 static int mi_list_kernel_events(struct lttng_event
*events
, int count
,
913 struct lttng_domain
*domain
)
917 /* Open domains element */
918 ret
= mi_lttng_domains_open(the_writer
);
924 ret
= mi_lttng_domain(the_writer
, domain
, 1);
930 ret
= mi_lttng_events_open(the_writer
);
935 for (i
= 0; i
< count
; i
++) {
936 ret
= mi_lttng_event(the_writer
, &events
[i
], 0,
937 the_handle
->domain
.type
);
943 /* close events, domain and domains */
944 ret
= mi_lttng_close_multi_element(the_writer
, 3);
954 * Ask for all trace events in the kernel
956 static int list_kernel_events(void)
958 int i
, size
, ret
= CMD_SUCCESS
;
959 struct lttng_domain domain
;
960 struct lttng_handle
*handle
;
961 struct lttng_event
*event_list
;
963 memset(&domain
, 0, sizeof(domain
));
965 DBG("Getting kernel tracing events");
967 domain
.type
= LTTNG_DOMAIN_KERNEL
;
969 handle
= lttng_create_handle(NULL
, &domain
);
970 if (handle
== NULL
) {
975 size
= lttng_list_tracepoints(handle
, &event_list
);
977 ERR("Unable to list kernel events: %s", lttng_strerror(size
));
978 lttng_destroy_handle(handle
);
984 ret
= mi_list_kernel_events(event_list
, size
, &domain
);
990 MSG("Kernel events:\n-------------");
992 for (i
= 0; i
< size
; i
++) {
993 print_events(&event_list
[i
]);
1002 lttng_destroy_handle(handle
);
1006 lttng_destroy_handle(handle
);
1012 * Print a list of system calls.
1014 static int mi_list_syscalls(struct lttng_event
*events
, int count
)
1019 ret
= mi_lttng_events_open(the_writer
);
1024 for (i
= 0; i
< count
; i
++) {
1025 ret
= mi_lttng_event(the_writer
, &events
[i
], 0,
1026 the_handle
->domain
.type
);
1033 ret
= mi_lttng_writer_close_element(the_writer
);
1043 * Ask for kernel system calls.
1045 static int list_syscalls(void)
1047 int i
, size
, ret
= CMD_SUCCESS
;
1048 struct lttng_event
*event_list
;
1050 DBG("Getting kernel system call events");
1052 size
= lttng_list_syscalls(&event_list
);
1054 ERR("Unable to list system calls: %s", lttng_strerror(size
));
1061 ret
= mi_list_syscalls(event_list
, size
);
1067 MSG("System calls:\n-------------");
1069 for (i
= 0; i
< size
; i
++) {
1070 print_events(&event_list
[i
]);
1086 * Print a list of agent events
1088 static int mi_list_session_agent_events(struct lttng_event
*events
, int count
)
1092 /* Open events element */
1093 ret
= mi_lttng_events_open(the_writer
);
1098 for (i
= 0; i
< count
; i
++) {
1099 ret
= mi_lttng_event(the_writer
, &events
[i
], 0,
1100 the_handle
->domain
.type
);
1106 /* Close events element */
1107 ret
= mi_lttng_writer_close_element(the_writer
);
1114 * List agent events for a specific session using the handle.
1116 * Return CMD_SUCCESS on success else a negative value.
1118 static int list_session_agent_events(void)
1120 int ret
= CMD_SUCCESS
, count
, i
;
1121 struct lttng_event
*events
= NULL
;
1123 count
= lttng_list_events(the_handle
, "", &events
);
1126 ERR("%s", lttng_strerror(count
));
1132 ret
= mi_list_session_agent_events(events
, count
);
1139 MSG("Events (Logger name):\n---------------------");
1141 MSG("%sNone\n", indent6
);
1145 for (i
= 0; i
< count
; i
++) {
1146 const char *filter_str
;
1147 char *filter_msg
= NULL
;
1148 struct lttng_event
*event
= &events
[i
];
1150 ret
= lttng_event_get_filter_expression(event
,
1153 filter_msg
= strdup(" [failed to retrieve filter]");
1154 } else if (filter_str
) {
1155 const char * const filter_fmt
=
1158 filter_msg
= malloc(strlen(filter_str
) +
1159 strlen(filter_fmt
) + 1);
1161 sprintf(filter_msg
, filter_fmt
,
1166 if (event
->loglevel_type
!=
1167 LTTNG_EVENT_LOGLEVEL_ALL
) {
1168 MSG("%s- %s%s (loglevel%s %s)%s", indent4
,
1170 enabled_string(event
->enabled
),
1171 logleveltype_string(
1172 event
->loglevel_type
),
1173 mi_lttng_loglevel_string(
1177 safe_string(filter_msg
));
1179 MSG("%s- %s%s%s", indent4
, event
->name
,
1180 enabled_string(event
->enabled
),
1181 safe_string(filter_msg
));
1197 * print a list of event
1199 static int mi_list_events(struct lttng_event
*events
, int count
)
1203 /* Open events element */
1204 ret
= mi_lttng_events_open(the_writer
);
1209 for (i
= 0; i
< count
; i
++) {
1210 ret
= mi_lttng_event(the_writer
, &events
[i
], 0,
1211 the_handle
->domain
.type
);
1217 /* Close events element */
1218 ret
= mi_lttng_writer_close_element(the_writer
);
1225 * List events of channel of session and domain.
1227 static int list_events(const char *channel_name
)
1229 int ret
= CMD_SUCCESS
, count
, i
;
1230 struct lttng_event
*events
= NULL
;
1232 count
= lttng_list_events(the_handle
, channel_name
, &events
);
1235 ERR("%s", lttng_strerror(count
));
1241 ret
= mi_list_events(events
, count
);
1248 MSG("\n%sRecording event rules:", indent4
);
1250 MSG("%sNone\n", indent6
);
1254 for (i
= 0; i
< count
; i
++) {
1255 print_events(&events
[i
]);
1267 void print_timer(const char *timer_name
, uint32_t space_count
, int64_t value
)
1271 _MSG("%s%s:", indent6
, timer_name
);
1272 for (i
= 0; i
< space_count
; i
++) {
1277 MSG("%" PRId64
" %s", value
, USEC_UNIT
);
1284 * Pretty print channel
1286 static void print_channel(struct lttng_channel
*channel
)
1289 uint64_t discarded_events
, lost_packets
, monitor_timer_interval
;
1290 int64_t blocking_timeout
;
1292 ret
= lttng_channel_get_discarded_event_count(channel
,
1295 ERR("Failed to retrieve discarded event count of channel");
1299 ret
= lttng_channel_get_lost_packet_count(channel
,
1302 ERR("Failed to retrieve lost packet count of channel");
1306 ret
= lttng_channel_get_monitor_timer_interval(channel
,
1307 &monitor_timer_interval
);
1309 ERR("Failed to retrieve monitor interval of channel");
1313 ret
= lttng_channel_get_blocking_timeout(channel
,
1316 ERR("Failed to retrieve blocking timeout of channel");
1320 MSG("- %s:%s\n", channel
->name
, enabled_string(channel
->enabled
));
1321 MSG("%sAttributes:", indent4
);
1322 MSG("%sEvent-loss mode: %s", indent6
, channel
->attr
.overwrite
? "overwrite" : "discard");
1323 MSG("%sSub-buffer size: %" PRIu64
" bytes", indent6
, channel
->attr
.subbuf_size
);
1324 MSG("%sSub-buffer count: %" PRIu64
, indent6
, channel
->attr
.num_subbuf
);
1326 print_timer("Switch timer", 5, channel
->attr
.switch_timer_interval
);
1327 print_timer("Read timer", 7, channel
->attr
.read_timer_interval
);
1328 print_timer("Monitor timer", 4, monitor_timer_interval
);
1330 if (!channel
->attr
.overwrite
) {
1331 if (blocking_timeout
== -1) {
1332 MSG("%sBlocking timeout: infinite", indent6
);
1334 MSG("%sBlocking timeout: %" PRId64
" %s", indent6
,
1335 blocking_timeout
, USEC_UNIT
);
1339 MSG("%sTrace file count: %" PRIu64
" per stream", indent6
,
1340 channel
->attr
.tracefile_count
== 0 ?
1341 1 : channel
->attr
.tracefile_count
);
1342 if (channel
->attr
.tracefile_size
!= 0 ) {
1343 MSG("%sTrace file size: %" PRIu64
" bytes", indent6
,
1344 channel
->attr
.tracefile_size
);
1346 MSG("%sTrace file size: %s", indent6
, "unlimited");
1348 switch (channel
->attr
.output
) {
1349 case LTTNG_EVENT_SPLICE
:
1350 MSG("%sOutput mode: splice", indent6
);
1352 case LTTNG_EVENT_MMAP
:
1353 MSG("%sOutput mode: mmap", indent6
);
1357 MSG("\n%sStatistics:", indent4
);
1358 if (the_listed_session
.snapshot_mode
) {
1360 * The lost packet count is omitted for sessions in snapshot
1361 * mode as it is misleading: it would indicate the number of
1362 * packets that the consumer could not extract during the
1363 * course of recording the snapshot. It does not have the
1364 * same meaning as the "regular" lost packet count that
1365 * would result from the consumer not keeping up with
1366 * event production in an overwrite-mode channel.
1368 * A more interesting statistic would be the number of
1369 * packets lost between the first and last extracted
1370 * packets of a given snapshot (which prevents most analyses).
1372 MSG("%sNone", indent6
);
1373 goto skip_stats_printing
;
1376 if (!channel
->attr
.overwrite
) {
1377 MSG("%sDiscarded events: %" PRIu64
, indent6
, discarded_events
);
1379 MSG("%sLost packets: %" PRIu64
, indent6
, lost_packets
);
1381 skip_stats_printing
:
1387 * Print a list of channel
1390 static int mi_list_channels(struct lttng_channel
*channels
, int count
,
1391 const char *channel_name
)
1394 unsigned int chan_found
= 0;
1396 /* Open channels element */
1397 ret
= mi_lttng_channels_open(the_writer
);
1402 for (i
= 0; i
< count
; i
++) {
1403 if (channel_name
!= NULL
) {
1404 if (strncmp(channels
[i
].name
, channel_name
, NAME_MAX
) == 0) {
1411 /* Write channel element and leave it open */
1412 ret
= mi_lttng_channel(the_writer
, &channels
[i
], 1);
1417 /* Listing events per channel */
1418 ret
= list_events(channels
[i
].name
);
1423 /* Closing the channel element we opened earlier */
1424 ret
= mi_lttng_writer_close_element(the_writer
);
1434 /* Close channels element */
1435 ret
= mi_lttng_writer_close_element(the_writer
);
1445 * List channel(s) of session and domain.
1447 * If channel_name is NULL, all channels are listed.
1449 static int list_channels(const char *channel_name
)
1451 int count
, i
, ret
= CMD_SUCCESS
;
1452 unsigned int chan_found
= 0;
1453 struct lttng_channel
*channels
= NULL
;
1455 DBG("Listing channel(s) (%s)", channel_name
? : "<all>");
1457 count
= lttng_list_channels(the_handle
, &channels
);
1460 case LTTNG_ERR_KERN_CHAN_NOT_FOUND
:
1462 /* When printing mi this is not an error
1463 * but an empty channels element */
1467 goto error_channels
;
1471 /* We had a real error */
1473 ERR("%s", lttng_strerror(count
));
1474 goto error_channels
;
1481 ret
= mi_list_channels(channels
, count
, channel_name
);
1489 MSG("Channels:\n-------------");
1492 for (i
= 0; i
< count
; i
++) {
1493 if (channel_name
!= NULL
) {
1494 if (strncmp(channels
[i
].name
, channel_name
, NAME_MAX
) == 0) {
1500 print_channel(&channels
[i
]);
1502 /* Listing events per channel */
1503 ret
= list_events(channels
[i
].name
);
1513 if (!chan_found
&& channel_name
!= NULL
) {
1515 ERR("Channel %s not found", channel_name
);
1526 static const char *get_capitalized_process_attr_str(enum lttng_process_attr process_attr
)
1528 switch (process_attr
) {
1529 case LTTNG_PROCESS_ATTR_PROCESS_ID
:
1530 return "Process ID";
1531 case LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID
:
1532 return "Virtual process ID";
1533 case LTTNG_PROCESS_ATTR_USER_ID
:
1535 case LTTNG_PROCESS_ATTR_VIRTUAL_USER_ID
:
1536 return "Virtual user ID";
1537 case LTTNG_PROCESS_ATTR_GROUP_ID
:
1539 case LTTNG_PROCESS_ATTR_VIRTUAL_GROUP_ID
:
1540 return "Virtual group ID";
1547 static int handle_process_attr_status(enum lttng_process_attr process_attr
,
1548 enum lttng_process_attr_tracker_handle_status status
)
1550 int ret
= CMD_SUCCESS
;
1553 case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_INVALID_TRACKING_POLICY
:
1554 case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_OK
:
1557 case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_COMMUNICATION_ERROR
:
1558 ERR("Communication occurred while fetching %s tracker",
1559 lttng_process_attr_to_string(process_attr
));
1562 case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_SESSION_DOES_NOT_EXIST
:
1563 ERR("Failed to get the inclusion set of the %s tracker: session `%s` no longer exists",
1564 lttng_process_attr_to_string(process_attr
),
1565 the_handle
->session_name
);
1569 ERR("Unknown error occurred while fetching the inclusion set of the %s tracker",
1570 lttng_process_attr_to_string(process_attr
));
1578 static int mi_output_empty_tracker(enum lttng_process_attr process_attr
)
1582 ret
= mi_lttng_process_attribute_tracker_open(the_writer
, process_attr
);
1587 ret
= mi_lttng_close_multi_element(the_writer
, 2);
1592 static inline bool is_value_type_name(
1593 enum lttng_process_attr_value_type value_type
)
1595 return value_type
== LTTNG_PROCESS_ATTR_VALUE_TYPE_USER_NAME
||
1596 value_type
== LTTNG_PROCESS_ATTR_VALUE_TYPE_GROUP_NAME
;
1600 * List a process attribute tracker for a session and domain tuple.
1602 static int list_process_attr_tracker(enum lttng_process_attr process_attr
)
1605 unsigned int count
, i
;
1606 enum lttng_tracking_policy policy
;
1607 enum lttng_error_code ret_code
;
1608 enum lttng_process_attr_tracker_handle_status handle_status
;
1609 enum lttng_process_attr_values_status values_status
;
1610 const struct lttng_process_attr_values
*values
;
1611 struct lttng_process_attr_tracker_handle
*tracker_handle
= NULL
;
1613 ret_code
= lttng_session_get_tracker_handle(the_handle
->session_name
,
1614 the_handle
->domain
.type
, process_attr
, &tracker_handle
);
1615 if (ret_code
!= LTTNG_OK
) {
1616 ERR("Failed to get process attribute tracker handle: %s",
1617 lttng_strerror(ret_code
));
1622 handle_status
= lttng_process_attr_tracker_handle_get_inclusion_set(
1623 tracker_handle
, &values
);
1624 ret
= handle_process_attr_status(process_attr
, handle_status
);
1625 if (ret
!= CMD_SUCCESS
) {
1629 handle_status
= lttng_process_attr_tracker_handle_get_tracking_policy(
1630 tracker_handle
, &policy
);
1631 ret
= handle_process_attr_status(process_attr
, handle_status
);
1632 if (ret
!= CMD_SUCCESS
) {
1637 char *process_attr_name
;
1638 const int print_ret
= asprintf(&process_attr_name
, "%ss:",
1639 get_capitalized_process_attr_str(process_attr
));
1641 if (print_ret
== -1) {
1645 _MSG(" %-22s", process_attr_name
);
1646 free(process_attr_name
);
1649 case LTTNG_TRACKING_POLICY_INCLUDE_SET
:
1651 case LTTNG_TRACKING_POLICY_EXCLUDE_ALL
:
1653 mi_output_empty_tracker(process_attr
);
1658 case LTTNG_TRACKING_POLICY_INCLUDE_ALL
:
1663 ERR("Unknown tracking policy encoutered while listing the %s process attribute tracker of session `%s`",
1664 lttng_process_attr_to_string(process_attr
),
1665 the_handle
->session_name
);
1670 values_status
= lttng_process_attr_values_get_count(values
, &count
);
1671 if (values_status
!= LTTNG_PROCESS_ATTR_VALUES_STATUS_OK
) {
1672 ERR("Failed to get the count of values in the inclusion set of the %s process attribute tracker of session `%s`",
1673 lttng_process_attr_to_string(process_attr
),
1674 the_handle
->session_name
);
1680 /* Functionally equivalent to the 'exclude all' policy. */
1682 mi_output_empty_tracker(process_attr
);
1689 /* Mi tracker_id element */
1691 /* Open tracker_id and targets elements */
1692 ret
= mi_lttng_process_attribute_tracker_open(
1693 the_writer
, process_attr
);
1699 for (i
= 0; i
< count
; i
++) {
1700 const enum lttng_process_attr_value_type value_type
=
1701 lttng_process_attr_values_get_type_at_index(
1703 int64_t integral_value
= INT64_MAX
;
1704 const char *name
= "error";
1709 switch (value_type
) {
1710 case LTTNG_PROCESS_ATTR_VALUE_TYPE_PID
:
1714 values_status
= lttng_process_attr_values_get_pid_at_index(
1716 integral_value
= (int64_t) pid
;
1719 case LTTNG_PROCESS_ATTR_VALUE_TYPE_UID
:
1723 values_status
= lttng_process_attr_values_get_uid_at_index(
1725 integral_value
= (int64_t) uid
;
1728 case LTTNG_PROCESS_ATTR_VALUE_TYPE_GID
:
1732 values_status
= lttng_process_attr_values_get_gid_at_index(
1734 integral_value
= (int64_t) gid
;
1737 case LTTNG_PROCESS_ATTR_VALUE_TYPE_USER_NAME
:
1738 values_status
= lttng_process_attr_values_get_user_name_at_index(
1741 case LTTNG_PROCESS_ATTR_VALUE_TYPE_GROUP_NAME
:
1742 values_status
= lttng_process_attr_values_get_group_name_at_index(
1750 if (values_status
!= LTTNG_PROCESS_ATTR_VALUES_STATUS_OK
) {
1752 * Not possible given the current liblttng-ctl
1755 ERR("Unknown error occurred while fetching process attribute value in inclusion list");
1760 if (is_value_type_name(value_type
)) {
1763 _MSG("%" PRIi64
, integral_value
);
1768 ret
= is_value_type_name(value_type
) ?
1769 mi_lttng_string_process_attribute_value(
1773 mi_lttng_integral_process_attribute_value(
1776 integral_value
, false);
1784 /* Mi close tracker_id and targets */
1786 ret
= mi_lttng_close_multi_element(the_writer
, 2);
1792 lttng_process_attr_tracker_handle_destroy(tracker_handle
);
1797 * List all trackers of a domain
1799 static int list_trackers(const struct lttng_domain
*domain
)
1803 MSG("Tracked process attributes");
1804 /* Trackers listing */
1806 ret
= mi_lttng_trackers_open(the_writer
);
1812 switch (domain
->type
) {
1813 case LTTNG_DOMAIN_KERNEL
:
1815 ret
= list_process_attr_tracker(LTTNG_PROCESS_ATTR_PROCESS_ID
);
1820 ret
= list_process_attr_tracker(
1821 LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID
);
1826 ret
= list_process_attr_tracker(LTTNG_PROCESS_ATTR_USER_ID
);
1831 ret
= list_process_attr_tracker(
1832 LTTNG_PROCESS_ATTR_VIRTUAL_USER_ID
);
1837 ret
= list_process_attr_tracker(LTTNG_PROCESS_ATTR_GROUP_ID
);
1842 ret
= list_process_attr_tracker(
1843 LTTNG_PROCESS_ATTR_VIRTUAL_GROUP_ID
);
1848 case LTTNG_DOMAIN_UST
:
1850 ret
= list_process_attr_tracker(
1851 LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID
);
1856 ret
= list_process_attr_tracker(
1857 LTTNG_PROCESS_ATTR_VIRTUAL_USER_ID
);
1862 ret
= list_process_attr_tracker(
1863 LTTNG_PROCESS_ATTR_VIRTUAL_GROUP_ID
);
1873 /* Close trackers element */
1874 ret
= mi_lttng_writer_close_element(the_writer
);
1884 static enum cmd_error_code
print_periodic_rotation_schedule(
1885 const struct lttng_rotation_schedule
*schedule
)
1887 enum cmd_error_code ret
;
1888 enum lttng_rotation_status status
;
1891 status
= lttng_rotation_schedule_periodic_get_period(schedule
,
1893 if (status
!= LTTNG_ROTATION_STATUS_OK
) {
1894 ERR("Failed to retrieve period parameter from periodic rotation schedule.");
1899 MSG(" timer period: %" PRIu64
" %s", value
, USEC_UNIT
);
1905 static enum cmd_error_code
print_size_threshold_rotation_schedule(
1906 const struct lttng_rotation_schedule
*schedule
)
1908 enum cmd_error_code ret
;
1909 enum lttng_rotation_status status
;
1912 status
= lttng_rotation_schedule_size_threshold_get_threshold(schedule
,
1914 if (status
!= LTTNG_ROTATION_STATUS_OK
) {
1915 ERR("Failed to retrieve size parameter from size-based rotation schedule.");
1920 MSG(" size threshold: %" PRIu64
" bytes", value
);
1926 static enum cmd_error_code
print_rotation_schedule(
1927 const struct lttng_rotation_schedule
*schedule
)
1929 enum cmd_error_code ret
;
1931 switch (lttng_rotation_schedule_get_type(schedule
)) {
1932 case LTTNG_ROTATION_SCHEDULE_TYPE_SIZE_THRESHOLD
:
1933 ret
= print_size_threshold_rotation_schedule(schedule
);
1935 case LTTNG_ROTATION_SCHEDULE_TYPE_PERIODIC
:
1936 ret
= print_periodic_rotation_schedule(schedule
);
1945 * List the automatic rotation settings.
1947 static enum cmd_error_code
list_rotate_settings(const char *session_name
)
1950 enum cmd_error_code cmd_ret
= CMD_SUCCESS
;
1951 unsigned int count
, i
;
1952 struct lttng_rotation_schedules
*schedules
= NULL
;
1953 enum lttng_rotation_status status
;
1955 ret
= lttng_session_list_rotation_schedules(session_name
, &schedules
);
1956 if (ret
!= LTTNG_OK
) {
1957 ERR("Failed to list session rotation schedules: %s", lttng_strerror(ret
));
1958 cmd_ret
= CMD_ERROR
;
1962 status
= lttng_rotation_schedules_get_count(schedules
, &count
);
1963 if (status
!= LTTNG_ROTATION_STATUS_OK
) {
1964 ERR("Failed to retrieve the number of session rotation schedules.");
1965 cmd_ret
= CMD_ERROR
;
1970 cmd_ret
= CMD_SUCCESS
;
1974 MSG("Automatic rotation schedules:");
1976 ret
= mi_lttng_writer_open_element(the_writer
,
1977 mi_lttng_element_rotation_schedules
);
1979 cmd_ret
= CMD_ERROR
;
1984 for (i
= 0; i
< count
; i
++) {
1985 enum cmd_error_code tmp_ret
= CMD_SUCCESS
;
1986 const struct lttng_rotation_schedule
*schedule
;
1988 schedule
= lttng_rotation_schedules_get_at_index(schedules
, i
);
1990 ERR("Failed to retrieve session rotation schedule.");
1991 cmd_ret
= CMD_ERROR
;
1996 ret
= mi_lttng_rotation_schedule(the_writer
, schedule
);
1998 tmp_ret
= CMD_ERROR
;
2001 tmp_ret
= print_rotation_schedule(schedule
);
2005 * Report an error if the serialization of any of the
2006 * descriptors failed.
2008 cmd_ret
= cmd_ret
? cmd_ret
: tmp_ret
;
2013 /* Close the rotation_schedules element. */
2014 ret
= mi_lttng_writer_close_element(the_writer
);
2016 cmd_ret
= CMD_ERROR
;
2021 lttng_rotation_schedules_destroy(schedules
);
2027 * Find the session with session_name as name
2028 * and print his informations.
2030 static int mi_list_session(const char *session_name
,
2031 struct lttng_session
*sessions
, int count
)
2034 unsigned int session_found
= 0;
2036 if (session_name
== NULL
) {
2037 ret
= -LTTNG_ERR_SESS_NOT_FOUND
;
2041 for (i
= 0; i
< count
; i
++) {
2042 if (strncmp(sessions
[i
].name
, session_name
, NAME_MAX
) == 0) {
2043 /* We need to leave it open to append other informations
2044 * like domain, channel, events etc.*/
2046 ret
= mi_lttng_session(the_writer
, &sessions
[i
], 1);
2054 if (!session_found
) {
2055 ERR("Session '%s' not found", session_name
);
2056 ret
= -LTTNG_ERR_SESS_NOT_FOUND
;
2066 * List all availables session
2068 static int mi_list_sessions(struct lttng_session
*sessions
, int count
)
2072 /* Opening sessions element */
2073 ret
= mi_lttng_sessions_open(the_writer
);
2078 /* Listing sessions */
2079 for (i
= 0; i
< count
; i
++) {
2080 ret
= mi_lttng_session(the_writer
, &sessions
[i
], 0);
2086 /* Closing sessions element */
2087 ret
= mi_lttng_writer_close_element(the_writer
);
2097 * List available tracing session. List only basic information.
2099 * If session_name is NULL, all sessions are listed.
2101 static int list_sessions(const char *session_name
)
2103 int ret
= CMD_SUCCESS
;
2105 unsigned int session_found
= 0;
2106 struct lttng_session
*sessions
= NULL
;
2108 count
= lttng_list_sessions(&sessions
);
2109 DBG("Session count %d", count
);
2112 ERR("%s", lttng_strerror(count
));
2118 if (session_name
== NULL
) {
2119 /* List all sessions */
2120 ret
= mi_list_sessions(sessions
, count
);
2122 /* Note : this return an open session element */
2123 ret
= mi_list_session(session_name
, sessions
, count
);
2132 MSG("Currently no available recording session");
2136 if (session_name
== NULL
) {
2137 MSG("Available recording sessions:");
2140 for (i
= 0; i
< count
; i
++) {
2141 if (session_name
!= NULL
) {
2142 if (strncmp(sessions
[i
].name
, session_name
, NAME_MAX
) == 0) {
2144 MSG("Recording session %s: [%s%s]", session_name
,
2145 active_string(sessions
[i
].enabled
),
2146 snapshot_string(sessions
[i
].snapshot_mode
));
2147 if (*sessions
[i
].path
) {
2148 MSG("%sTrace output: %s\n", indent4
, sessions
[i
].path
);
2150 memcpy(&the_listed_session
,
2152 sizeof(the_listed_session
));
2156 MSG(" %d) %s [%s%s]", i
+ 1,
2158 active_string(sessions
[i
].enabled
),
2159 snapshot_string(sessions
[i
].snapshot_mode
));
2160 if (*sessions
[i
].path
) {
2161 MSG("%sTrace output: %s", indent4
, sessions
[i
].path
);
2163 if (sessions
[i
].live_timer_interval
!= 0) {
2164 MSG("%sLive timer interval: %u %s", indent4
,
2165 sessions
[i
].live_timer_interval
,
2172 if (!session_found
&& session_name
!= NULL
) {
2173 ERR("Session '%s' not found", session_name
);
2178 if (session_name
== NULL
) {
2179 MSG("\nUse lttng list <session_name> for more details");
2191 * list available domain(s) for a session.
2193 static int mi_list_domains(struct lttng_domain
*domains
, int count
)
2196 /* Open domains element */
2197 ret
= mi_lttng_domains_open(the_writer
);
2202 for (i
= 0; i
< count
; i
++) {
2203 ret
= mi_lttng_domain(the_writer
, &domains
[i
], 0);
2209 /* Closing domains element */
2210 ret
= mi_lttng_writer_close_element(the_writer
);
2219 * List available domain(s) for a session.
2221 static int list_domains(const char *session_name
)
2223 int i
, count
, ret
= CMD_SUCCESS
;
2224 struct lttng_domain
*domains
= NULL
;
2227 count
= lttng_list_domains(session_name
, &domains
);
2230 ERR("%s", lttng_strerror(count
));
2236 ret
= mi_list_domains(domains
, count
);
2243 MSG("Domains:\n-------------");
2249 for (i
= 0; i
< count
; i
++) {
2250 switch (domains
[i
].type
) {
2251 case LTTNG_DOMAIN_KERNEL
:
2254 case LTTNG_DOMAIN_UST
:
2255 MSG(" - UST global");
2257 case LTTNG_DOMAIN_JUL
:
2258 MSG(" - JUL (Java Util Logging)");
2260 case LTTNG_DOMAIN_LOG4J
:
2261 MSG(" - LOG4j (Logging for Java)");
2263 case LTTNG_DOMAIN_PYTHON
:
2264 MSG(" - Python (logging)");
2280 * The 'list <options>' first level command
2282 int cmd_list(int argc
, const char **argv
)
2284 int opt
, ret
= CMD_SUCCESS
;
2285 const char *session_name
, *leftover
= NULL
;
2286 static poptContext pc
;
2287 struct lttng_domain domain
;
2288 struct lttng_domain
*domains
= NULL
;
2290 memset(&domain
, 0, sizeof(domain
));
2297 pc
= poptGetContext(NULL
, argc
, argv
, long_options
, 0);
2298 poptReadDefaultConfig(pc
, 0);
2300 while ((opt
= poptGetNextOpt(pc
)) != -1) {
2308 case OPT_LIST_OPTIONS
:
2309 list_cmd_options(stdout
, long_options
);
2312 ret
= CMD_UNDEFINED
;
2319 the_writer
= mi_lttng_writer_create(
2320 fileno(stdout
), lttng_opt_mi
);
2326 /* Open command element */
2327 ret
= mi_lttng_writer_command_open(
2328 the_writer
, mi_lttng_element_command_list
);
2334 /* Open output element */
2335 ret
= mi_lttng_writer_open_element(
2336 the_writer
, mi_lttng_element_command_output
);
2343 /* Get session name (trailing argument) */
2344 session_name
= poptGetArg(pc
);
2345 DBG2("Session name: %s", session_name
);
2347 leftover
= poptGetArg(pc
);
2349 ERR("Unknown argument: %s", leftover
);
2355 domain
.type
= LTTNG_DOMAIN_KERNEL
;
2356 } else if (opt_userspace
) {
2357 DBG2("Listing userspace global domain");
2358 domain
.type
= LTTNG_DOMAIN_UST
;
2359 } else if (opt_jul
) {
2360 DBG2("Listing JUL domain");
2361 domain
.type
= LTTNG_DOMAIN_JUL
;
2362 } else if (opt_log4j
) {
2363 domain
.type
= LTTNG_DOMAIN_LOG4J
;
2364 } else if (opt_python
) {
2365 domain
.type
= LTTNG_DOMAIN_PYTHON
;
2368 if (!opt_kernel
&& opt_syscall
) {
2369 WARN("--syscall will only work with the Kernel domain (-k)");
2374 if (opt_kernel
|| opt_userspace
|| opt_jul
|| opt_log4j
|| opt_python
) {
2375 the_handle
= lttng_create_handle(session_name
, &domain
);
2376 if (the_handle
== NULL
) {
2382 if (session_name
== NULL
) {
2383 if (!opt_kernel
&& !opt_userspace
&& !opt_jul
&& !opt_log4j
2385 ret
= list_sessions(NULL
);
2392 ret
= list_syscalls();
2397 ret
= list_kernel_events();
2403 if (opt_userspace
) {
2405 ret
= list_ust_event_fields();
2407 ret
= list_ust_events();
2413 if (opt_jul
|| opt_log4j
|| opt_python
) {
2414 ret
= list_agent_events();
2420 /* List session attributes */
2422 /* Open element sessions
2423 * Present for xml consistency */
2424 ret
= mi_lttng_sessions_open(the_writer
);
2429 /* MI: the ouptut of list_sessions is an unclosed session element */
2430 ret
= list_sessions(session_name
);
2435 ret
= list_rotate_settings(session_name
);
2440 /* Domain listing */
2442 ret
= list_domains(session_name
);
2446 /* Channel listing */
2447 if (opt_kernel
|| opt_userspace
) {
2449 /* Add of domains and domain element for xml
2450 * consistency and validation
2452 ret
= mi_lttng_domains_open(the_writer
);
2457 /* Open domain and leave it open for
2458 * nested channels printing */
2459 ret
= mi_lttng_domain(the_writer
, &domain
, 1);
2468 ret
= list_trackers(&domain
);
2474 ret
= list_channels(opt_channel
);
2480 /* Close domain and domain element */
2481 ret
= mi_lttng_close_multi_element(
2492 /* We want all domain(s) */
2493 nb_domain
= lttng_list_domains(session_name
, &domains
);
2494 if (nb_domain
< 0) {
2496 ERR("%s", lttng_strerror(nb_domain
));
2501 ret
= mi_lttng_domains_open(the_writer
);
2508 for (i
= 0; i
< nb_domain
; i
++) {
2509 switch (domains
[i
].type
) {
2510 case LTTNG_DOMAIN_KERNEL
:
2511 MSG("=== Domain: Linux kernel ===\n");
2513 case LTTNG_DOMAIN_UST
:
2514 MSG("=== Domain: User space ===\n");
2515 MSG("Buffering scheme: %s\n",
2516 domains
[i
].buf_type
==
2517 LTTNG_BUFFER_PER_PID
? "per-process" : "per-user");
2519 case LTTNG_DOMAIN_JUL
:
2520 MSG("=== Domain: java.util.logging (JUL) ===\n");
2522 case LTTNG_DOMAIN_LOG4J
:
2523 MSG("=== Domain: log4j ===\n");
2525 case LTTNG_DOMAIN_PYTHON
:
2526 MSG("=== Domain: Python logging ===\n");
2529 MSG("=== Domain: Unimplemented ===\n");
2534 ret
= mi_lttng_domain(the_writer
,
2542 /* Clean handle before creating a new one */
2544 lttng_destroy_handle(the_handle
);
2547 the_handle
= lttng_create_handle(
2548 session_name
, &domains
[i
]);
2549 if (the_handle
== NULL
) {
2554 if (domains
[i
].type
== LTTNG_DOMAIN_JUL
||
2555 domains
[i
].type
== LTTNG_DOMAIN_LOG4J
||
2556 domains
[i
].type
== LTTNG_DOMAIN_PYTHON
) {
2557 ret
= list_session_agent_events();
2565 switch (domains
[i
].type
) {
2566 case LTTNG_DOMAIN_KERNEL
:
2567 case LTTNG_DOMAIN_UST
:
2568 ret
= list_trackers(&domains
[i
]);
2577 ret
= list_channels(opt_channel
);
2584 /* Close domain element */
2585 ret
= mi_lttng_writer_close_element(
2595 /* Close the domains, session and sessions element */
2596 ret
= mi_lttng_close_multi_element(
2608 /* Close output element */
2609 ret
= mi_lttng_writer_close_element(the_writer
);
2615 /* Command element close */
2616 ret
= mi_lttng_writer_command_close(the_writer
);
2624 if (the_writer
&& mi_lttng_writer_destroy(the_writer
)) {
2625 /* Preserve original error code */
2626 ret
= ret
? ret
: -LTTNG_ERR_MI_IO_FAIL
;
2631 lttng_destroy_handle(the_handle
);
2634 poptFreeContext(pc
);