Fix: Don't report an error when listing a session with no channels
[lttng-tools.git] / src / bin / lttng / commands / list.c
CommitLineData
f3ed775e
DG
1/*
2 * Copyright (C) 2011 - David Goulet <david.goulet@polymtl.ca>
3 *
d14d33bf
AM
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.
f3ed775e
DG
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 *
d14d33bf
AM
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.
f3ed775e
DG
16 */
17
18#define _GNU_SOURCE
9f19cc17 19#include <inttypes.h>
f3ed775e
DG
20#include <popt.h>
21#include <stdio.h>
22#include <stdlib.h>
23#include <string.h>
7a3d1328 24#include <assert.h>
f3ed775e 25
c399183f 26#include "../command.h"
f3ed775e 27
9f19cc17
DG
28static int opt_userspace;
29static int opt_kernel;
3c6a091f 30static int opt_jul;
9f19cc17
DG
31static char *opt_channel;
32static int opt_domain;
f37d259d 33static int opt_fields;
d78d6610
DG
34#if 0
35/* Not implemented yet */
36static char *opt_cmd_name;
37static pid_t opt_pid;
38#endif
9f19cc17
DG
39
40const char *indent4 = " ";
41const char *indent6 = " ";
42const char *indent8 = " ";
f3ed775e
DG
43
44enum {
45 OPT_HELP = 1,
eeac7d46 46 OPT_USERSPACE,
679b4943 47 OPT_LIST_OPTIONS,
f3ed775e
DG
48};
49
cd80958d
DG
50static struct lttng_handle *handle;
51
f3ed775e
DG
52static struct poptOption long_options[] = {
53 /* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
54 {"help", 'h', POPT_ARG_NONE, 0, OPT_HELP, 0, 0},
9f19cc17 55 {"kernel", 'k', POPT_ARG_VAL, &opt_kernel, 1, 0, 0},
3c6a091f 56 {"jul", 'j', POPT_ARG_VAL, &opt_jul, 1, 0, 0},
d78d6610
DG
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
9f19cc17
DG
64 {"channel", 'c', POPT_ARG_STRING, &opt_channel, 0, 0, 0},
65 {"domain", 'd', POPT_ARG_VAL, &opt_domain, 1, 0, 0},
f37d259d 66 {"fields", 'f', POPT_ARG_VAL, &opt_fields, 1, 0, 0},
679b4943 67 {"list-options", 0, POPT_ARG_NONE, NULL, OPT_LIST_OPTIONS, NULL, NULL},
f3ed775e
DG
68 {0, 0, 0, 0, 0, 0, 0}
69};
70
71/*
72 * usage
73 */
74static void usage(FILE *ofp)
75{
747361fe 76 fprintf(ofp, "usage: lttng list [OPTIONS] [SESSION [SESSION OPTIONS]]\n");
9f19cc17
DG
77 fprintf(ofp, "\n");
78 fprintf(ofp, "With no arguments, list available tracing session(s)\n");
79 fprintf(ofp, "\n");
27221701
DG
80 fprintf(ofp, "Without a session, -k lists available kernel events\n");
81 fprintf(ofp, "Without a session, -u lists available userspace events\n");
9f19cc17
DG
82 fprintf(ofp, "\n");
83 fprintf(ofp, " -h, --help Show this help\n");
27221701 84 fprintf(ofp, " --list-options Simple listing of options\n");
9f19cc17
DG
85 fprintf(ofp, " -k, --kernel Select kernel domain\n");
86 fprintf(ofp, " -u, --userspace Select user-space domain.\n");
3c6a091f 87 fprintf(ofp, " -j, --jul Apply for Java application using JUL\n");
f37d259d 88 fprintf(ofp, " -f, --fields List event fields.\n");
d78d6610 89#if 0
9f19cc17 90 fprintf(ofp, " -p, --pid PID List user-space events by PID\n");
d78d6610 91#endif
f3ed775e 92 fprintf(ofp, "\n");
27221701 93 fprintf(ofp, "Session Options:\n");
9f19cc17
DG
94 fprintf(ofp, " -c, --channel NAME List details of a channel\n");
95 fprintf(ofp, " -d, --domain List available domain(s)\n");
f3ed775e
DG
96 fprintf(ofp, "\n");
97}
98
99/*
9f19cc17 100 * Get command line from /proc for a specific pid.
f3ed775e 101 *
9f19cc17
DG
102 * On success, return an allocated string pointer to the proc cmdline.
103 * On error, return NULL.
f3ed775e
DG
104 */
105static char *get_cmdline_by_pid(pid_t pid)
106{
107 int ret;
108 FILE *fp;
109 char *cmdline = NULL;
f2b2a1ab 110 char path[20]; /* Can't go bigger than /proc/65535/cmdline */
f3ed775e
DG
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);
b1674e11
JG
120 if (!cmdline) {
121 perror("malloc cmdline");
122 goto end;
123 }
f3ed775e 124 ret = fread(cmdline, 1, PATH_MAX, fp);
f40799e8
DG
125 if (ret < 0) {
126 perror("fread proc list");
127 }
f3ed775e
DG
128 fclose(fp);
129
130end:
131 return cmdline;
132}
b551a063 133
464dd62d
MD
134static
135const char *active_string(int value)
136{
137 switch (value) {
2cbf8fed
DG
138 case 0: return "inactive";
139 case 1: return "active";
464dd62d
MD
140 case -1: return "";
141 default: return NULL;
142 }
143}
144
2cbf8fed
DG
145static const char *snapshot_string(int value)
146{
147 switch (value) {
148 case 1:
149 return " snapshot";
150 default:
151 return "";
152 }
153}
154
464dd62d
MD
155static
156const char *enabled_string(int value)
157{
158 switch (value) {
b09f0429
MD
159 case 0: return " [disabled]";
160 case 1: return " [enabled]";
464dd62d
MD
161 case -1: return "";
162 default: return NULL;
163 }
164}
165
fceb65df
MD
166static
167const char *filter_string(int value)
168{
169 switch (value) {
170 case 1: return " [with filter]";
171 default: return "";
172 }
173}
174
4634f12e
JI
175static
176const char *exclusion_string(int value)
177{
178 switch (value) {
179 case 1: return " [has exclusions]";
180 default: return "";
181 }
182}
183
ff94328f
DG
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
8005f29a
MD
212static const char *loglevel_string(int value)
213{
214 switch (value) {
255a5dab
MD
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>>";
8005f29a
MD
249 }
250}
251
1f0e17de
DG
252static const char *logleveltype_string(enum lttng_loglevel_type value)
253{
254 switch (value) {
af6bce80
DG
255 case LTTNG_EVENT_LOGLEVEL_ALL:
256 return ":";
1f0e17de 257 case LTTNG_EVENT_LOGLEVEL_RANGE:
af6bce80 258 return " <=";
1f0e17de 259 case LTTNG_EVENT_LOGLEVEL_SINGLE:
af6bce80 260 return " ==";
1f0e17de 261 default:
af6bce80 262 return " <<TYPE UNKN>>";
1f0e17de
DG
263 }
264}
265
b551a063
DG
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:
e4baff1e 273 {
8b703175 274 if (event->loglevel != -1) {
af6bce80 275 MSG("%s%s (loglevel%s %s (%d)) (type: tracepoint)%s%s%s",
8b703175 276 indent6,
81afa345 277 event->name,
1f0e17de 278 logleveltype_string(event->loglevel_type),
8005f29a 279 loglevel_string(event->loglevel),
8b703175 280 event->loglevel,
fceb65df 281 enabled_string(event->enabled),
4634f12e 282 exclusion_string(event->exclusion),
fceb65df 283 filter_string(event->filter));
8b703175 284 } else {
4634f12e 285 MSG("%s%s (type: tracepoint)%s%s%s",
8b703175
MD
286 indent6,
287 event->name,
fceb65df 288 enabled_string(event->enabled),
4634f12e 289 exclusion_string(event->exclusion),
fceb65df 290 filter_string(event->filter));
8b703175 291 }
b551a063 292 break;
e4baff1e 293 }
1896972b
DG
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;
b551a063 305 case LTTNG_EVENT_PROBE:
fceb65df
MD
306 MSG("%s%s (type: probe)%s%s", indent6,
307 event->name, enabled_string(event->enabled),
308 filter_string(event->filter));
b551a063
DG
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;
b551a063 316 case LTTNG_EVENT_FUNCTION_ENTRY:
fceb65df
MD
317 MSG("%s%s (type: function)%s%s", indent6,
318 event->name, enabled_string(event->enabled),
319 filter_string(event->filter));
b551a063
DG
320 MSG("%ssymbol: \"%s\"", indent8, event->attr.ftrace.symbol_name);
321 break;
322 case LTTNG_EVENT_SYSCALL:
fceb65df
MD
323 MSG("%ssyscalls (type: syscall)%s%s", indent6,
324 enabled_string(event->enabled),
325 filter_string(event->filter));
b551a063
DG
326 break;
327 case LTTNG_EVENT_NOOP:
fceb65df
MD
328 MSG("%s (type: noop)%s%s", indent6,
329 enabled_string(event->enabled),
330 filter_string(event->filter));
b551a063
DG
331 break;
332 case LTTNG_EVENT_ALL:
333 /* We should never have "all" events in list. */
334 assert(0);
335 break;
336 }
337}
338
f37d259d
MD
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 }
d8fbe2a9 364 MSG("%sfield: %s (%s)%s", indent8, field->field_name,
45a32634 365 field_type(field), field->nowrite ? " [no write]" : "");
f37d259d
MD
366}
367
3c6a091f
DG
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
b551a063
DG
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;
ea5cbc00 432 char *cmdline = NULL;
b551a063 433
441c16a7
MD
434 memset(&domain, 0, sizeof(domain));
435
b551a063
DG
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) {
60e835ca 447 ERR("Unable to list UST events: %s", lttng_strerror(size));
ef021732 448 lttng_destroy_handle(handle);
b551a063
DG
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;
ea5cbc00
CB
461 cmdline = get_cmdline_by_pid(cur_pid);
462 MSG("\nPID: %d - Name: %s", cur_pid, cmdline);
463 free(cmdline);
b551a063
DG
464 }
465 print_events(&event_list[i]);
466 }
467
468 MSG("");
469
470 free(event_list);
ef021732 471 lttng_destroy_handle(handle);
b551a063
DG
472
473 return CMD_SUCCESS;
474
475error:
ef021732 476 lttng_destroy_handle(handle);
b551a063
DG
477 return -1;
478}
f3ed775e 479
f37d259d
MD
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;
ea5cbc00
CB
490 char *cmdline = NULL;
491
f37d259d
MD
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) {
60e835ca 508 ERR("Unable to list UST event fields: %s", lttng_strerror(size));
f37d259d
MD
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;
ea5cbc00
CB
522 cmdline = get_cmdline_by_pid(cur_pid);
523 MSG("\nPID: %d - Name: %s", cur_pid, cmdline);
524 free(cmdline);
8966b2b0
DG
525 /* Wipe current event since we are about to print a new PID. */
526 memset(&cur_event, 0, sizeof(cur_event));
f37d259d
MD
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
f3ed775e 548/*
9f19cc17 549 * Ask for all trace events in the kernel and pretty print them.
f3ed775e 550 */
9f19cc17 551static int list_kernel_events(void)
f3ed775e 552{
9f19cc17 553 int i, size;
b551a063
DG
554 struct lttng_domain domain;
555 struct lttng_handle *handle;
9f19cc17 556 struct lttng_event *event_list;
f3ed775e 557
441c16a7
MD
558 memset(&domain, 0, sizeof(domain));
559
b551a063
DG
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 }
f3ed775e 568
cd80958d 569 size = lttng_list_tracepoints(handle, &event_list);
9f19cc17 570 if (size < 0) {
60e835ca 571 ERR("Unable to list kernel events: %s", lttng_strerror(size));
ef021732 572 lttng_destroy_handle(handle);
9f19cc17 573 return size;
f3ed775e
DG
574 }
575
9f19cc17 576 MSG("Kernel events:\n-------------");
f3ed775e 577
9f19cc17 578 for (i = 0; i < size; i++) {
b551a063 579 print_events(&event_list[i]);
f3ed775e
DG
580 }
581
b551a063
DG
582 MSG("");
583
f3ed775e
DG
584 free(event_list);
585
ef021732 586 lttng_destroy_handle(handle);
f3ed775e 587 return CMD_SUCCESS;
b551a063
DG
588
589error:
ef021732 590 lttng_destroy_handle(handle);
b551a063 591 return -1;
f3ed775e
DG
592}
593
3c6a091f
DG
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++) {
ff94328f
DG
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));
3c6a091f
DG
622 }
623
624 MSG("");
625
626end:
627 free(events);
628 ret = CMD_SUCCESS;
629
630error:
631 return ret;
632}
633
f3ed775e 634/*
9f19cc17 635 * List events of channel of session and domain.
f3ed775e 636 */
cd80958d 637static int list_events(const char *channel_name)
f3ed775e
DG
638{
639 int ret, count, i;
9f19cc17 640 struct lttng_event *events = NULL;
f3ed775e 641
cd80958d 642 count = lttng_list_events(handle, channel_name, &events);
f3ed775e
DG
643 if (count < 0) {
644 ret = count;
60e835ca 645 ERR("%s", lttng_strerror(ret));
f3ed775e
DG
646 goto error;
647 }
648
9f19cc17
DG
649 MSG("\n%sEvents:", indent4);
650 if (count == 0) {
5edd7e09 651 MSG("%sNone\n", indent6);
9f19cc17
DG
652 goto end;
653 }
654
f3ed775e 655 for (i = 0; i < count; i++) {
b551a063 656 print_events(&events[i]);
f3ed775e
DG
657 }
658
9f19cc17 659 MSG("");
f3ed775e 660
9f19cc17 661end:
0e428499 662 free(events);
9f19cc17 663 ret = CMD_SUCCESS;
f3ed775e
DG
664
665error:
666 return ret;
667}
668
669/*
9f19cc17
DG
670 * Pretty print channel
671 */
672static void print_channel(struct lttng_channel *channel)
673{
464dd62d 674 MSG("- %s:%s\n", channel->name, enabled_string(channel->enabled));
9f19cc17
DG
675
676 MSG("%sAttributes:", indent4);
a5bbe8f6
DG
677 MSG("%soverwrite mode: %d", indent6, channel->attr.overwrite);
678 MSG("%ssubbufers size: %" PRIu64, indent6, channel->attr.subbuf_size);
9f19cc17 679 MSG("%snumber of subbufers: %" PRIu64, indent6, channel->attr.num_subbuf);
a5bbe8f6
DG
680 MSG("%sswitch timer interval: %u", indent6, channel->attr.switch_timer_interval);
681 MSG("%sread timer interval: %u", indent6, channel->attr.read_timer_interval);
2f785fe7
DG
682 MSG("%strace file count: %" PRIu64, indent6, channel->attr.tracefile_count);
683 MSG("%strace file size (bytes): %" PRIu64, indent6, channel->attr.tracefile_size);
9f19cc17
DG
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.
f3ed775e 696 *
9f19cc17 697 * If channel_name is NULL, all channels are listed.
f3ed775e 698 */
cd80958d 699static int list_channels(const char *channel_name)
f3ed775e 700{
9f19cc17
DG
701 int count, i, ret = CMD_SUCCESS;
702 unsigned int chan_found = 0;
703 struct lttng_channel *channels = NULL;
f3ed775e 704
3e25cb20 705 DBG("Listing channel(s) (%s)", channel_name ? : "<all>");
9f19cc17 706
cd80958d 707 count = lttng_list_channels(handle, &channels);
f3ed775e 708 if (count < 0) {
c7d620a2
DG
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));
60e835ca 718 break;
c7d620a2 719 }
ae856491 720 goto error_channels;
f3ed775e
DG
721 }
722
d2243cc1 723 if (count) {
9f19cc17
DG
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 */
cd80958d 738 ret = list_events(channels[i].name);
9f19cc17 739 if (ret < 0) {
60e835ca 740 ERR("%s", lttng_strerror(ret));
9f19cc17
DG
741 }
742
743 if (chan_found) {
744 break;
f3ed775e 745 }
f3ed775e
DG
746 }
747
9f19cc17 748 if (!chan_found && channel_name != NULL) {
ae856491
DG
749 ERR("Channel %s not found", channel_name);
750 goto error;
9f19cc17 751 }
f3ed775e 752
9f19cc17 753 ret = CMD_SUCCESS;
f3ed775e
DG
754
755error:
ae856491
DG
756 free(channels);
757
758error_channels:
f3ed775e
DG
759 return ret;
760}
761
762/*
9f19cc17 763 * List available tracing session. List only basic information.
f3ed775e 764 *
9f19cc17 765 * If session_name is NULL, all sessions are listed.
f3ed775e 766 */
9f19cc17 767static int list_sessions(const char *session_name)
f3ed775e 768{
9f19cc17
DG
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;
8f3f773f 777 ERR("%s", lttng_strerror(ret));
9f19cc17 778 goto error;
d32fb093
DG
779 } else if (count == 0) {
780 MSG("Currently no available tracing session");
781 goto end;
9f19cc17
DG
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;
2cbf8fed
DG
792 MSG("Tracing session %s: [%s%s]", session_name,
793 active_string(sessions[i].enabled),
794 snapshot_string(sessions[i].snapshot_mode));
2f785fe7
DG
795 MSG("%sTrace path: %s", indent4, sessions[i].path);
796 MSG("%sLive timer interval (usec): %u\n", indent4,
797 sessions[i].live_timer_interval);
9f19cc17
DG
798 break;
799 }
3842aa86 800 } else {
2cbf8fed
DG
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));
9f19cc17
DG
804 }
805 }
806
807 free(sessions);
808
809 if (!session_found && session_name != NULL) {
b6913340
DG
810 ERR("Session '%s' not found", session_name);
811 ret = CMD_ERROR;
812 goto error;
9f19cc17
DG
813 }
814
815 if (session_name == NULL) {
6e0de39b 816 MSG("\nUse lttng list <session_name> for more details");
9f19cc17 817 }
f3ed775e 818
d32fb093 819end:
f3ed775e
DG
820 return CMD_SUCCESS;
821
822error:
823 return ret;
824}
f3ed775e
DG
825
826/*
9f19cc17 827 * List available domain(s) for a session.
f3ed775e 828 */
330be774 829static int list_domains(const char *session_name)
f3ed775e 830{
9f19cc17
DG
831 int i, count, ret = CMD_SUCCESS;
832 struct lttng_domain *domains = NULL;
833
834 MSG("Domains:\n-------------");
835
330be774 836 count = lttng_list_domains(session_name, &domains);
9f19cc17
DG
837 if (count < 0) {
838 ret = count;
60e835ca 839 ERR("%s", lttng_strerror(ret));
9f19cc17
DG
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");
b551a063
DG
850 break;
851 case LTTNG_DOMAIN_UST:
852 MSG(" - UST global");
853 break;
3c6a091f
DG
854 case LTTNG_DOMAIN_JUL:
855 MSG(" - JUL (Java Util Logging)");
856 break;
9f19cc17
DG
857 default:
858 break;
859 }
860 }
861
862end:
863 free(domains);
864
865error:
866 return ret;
f3ed775e 867}
f3ed775e
DG
868
869/*
9f19cc17 870 * The 'list <options>' first level command
f3ed775e
DG
871 */
872int cmd_list(int argc, const char **argv)
873{
c617c0c6 874 int opt, ret = CMD_SUCCESS;
9f19cc17 875 const char *session_name;
f3ed775e 876 static poptContext pc;
9f19cc17
DG
877 struct lttng_domain domain;
878 struct lttng_domain *domains = NULL;
f3ed775e 879
441c16a7
MD
880 memset(&domain, 0, sizeof(domain));
881
9f19cc17 882 if (argc < 1) {
f3ed775e 883 usage(stderr);
ca1c3607 884 ret = CMD_ERROR;
f3ed775e
DG
885 goto end;
886 }
887
888 pc = poptGetContext(NULL, argc, argv, long_options, 0);
889 poptReadDefaultConfig(pc, 0);
890
891 while ((opt = poptGetNextOpt(pc)) != -1) {
892 switch (opt) {
893 case OPT_HELP:
ca1c3607 894 usage(stdout);
f3ed775e 895 goto end;
eeac7d46
MD
896 case OPT_USERSPACE:
897 opt_userspace = 1;
eeac7d46 898 break;
679b4943
SM
899 case OPT_LIST_OPTIONS:
900 list_cmd_options(stdout, long_options);
679b4943 901 goto end;
f3ed775e
DG
902 default:
903 usage(stderr);
904 ret = CMD_UNDEFINED;
905 goto end;
906 }
907 }
908
9f19cc17
DG
909 /* Get session name (trailing argument) */
910 session_name = poptGetArg(pc);
b551a063 911 DBG2("Session name: %s", session_name);
9f19cc17 912
cd80958d
DG
913 if (opt_kernel) {
914 domain.type = LTTNG_DOMAIN_KERNEL;
b551a063
DG
915 } else if (opt_userspace) {
916 DBG2("Listing userspace global domain");
917 domain.type = LTTNG_DOMAIN_UST;
3c6a091f
DG
918 } else if (opt_jul) {
919 DBG2("Listing JUL domain");
920 domain.type = LTTNG_DOMAIN_JUL;
cd80958d
DG
921 }
922
3c6a091f 923 if (opt_kernel || opt_userspace || opt_jul) {
aa5de748
MD
924 handle = lttng_create_handle(session_name, &domain);
925 if (handle == NULL) {
926 ret = CMD_FATAL;
927 goto end;
928 }
cd80958d
DG
929 }
930
9f19cc17 931 if (session_name == NULL) {
3c6a091f 932 if (!opt_kernel && !opt_userspace && !opt_jul) {
b551a063 933 ret = list_sessions(NULL);
b6913340 934 if (ret != 0) {
b551a063
DG
935 goto end;
936 }
937 }
9f19cc17
DG
938 if (opt_kernel) {
939 ret = list_kernel_events();
940 if (ret < 0) {
6191db77 941 ret = CMD_ERROR;
9f19cc17
DG
942 goto end;
943 }
b551a063
DG
944 }
945 if (opt_userspace) {
f37d259d
MD
946 if (opt_fields) {
947 ret = list_ust_event_fields();
948 } else {
949 ret = list_ust_events();
950 }
9f19cc17 951 if (ret < 0) {
6191db77 952 ret = CMD_ERROR;
9f19cc17
DG
953 goto end;
954 }
955 }
3c6a091f
DG
956 if (opt_jul) {
957 ret = list_jul_events();
958 if (ret < 0) {
959 ret = CMD_ERROR;
960 goto end;
961 }
962 }
9f19cc17
DG
963 } else {
964 /* List session attributes */
965 ret = list_sessions(session_name);
b6913340 966 if (ret != 0) {
9f19cc17
DG
967 goto end;
968 }
969
970 /* Domain listing */
971 if (opt_domain) {
330be774 972 ret = list_domains(session_name);
9f19cc17
DG
973 goto end;
974 }
975
1c3de747 976 if (opt_kernel || opt_userspace) {
9f19cc17 977 /* Channel listing */
cd80958d 978 ret = list_channels(opt_channel);
9f19cc17
DG
979 if (ret < 0) {
980 goto end;
981 }
9f19cc17 982 } else {
c617c0c6
MD
983 int i, nb_domain;
984
9f19cc17 985 /* We want all domain(s) */
330be774 986 nb_domain = lttng_list_domains(session_name, &domains);
b551a063 987 if (nb_domain < 0) {
67635185 988 ret = nb_domain;
60e835ca 989 ERR("%s", lttng_strerror(ret));
9f19cc17
DG
990 goto end;
991 }
992
b551a063 993 for (i = 0; i < nb_domain; i++) {
9f19cc17
DG
994 switch (domains[i].type) {
995 case LTTNG_DOMAIN_KERNEL:
996 MSG("=== Domain: Kernel ===\n");
997 break;
b551a063
DG
998 case LTTNG_DOMAIN_UST:
999 MSG("=== Domain: UST global ===\n");
88c5f0d8
DG
1000 MSG("Buffer type: %s\n",
1001 domains[i].buf_type ==
1002 LTTNG_BUFFER_PER_PID ? "per PID" : "per UID");
b551a063 1003 break;
3c6a091f
DG
1004 case LTTNG_DOMAIN_JUL:
1005 MSG("=== Domain: JUL (Java Util Logging) ===\n");
1006 break;
9f19cc17
DG
1007 default:
1008 MSG("=== Domain: Unimplemented ===\n");
1009 break;
1010 }
1011
cd80958d 1012 /* Clean handle before creating a new one */
aa5de748
MD
1013 if (handle) {
1014 lttng_destroy_handle(handle);
1015 }
cd80958d
DG
1016
1017 handle = lttng_create_handle(session_name, &domains[i]);
1018 if (handle == NULL) {
ca1c3607 1019 ret = CMD_FATAL;
cd80958d
DG
1020 goto end;
1021 }
1022
3c6a091f
DG
1023 if (domains[i].type == LTTNG_DOMAIN_JUL) {
1024 ret = list_session_jul_events();
1025 if (ret < 0) {
1026 goto end;
1027 }
1028 continue;
1029 }
1030
cd80958d 1031 ret = list_channels(opt_channel);
9f19cc17
DG
1032 if (ret < 0) {
1033 goto end;
1034 }
1035 }
1036 }
f3ed775e
DG
1037 }
1038
1039end:
0e428499 1040 free(domains);
aa5de748
MD
1041 if (handle) {
1042 lttng_destroy_handle(handle);
1043 }
cd80958d 1044
ca1c3607 1045 poptFreeContext(pc);
f3ed775e
DG
1046 return ret;
1047}
This page took 0.102015 seconds and 4 git commands to generate.