Mi: add mi support for lttng struct
[lttng-tools.git] / src / bin / lttng / commands / list.c
... / ...
CommitLineData
1/*
2 * Copyright (C) 2011 - David Goulet <david.goulet@polymtl.ca>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License, version 2 only,
6 * as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write to the Free Software Foundation, Inc.,
15 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
16 */
17
18#define _GNU_SOURCE
19#include <inttypes.h>
20#include <popt.h>
21#include <stdio.h>
22#include <stdlib.h>
23#include <string.h>
24#include <assert.h>
25
26#include "../command.h"
27
28static int opt_userspace;
29static int opt_kernel;
30static int opt_jul;
31static char *opt_channel;
32static int opt_domain;
33static int opt_fields;
34#if 0
35/* Not implemented yet */
36static char *opt_cmd_name;
37static pid_t opt_pid;
38#endif
39
40const char *indent4 = " ";
41const char *indent6 = " ";
42const char *indent8 = " ";
43
44enum {
45 OPT_HELP = 1,
46 OPT_USERSPACE,
47 OPT_LIST_OPTIONS,
48};
49
50static struct lttng_handle *handle;
51
52static struct poptOption long_options[] = {
53 /* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
54 {"help", 'h', POPT_ARG_NONE, 0, OPT_HELP, 0, 0},
55 {"kernel", 'k', POPT_ARG_VAL, &opt_kernel, 1, 0, 0},
56 {"jul", 'j', POPT_ARG_VAL, &opt_jul, 1, 0, 0},
57#if 0
58 /* Not implemented yet */
59 {"userspace", 'u', POPT_ARG_STRING | POPT_ARGFLAG_OPTIONAL, &opt_cmd_name, OPT_USERSPACE, 0, 0},
60 {"pid", 'p', POPT_ARG_INT, &opt_pid, 0, 0, 0},
61#else
62 {"userspace", 'u', POPT_ARG_NONE, 0, OPT_USERSPACE, 0, 0},
63#endif
64 {"channel", 'c', POPT_ARG_STRING, &opt_channel, 0, 0, 0},
65 {"domain", 'd', POPT_ARG_VAL, &opt_domain, 1, 0, 0},
66 {"fields", 'f', POPT_ARG_VAL, &opt_fields, 1, 0, 0},
67 {"list-options", 0, POPT_ARG_NONE, NULL, OPT_LIST_OPTIONS, NULL, NULL},
68 {0, 0, 0, 0, 0, 0, 0}
69};
70
71/*
72 * usage
73 */
74static void usage(FILE *ofp)
75{
76 fprintf(ofp, "usage: lttng list [OPTIONS] [SESSION [SESSION OPTIONS]]\n");
77 fprintf(ofp, "\n");
78 fprintf(ofp, "With no arguments, list available tracing session(s)\n");
79 fprintf(ofp, "\n");
80 fprintf(ofp, "Without a session, -k lists available kernel events\n");
81 fprintf(ofp, "Without a session, -u lists available userspace events\n");
82 fprintf(ofp, "\n");
83 fprintf(ofp, " -h, --help Show this help\n");
84 fprintf(ofp, " --list-options Simple listing of options\n");
85 fprintf(ofp, " -k, --kernel Select kernel domain\n");
86 fprintf(ofp, " -u, --userspace Select user-space domain.\n");
87 fprintf(ofp, " -j, --jul Apply for Java application using JUL\n");
88 fprintf(ofp, " -f, --fields List event fields.\n");
89#if 0
90 fprintf(ofp, " -p, --pid PID List user-space events by PID\n");
91#endif
92 fprintf(ofp, "\n");
93 fprintf(ofp, "Session Options:\n");
94 fprintf(ofp, " -c, --channel NAME List details of a channel\n");
95 fprintf(ofp, " -d, --domain List available domain(s)\n");
96 fprintf(ofp, "\n");
97}
98
99/*
100 * Get command line from /proc for a specific pid.
101 *
102 * On success, return an allocated string pointer to the proc cmdline.
103 * On error, return NULL.
104 */
105static char *get_cmdline_by_pid(pid_t pid)
106{
107 int ret;
108 FILE *fp;
109 char *cmdline = NULL;
110 char path[20]; /* Can't go bigger than /proc/65535/cmdline */
111
112 snprintf(path, sizeof(path), "/proc/%d/cmdline", pid);
113 fp = fopen(path, "r");
114 if (fp == NULL) {
115 goto end;
116 }
117
118 /* Caller must free() *cmdline */
119 cmdline = malloc(PATH_MAX);
120 if (!cmdline) {
121 perror("malloc cmdline");
122 goto end;
123 }
124 ret = fread(cmdline, 1, PATH_MAX, fp);
125 if (ret < 0) {
126 perror("fread proc list");
127 }
128 fclose(fp);
129
130end:
131 return cmdline;
132}
133
134static
135const char *active_string(int value)
136{
137 switch (value) {
138 case 0: return "inactive";
139 case 1: return "active";
140 case -1: return "";
141 default: return NULL;
142 }
143}
144
145static const char *snapshot_string(int value)
146{
147 switch (value) {
148 case 1:
149 return " snapshot";
150 default:
151 return "";
152 }
153}
154
155static
156const char *enabled_string(int value)
157{
158 switch (value) {
159 case 0: return " [disabled]";
160 case 1: return " [enabled]";
161 case -1: return "";
162 default: return NULL;
163 }
164}
165
166static
167const char *filter_string(int value)
168{
169 switch (value) {
170 case 1: return " [with filter]";
171 default: return "";
172 }
173}
174
175static
176const char *exclusion_string(int value)
177{
178 switch (value) {
179 case 1: return " [has exclusions]";
180 default: return "";
181 }
182}
183
184static const char *loglevel_jul_string(int value)
185{
186 switch (value) {
187 case -1:
188 return "";
189 case LTTNG_LOGLEVEL_JUL_OFF:
190 return "JUL_OFF";
191 case LTTNG_LOGLEVEL_JUL_SEVERE:
192 return "JUL_SEVERE";
193 case LTTNG_LOGLEVEL_JUL_WARNING:
194 return "JUL_WARNING";
195 case LTTNG_LOGLEVEL_JUL_INFO:
196 return "JUL_INFO";
197 case LTTNG_LOGLEVEL_JUL_CONFIG:
198 return "JUL_CONFIG";
199 case LTTNG_LOGLEVEL_JUL_FINE:
200 return "JUL_FINE";
201 case LTTNG_LOGLEVEL_JUL_FINER:
202 return "JUL_FINER";
203 case LTTNG_LOGLEVEL_JUL_FINEST:
204 return "JUL_FINEST";
205 case LTTNG_LOGLEVEL_JUL_ALL:
206 return "JUL_ALL";
207 default:
208 return "<<UNKNOWN>>";
209 }
210}
211
212static const char *loglevel_string(int value)
213{
214 switch (value) {
215 case -1:
216 return "";
217 case LTTNG_LOGLEVEL_EMERG:
218 return "TRACE_EMERG";
219 case LTTNG_LOGLEVEL_ALERT:
220 return "TRACE_ALERT";
221 case LTTNG_LOGLEVEL_CRIT:
222 return "TRACE_CRIT";
223 case LTTNG_LOGLEVEL_ERR:
224 return "TRACE_ERR";
225 case LTTNG_LOGLEVEL_WARNING:
226 return "TRACE_WARNING";
227 case LTTNG_LOGLEVEL_NOTICE:
228 return "TRACE_NOTICE";
229 case LTTNG_LOGLEVEL_INFO:
230 return "TRACE_INFO";
231 case LTTNG_LOGLEVEL_DEBUG_SYSTEM:
232 return "TRACE_DEBUG_SYSTEM";
233 case LTTNG_LOGLEVEL_DEBUG_PROGRAM:
234 return "TRACE_DEBUG_PROGRAM";
235 case LTTNG_LOGLEVEL_DEBUG_PROCESS:
236 return "TRACE_DEBUG_PROCESS";
237 case LTTNG_LOGLEVEL_DEBUG_MODULE:
238 return "TRACE_DEBUG_MODULE";
239 case LTTNG_LOGLEVEL_DEBUG_UNIT:
240 return "TRACE_DEBUG_UNIT";
241 case LTTNG_LOGLEVEL_DEBUG_FUNCTION:
242 return "TRACE_DEBUG_FUNCTION";
243 case LTTNG_LOGLEVEL_DEBUG_LINE:
244 return "TRACE_DEBUG_LINE";
245 case LTTNG_LOGLEVEL_DEBUG:
246 return "TRACE_DEBUG";
247 default:
248 return "<<UNKNOWN>>";
249 }
250}
251
252static const char *logleveltype_string(enum lttng_loglevel_type value)
253{
254 switch (value) {
255 case LTTNG_EVENT_LOGLEVEL_ALL:
256 return ":";
257 case LTTNG_EVENT_LOGLEVEL_RANGE:
258 return " <=";
259 case LTTNG_EVENT_LOGLEVEL_SINGLE:
260 return " ==";
261 default:
262 return " <<TYPE UNKN>>";
263 }
264}
265
266/*
267 * Pretty print single event.
268 */
269static void print_events(struct lttng_event *event)
270{
271 switch (event->type) {
272 case LTTNG_EVENT_TRACEPOINT:
273 {
274 if (event->loglevel != -1) {
275 MSG("%s%s (loglevel%s %s (%d)) (type: tracepoint)%s%s%s",
276 indent6,
277 event->name,
278 logleveltype_string(event->loglevel_type),
279 loglevel_string(event->loglevel),
280 event->loglevel,
281 enabled_string(event->enabled),
282 exclusion_string(event->exclusion),
283 filter_string(event->filter));
284 } else {
285 MSG("%s%s (type: tracepoint)%s%s%s",
286 indent6,
287 event->name,
288 enabled_string(event->enabled),
289 exclusion_string(event->exclusion),
290 filter_string(event->filter));
291 }
292 break;
293 }
294 case LTTNG_EVENT_FUNCTION:
295 MSG("%s%s (type: function)%s%s", indent6,
296 event->name, enabled_string(event->enabled),
297 filter_string(event->filter));
298 if (event->attr.probe.addr != 0) {
299 MSG("%saddr: 0x%" PRIx64, indent8, event->attr.probe.addr);
300 } else {
301 MSG("%soffset: 0x%" PRIx64, indent8, event->attr.probe.offset);
302 MSG("%ssymbol: %s", indent8, event->attr.probe.symbol_name);
303 }
304 break;
305 case LTTNG_EVENT_PROBE:
306 MSG("%s%s (type: probe)%s%s", indent6,
307 event->name, enabled_string(event->enabled),
308 filter_string(event->filter));
309 if (event->attr.probe.addr != 0) {
310 MSG("%saddr: 0x%" PRIx64, indent8, event->attr.probe.addr);
311 } else {
312 MSG("%soffset: 0x%" PRIx64, indent8, event->attr.probe.offset);
313 MSG("%ssymbol: %s", indent8, event->attr.probe.symbol_name);
314 }
315 break;
316 case LTTNG_EVENT_FUNCTION_ENTRY:
317 MSG("%s%s (type: function)%s%s", indent6,
318 event->name, enabled_string(event->enabled),
319 filter_string(event->filter));
320 MSG("%ssymbol: \"%s\"", indent8, event->attr.ftrace.symbol_name);
321 break;
322 case LTTNG_EVENT_SYSCALL:
323 MSG("%ssyscalls (type: syscall)%s%s", indent6,
324 enabled_string(event->enabled),
325 filter_string(event->filter));
326 break;
327 case LTTNG_EVENT_NOOP:
328 MSG("%s (type: noop)%s%s", indent6,
329 enabled_string(event->enabled),
330 filter_string(event->filter));
331 break;
332 case LTTNG_EVENT_ALL:
333 /* We should never have "all" events in list. */
334 assert(0);
335 break;
336 }
337}
338
339static const char *field_type(struct lttng_event_field *field)
340{
341 switch(field->type) {
342 case LTTNG_EVENT_FIELD_INTEGER:
343 return "integer";
344 case LTTNG_EVENT_FIELD_ENUM:
345 return "enum";
346 case LTTNG_EVENT_FIELD_FLOAT:
347 return "float";
348 case LTTNG_EVENT_FIELD_STRING:
349 return "string";
350 case LTTNG_EVENT_FIELD_OTHER:
351 default: /* fall-through */
352 return "unknown";
353 }
354}
355
356/*
357 * Pretty print single event fields.
358 */
359static void print_event_field(struct lttng_event_field *field)
360{
361 if (!field->field_name[0]) {
362 return;
363 }
364 MSG("%sfield: %s (%s)%s", indent8, field->field_name,
365 field_type(field), field->nowrite ? " [no write]" : "");
366}
367
368static int list_jul_events(void)
369{
370 int i, size;
371 struct lttng_domain domain;
372 struct lttng_handle *handle;
373 struct lttng_event *event_list;
374 pid_t cur_pid = 0;
375 char *cmdline = NULL;
376
377 DBG("Getting JUL tracing events");
378
379 memset(&domain, 0, sizeof(domain));
380 domain.type = LTTNG_DOMAIN_JUL;
381
382 handle = lttng_create_handle(NULL, &domain);
383 if (handle == NULL) {
384 goto error;
385 }
386
387 size = lttng_list_tracepoints(handle, &event_list);
388 if (size < 0) {
389 ERR("Unable to list JUL events: %s", lttng_strerror(size));
390 lttng_destroy_handle(handle);
391 return size;
392 }
393
394 MSG("JUL events (Logger name):\n-------------------------");
395
396 if (size == 0) {
397 MSG("None");
398 }
399
400 for (i = 0; i < size; i++) {
401 if (cur_pid != event_list[i].pid) {
402 cur_pid = event_list[i].pid;
403 cmdline = get_cmdline_by_pid(cur_pid);
404 MSG("\nPID: %d - Name: %s", cur_pid, cmdline);
405 free(cmdline);
406 }
407 MSG("%s- %s", indent6, event_list[i].name);
408 }
409
410 MSG("");
411
412 free(event_list);
413 lttng_destroy_handle(handle);
414
415 return CMD_SUCCESS;
416
417error:
418 lttng_destroy_handle(handle);
419 return -1;
420}
421
422/*
423 * Ask session daemon for all user space tracepoints available.
424 */
425static int list_ust_events(void)
426{
427 int i, size;
428 struct lttng_domain domain;
429 struct lttng_handle *handle;
430 struct lttng_event *event_list;
431 pid_t cur_pid = 0;
432 char *cmdline = NULL;
433
434 memset(&domain, 0, sizeof(domain));
435
436 DBG("Getting UST tracing events");
437
438 domain.type = LTTNG_DOMAIN_UST;
439
440 handle = lttng_create_handle(NULL, &domain);
441 if (handle == NULL) {
442 goto error;
443 }
444
445 size = lttng_list_tracepoints(handle, &event_list);
446 if (size < 0) {
447 ERR("Unable to list UST events: %s", lttng_strerror(size));
448 lttng_destroy_handle(handle);
449 return size;
450 }
451
452 MSG("UST events:\n-------------");
453
454 if (size == 0) {
455 MSG("None");
456 }
457
458 for (i = 0; i < size; i++) {
459 if (cur_pid != event_list[i].pid) {
460 cur_pid = event_list[i].pid;
461 cmdline = get_cmdline_by_pid(cur_pid);
462 MSG("\nPID: %d - Name: %s", cur_pid, cmdline);
463 free(cmdline);
464 }
465 print_events(&event_list[i]);
466 }
467
468 MSG("");
469
470 free(event_list);
471 lttng_destroy_handle(handle);
472
473 return CMD_SUCCESS;
474
475error:
476 lttng_destroy_handle(handle);
477 return -1;
478}
479
480/*
481 * Ask session daemon for all user space tracepoint fields available.
482 */
483static int list_ust_event_fields(void)
484{
485 int i, size;
486 struct lttng_domain domain;
487 struct lttng_handle *handle;
488 struct lttng_event_field *event_field_list;
489 pid_t cur_pid = 0;
490 char *cmdline = NULL;
491
492 struct lttng_event cur_event;
493
494 memset(&domain, 0, sizeof(domain));
495 memset(&cur_event, 0, sizeof(cur_event));
496
497 DBG("Getting UST tracing event fields");
498
499 domain.type = LTTNG_DOMAIN_UST;
500
501 handle = lttng_create_handle(NULL, &domain);
502 if (handle == NULL) {
503 goto error;
504 }
505
506 size = lttng_list_tracepoint_fields(handle, &event_field_list);
507 if (size < 0) {
508 ERR("Unable to list UST event fields: %s", lttng_strerror(size));
509 lttng_destroy_handle(handle);
510 return size;
511 }
512
513 MSG("UST events:\n-------------");
514
515 if (size == 0) {
516 MSG("None");
517 }
518
519 for (i = 0; i < size; i++) {
520 if (cur_pid != event_field_list[i].event.pid) {
521 cur_pid = event_field_list[i].event.pid;
522 cmdline = get_cmdline_by_pid(cur_pid);
523 MSG("\nPID: %d - Name: %s", cur_pid, cmdline);
524 free(cmdline);
525 /* Wipe current event since we are about to print a new PID. */
526 memset(&cur_event, 0, sizeof(cur_event));
527 }
528 if (strcmp(cur_event.name, event_field_list[i].event.name) != 0) {
529 print_events(&event_field_list[i].event);
530 memcpy(&cur_event, &event_field_list[i].event,
531 sizeof(cur_event));
532 }
533 print_event_field(&event_field_list[i]);
534 }
535
536 MSG("");
537
538 free(event_field_list);
539 lttng_destroy_handle(handle);
540
541 return CMD_SUCCESS;
542
543error:
544 lttng_destroy_handle(handle);
545 return -1;
546}
547
548/*
549 * Ask for all trace events in the kernel and pretty print them.
550 */
551static int list_kernel_events(void)
552{
553 int i, size;
554 struct lttng_domain domain;
555 struct lttng_handle *handle;
556 struct lttng_event *event_list;
557
558 memset(&domain, 0, sizeof(domain));
559
560 DBG("Getting kernel tracing events");
561
562 domain.type = LTTNG_DOMAIN_KERNEL;
563
564 handle = lttng_create_handle(NULL, &domain);
565 if (handle == NULL) {
566 goto error;
567 }
568
569 size = lttng_list_tracepoints(handle, &event_list);
570 if (size < 0) {
571 ERR("Unable to list kernel events: %s", lttng_strerror(size));
572 lttng_destroy_handle(handle);
573 return size;
574 }
575
576 MSG("Kernel events:\n-------------");
577
578 for (i = 0; i < size; i++) {
579 print_events(&event_list[i]);
580 }
581
582 MSG("");
583
584 free(event_list);
585
586 lttng_destroy_handle(handle);
587 return CMD_SUCCESS;
588
589error:
590 lttng_destroy_handle(handle);
591 return -1;
592}
593
594/*
595 * List JUL events for a specific session using the handle.
596 *
597 * Return CMD_SUCCESS on success else a negative value.
598 */
599static int list_session_jul_events(void)
600{
601 int ret, count, i;
602 struct lttng_event *events = NULL;
603
604 count = lttng_list_events(handle, "", &events);
605 if (count < 0) {
606 ret = count;
607 ERR("%s", lttng_strerror(ret));
608 goto error;
609 }
610
611 MSG("Events (Logger name):\n---------------------");
612 if (count == 0) {
613 MSG("%sNone\n", indent6);
614 goto end;
615 }
616
617 for (i = 0; i < count; i++) {
618 MSG("%s- %s%s (loglevel%s %s)", indent4, events[i].name,
619 enabled_string(events[i].enabled),
620 logleveltype_string(events[i].loglevel_type),
621 loglevel_jul_string(events[i].loglevel));
622 }
623
624 MSG("");
625
626end:
627 free(events);
628 ret = CMD_SUCCESS;
629
630error:
631 return ret;
632}
633
634/*
635 * List events of channel of session and domain.
636 */
637static int list_events(const char *channel_name)
638{
639 int ret, count, i;
640 struct lttng_event *events = NULL;
641
642 count = lttng_list_events(handle, channel_name, &events);
643 if (count < 0) {
644 ret = count;
645 ERR("%s", lttng_strerror(ret));
646 goto error;
647 }
648
649 MSG("\n%sEvents:", indent4);
650 if (count == 0) {
651 MSG("%sNone\n", indent6);
652 goto end;
653 }
654
655 for (i = 0; i < count; i++) {
656 print_events(&events[i]);
657 }
658
659 MSG("");
660
661end:
662 free(events);
663 ret = CMD_SUCCESS;
664
665error:
666 return ret;
667}
668
669/*
670 * Pretty print channel
671 */
672static void print_channel(struct lttng_channel *channel)
673{
674 MSG("- %s:%s\n", channel->name, enabled_string(channel->enabled));
675
676 MSG("%sAttributes:", indent4);
677 MSG("%soverwrite mode: %d", indent6, channel->attr.overwrite);
678 MSG("%ssubbufers size: %" PRIu64, indent6, channel->attr.subbuf_size);
679 MSG("%snumber of subbufers: %" PRIu64, indent6, channel->attr.num_subbuf);
680 MSG("%sswitch timer interval: %u", indent6, channel->attr.switch_timer_interval);
681 MSG("%sread timer interval: %u", indent6, channel->attr.read_timer_interval);
682 MSG("%strace file count: %" PRIu64, indent6, channel->attr.tracefile_count);
683 MSG("%strace file size (bytes): %" PRIu64, indent6, channel->attr.tracefile_size);
684 switch (channel->attr.output) {
685 case LTTNG_EVENT_SPLICE:
686 MSG("%soutput: splice()", indent6);
687 break;
688 case LTTNG_EVENT_MMAP:
689 MSG("%soutput: mmap()", indent6);
690 break;
691 }
692}
693
694/*
695 * List channel(s) of session and domain.
696 *
697 * If channel_name is NULL, all channels are listed.
698 */
699static int list_channels(const char *channel_name)
700{
701 int count, i, ret = CMD_SUCCESS;
702 unsigned int chan_found = 0;
703 struct lttng_channel *channels = NULL;
704
705 DBG("Listing channel(s) (%s)", channel_name ? : "<all>");
706
707 count = lttng_list_channels(handle, &channels);
708 if (count < 0) {
709 switch (-count) {
710 case LTTNG_ERR_KERN_CHAN_NOT_FOUND:
711 ret = CMD_SUCCESS;
712 WARN("No kernel channel");
713 break;
714 default:
715 /* We had a real error */
716 ret = count;
717 ERR("%s", lttng_strerror(ret));
718 break;
719 }
720 goto error_channels;
721 }
722
723 if (channel_name == NULL) {
724 MSG("Channels:\n-------------");
725 }
726
727 for (i = 0; i < count; i++) {
728 if (channel_name != NULL) {
729 if (strncmp(channels[i].name, channel_name, NAME_MAX) == 0) {
730 chan_found = 1;
731 } else {
732 continue;
733 }
734 }
735 print_channel(&channels[i]);
736
737 /* Listing events per channel */
738 ret = list_events(channels[i].name);
739 if (ret < 0) {
740 ERR("%s", lttng_strerror(ret));
741 }
742
743 if (chan_found) {
744 break;
745 }
746 }
747
748 if (!chan_found && channel_name != NULL) {
749 ERR("Channel %s not found", channel_name);
750 goto error;
751 }
752
753 ret = CMD_SUCCESS;
754
755error:
756 free(channels);
757
758error_channels:
759 return ret;
760}
761
762/*
763 * List available tracing session. List only basic information.
764 *
765 * If session_name is NULL, all sessions are listed.
766 */
767static int list_sessions(const char *session_name)
768{
769 int ret, count, i;
770 unsigned int session_found = 0;
771 struct lttng_session *sessions;
772
773 count = lttng_list_sessions(&sessions);
774 DBG("Session count %d", count);
775 if (count < 0) {
776 ret = count;
777 ERR("%s", lttng_strerror(ret));
778 goto error;
779 } else if (count == 0) {
780 MSG("Currently no available tracing session");
781 goto end;
782 }
783
784 if (session_name == NULL) {
785 MSG("Available tracing sessions:");
786 }
787
788 for (i = 0; i < count; i++) {
789 if (session_name != NULL) {
790 if (strncmp(sessions[i].name, session_name, NAME_MAX) == 0) {
791 session_found = 1;
792 MSG("Tracing session %s: [%s%s]", session_name,
793 active_string(sessions[i].enabled),
794 snapshot_string(sessions[i].snapshot_mode));
795 MSG("%sTrace path: %s", indent4, sessions[i].path);
796 MSG("%sLive timer interval (usec): %u\n", indent4,
797 sessions[i].live_timer_interval);
798 break;
799 }
800 } else {
801 MSG(" %d) %s (%s) [%s%s]", i + 1, sessions[i].name, sessions[i].path,
802 active_string(sessions[i].enabled),
803 snapshot_string(sessions[i].snapshot_mode));
804 }
805 }
806
807 free(sessions);
808
809 if (!session_found && session_name != NULL) {
810 ERR("Session '%s' not found", session_name);
811 ret = CMD_ERROR;
812 goto error;
813 }
814
815 if (session_name == NULL) {
816 MSG("\nUse lttng list <session_name> for more details");
817 }
818
819end:
820 return CMD_SUCCESS;
821
822error:
823 return ret;
824}
825
826/*
827 * List available domain(s) for a session.
828 */
829static int list_domains(const char *session_name)
830{
831 int i, count, ret = CMD_SUCCESS;
832 struct lttng_domain *domains = NULL;
833
834 MSG("Domains:\n-------------");
835
836 count = lttng_list_domains(session_name, &domains);
837 if (count < 0) {
838 ret = count;
839 ERR("%s", lttng_strerror(ret));
840 goto error;
841 } else if (count == 0) {
842 MSG(" None");
843 goto end;
844 }
845
846 for (i = 0; i < count; i++) {
847 switch (domains[i].type) {
848 case LTTNG_DOMAIN_KERNEL:
849 MSG(" - Kernel");
850 break;
851 case LTTNG_DOMAIN_UST:
852 MSG(" - UST global");
853 break;
854 case LTTNG_DOMAIN_JUL:
855 MSG(" - JUL (Java Util Logging)");
856 break;
857 default:
858 break;
859 }
860 }
861
862end:
863 free(domains);
864
865error:
866 return ret;
867}
868
869/*
870 * The 'list <options>' first level command
871 */
872int cmd_list(int argc, const char **argv)
873{
874 int opt, ret = CMD_SUCCESS;
875 const char *session_name;
876 static poptContext pc;
877 struct lttng_domain domain;
878 struct lttng_domain *domains = NULL;
879
880 memset(&domain, 0, sizeof(domain));
881
882 if (argc < 1) {
883 usage(stderr);
884 ret = CMD_ERROR;
885 goto end;
886 }
887
888 pc = poptGetContext(NULL, argc, argv, long_options, 0);
889 poptReadDefaultConfig(pc, 0);
890
891 /* TODO: mi support */
892 if (lttng_opt_mi) {
893 ret = -LTTNG_ERR_MI_NOT_IMPLEMENTED;
894 ERR("mi option not supported");
895 goto end;
896 }
897
898 while ((opt = poptGetNextOpt(pc)) != -1) {
899 switch (opt) {
900 case OPT_HELP:
901 usage(stdout);
902 goto end;
903 case OPT_USERSPACE:
904 opt_userspace = 1;
905 break;
906 case OPT_LIST_OPTIONS:
907 list_cmd_options(stdout, long_options);
908 goto end;
909 default:
910 usage(stderr);
911 ret = CMD_UNDEFINED;
912 goto end;
913 }
914 }
915
916 /* Get session name (trailing argument) */
917 session_name = poptGetArg(pc);
918 DBG2("Session name: %s", session_name);
919
920 if (opt_kernel) {
921 domain.type = LTTNG_DOMAIN_KERNEL;
922 } else if (opt_userspace) {
923 DBG2("Listing userspace global domain");
924 domain.type = LTTNG_DOMAIN_UST;
925 } else if (opt_jul) {
926 DBG2("Listing JUL domain");
927 domain.type = LTTNG_DOMAIN_JUL;
928 }
929
930 if (opt_kernel || opt_userspace || opt_jul) {
931 handle = lttng_create_handle(session_name, &domain);
932 if (handle == NULL) {
933 ret = CMD_FATAL;
934 goto end;
935 }
936 }
937
938 if (session_name == NULL) {
939 if (!opt_kernel && !opt_userspace && !opt_jul) {
940 ret = list_sessions(NULL);
941 if (ret != 0) {
942 goto end;
943 }
944 }
945 if (opt_kernel) {
946 ret = list_kernel_events();
947 if (ret < 0) {
948 ret = CMD_ERROR;
949 goto end;
950 }
951 }
952 if (opt_userspace) {
953 if (opt_fields) {
954 ret = list_ust_event_fields();
955 } else {
956 ret = list_ust_events();
957 }
958 if (ret < 0) {
959 ret = CMD_ERROR;
960 goto end;
961 }
962 }
963 if (opt_jul) {
964 ret = list_jul_events();
965 if (ret < 0) {
966 ret = CMD_ERROR;
967 goto end;
968 }
969 }
970 } else {
971 /* List session attributes */
972 ret = list_sessions(session_name);
973 if (ret != 0) {
974 goto end;
975 }
976
977 /* Domain listing */
978 if (opt_domain) {
979 ret = list_domains(session_name);
980 goto end;
981 }
982
983 if (opt_kernel || opt_userspace) {
984 /* Channel listing */
985 ret = list_channels(opt_channel);
986 if (ret < 0) {
987 goto end;
988 }
989 } else {
990 int i, nb_domain;
991
992 /* We want all domain(s) */
993 nb_domain = lttng_list_domains(session_name, &domains);
994 if (nb_domain < 0) {
995 ret = nb_domain;
996 ERR("%s", lttng_strerror(ret));
997 goto end;
998 }
999
1000 for (i = 0; i < nb_domain; i++) {
1001 switch (domains[i].type) {
1002 case LTTNG_DOMAIN_KERNEL:
1003 MSG("=== Domain: Kernel ===\n");
1004 break;
1005 case LTTNG_DOMAIN_UST:
1006 MSG("=== Domain: UST global ===\n");
1007 MSG("Buffer type: %s\n",
1008 domains[i].buf_type ==
1009 LTTNG_BUFFER_PER_PID ? "per PID" : "per UID");
1010 break;
1011 case LTTNG_DOMAIN_JUL:
1012 MSG("=== Domain: JUL (Java Util Logging) ===\n");
1013 break;
1014 default:
1015 MSG("=== Domain: Unimplemented ===\n");
1016 break;
1017 }
1018
1019 /* Clean handle before creating a new one */
1020 if (handle) {
1021 lttng_destroy_handle(handle);
1022 }
1023
1024 handle = lttng_create_handle(session_name, &domains[i]);
1025 if (handle == NULL) {
1026 ret = CMD_FATAL;
1027 goto end;
1028 }
1029
1030 if (domains[i].type == LTTNG_DOMAIN_JUL) {
1031 ret = list_session_jul_events();
1032 if (ret < 0) {
1033 goto end;
1034 }
1035 continue;
1036 }
1037
1038 ret = list_channels(opt_channel);
1039 if (ret < 0) {
1040 goto end;
1041 }
1042 }
1043 }
1044 }
1045
1046end:
1047 free(domains);
1048 if (handle) {
1049 lttng_destroy_handle(handle);
1050 }
1051
1052 poptFreeContext(pc);
1053 return ret;
1054}
This page took 0.026255 seconds and 4 git commands to generate.