X-Git-Url: http://git.efficios.com/?p=lttng-tools.git;a=blobdiff_plain;f=src%2Fbin%2Flttng%2Fcommands%2Flist.c;h=1c7085dd7018c5b788ed23ad409f924a552066cf;hp=7c33046ebec1490f798ca4a63e71f0778f91c1db;hb=f20baf8e44b5d8a1c90b8b029b876762f6f916a6;hpb=081311398b0deca05eebaac8672efbc9af272d36 diff --git a/src/bin/lttng/commands/list.c b/src/bin/lttng/commands/list.c index 7c33046eb..1c7085dd7 100644 --- a/src/bin/lttng/commands/list.c +++ b/src/bin/lttng/commands/list.c @@ -1,19 +1,18 @@ /* * Copyright (C) 2011 - David Goulet * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; only version 2 - * of the License. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2 only, + * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #define _GNU_SOURCE @@ -30,6 +29,7 @@ static int opt_userspace; static int opt_kernel; static char *opt_channel; static int opt_domain; +static int opt_fields; #if 0 /* Not implemented yet */ static char *opt_cmd_name; @@ -61,6 +61,7 @@ static struct poptOption long_options[] = { #endif {"channel", 'c', POPT_ARG_STRING, &opt_channel, 0, 0, 0}, {"domain", 'd', POPT_ARG_VAL, &opt_domain, 1, 0, 0}, + {"fields", 'f', POPT_ARG_VAL, &opt_fields, 1, 0, 0}, {"list-options", 0, POPT_ARG_NONE, NULL, OPT_LIST_OPTIONS, NULL, NULL}, {0, 0, 0, 0, 0, 0, 0} }; @@ -70,7 +71,7 @@ static struct poptOption long_options[] = { */ static void usage(FILE *ofp) { - fprintf(ofp, "usage: lttng list [OPTIONS] [SESSION []]\n"); + fprintf(ofp, "usage: lttng list [OPTIONS] [SESSION [SESSION OPTIONS]]\n"); fprintf(ofp, "\n"); fprintf(ofp, "With no arguments, list available tracing session(s)\n"); fprintf(ofp, "\n"); @@ -81,6 +82,7 @@ static void usage(FILE *ofp) fprintf(ofp, " --list-options Simple listing of options\n"); fprintf(ofp, " -k, --kernel Select kernel domain\n"); fprintf(ofp, " -u, --userspace Select user-space domain.\n"); + fprintf(ofp, " -f, --fields List event fields.\n"); #if 0 fprintf(ofp, " -p, --pid PID List user-space events by PID\n"); #endif @@ -126,13 +128,23 @@ static const char *active_string(int value) { switch (value) { - case 0: return " [inactive]"; - case 1: return " [active]"; + case 0: return "inactive"; + case 1: return "active"; case -1: return ""; default: return NULL; } } +static const char *snapshot_string(int value) +{ + switch (value) { + case 1: + return " snapshot"; + default: + return ""; + } +} + static const char *enabled_string(int value) { @@ -145,46 +157,51 @@ const char *enabled_string(int value) } static -const char *loglevel_string_pre(int loglevel) -{ - if (loglevel == -1) { - return ""; - } else { - return " (loglevel: "; - } -} - -static -const char *loglevel_string_post(int loglevel) +const char *filter_string(int value) { - if (loglevel == -1) { - return ""; - } else { - return ")"; + switch (value) { + case 1: return " [with filter]"; + default: return ""; } } static const char *loglevel_string(int value) { switch (value) { - case -1: return ""; - case 0: return "TRACE_EMERG"; - case 1: return "TRACE_ALERT"; - case 2: return "TRACE_CRIT"; - case 3: return "TRACE_ERR"; - case 4: return "TRACE_WARNING"; - case 5: return "TRACE_NOTICE"; - case 6: return "TRACE_INFO"; - case 7: return "TRACE_SYSTEM"; - case 8: return "TRACE_PROGRAM"; - case 9: return "TRACE_PROCESS"; - case 10: return "TRACE_MODULE"; - case 11: return "TRACE_UNIT"; - case 12: return "TRACE_FUNCTION"; - case 13: return "TRACE_DEFAULT"; - case 14: return "TRACE_VERBOSE"; - case 15: return "TRACE_DEBUG"; - default: return "<>"; + case -1: + return ""; + case LTTNG_LOGLEVEL_EMERG: + return "TRACE_EMERG"; + case LTTNG_LOGLEVEL_ALERT: + return "TRACE_ALERT"; + case LTTNG_LOGLEVEL_CRIT: + return "TRACE_CRIT"; + case LTTNG_LOGLEVEL_ERR: + return "TRACE_ERR"; + case LTTNG_LOGLEVEL_WARNING: + return "TRACE_WARNING"; + case LTTNG_LOGLEVEL_NOTICE: + return "TRACE_NOTICE"; + case LTTNG_LOGLEVEL_INFO: + return "TRACE_INFO"; + case LTTNG_LOGLEVEL_DEBUG_SYSTEM: + return "TRACE_DEBUG_SYSTEM"; + case LTTNG_LOGLEVEL_DEBUG_PROGRAM: + return "TRACE_DEBUG_PROGRAM"; + case LTTNG_LOGLEVEL_DEBUG_PROCESS: + return "TRACE_DEBUG_PROCESS"; + case LTTNG_LOGLEVEL_DEBUG_MODULE: + return "TRACE_DEBUG_MODULE"; + case LTTNG_LOGLEVEL_DEBUG_UNIT: + return "TRACE_DEBUG_UNIT"; + case LTTNG_LOGLEVEL_DEBUG_FUNCTION: + return "TRACE_DEBUG_FUNCTION"; + case LTTNG_LOGLEVEL_DEBUG_LINE: + return "TRACE_DEBUG_LINE"; + case LTTNG_LOGLEVEL_DEBUG: + return "TRACE_DEBUG"; + default: + return "<>"; } } @@ -196,17 +213,38 @@ static void print_events(struct lttng_event *event) switch (event->type) { case LTTNG_EVENT_TRACEPOINT: { - MSG("%s%s%s%s%s (type: tracepoint)%s", indent6, + if (event->loglevel != -1) { + MSG("%s%s (loglevel: %s (%d)) (type: tracepoint)%s%s", + indent6, event->name, - loglevel_string_pre(event->loglevel), loglevel_string(event->loglevel), - loglevel_string_post(event->loglevel), - enabled_string(event->enabled)); + event->loglevel, + enabled_string(event->enabled), + filter_string(event->filter)); + } else { + MSG("%s%s (type: tracepoint)%s%s", + indent6, + event->name, + enabled_string(event->enabled), + filter_string(event->filter)); + } break; } + case LTTNG_EVENT_FUNCTION: + MSG("%s%s (type: function)%s%s", indent6, + event->name, enabled_string(event->enabled), + filter_string(event->filter)); + if (event->attr.probe.addr != 0) { + MSG("%saddr: 0x%" PRIx64, indent8, event->attr.probe.addr); + } else { + MSG("%soffset: 0x%" PRIx64, indent8, event->attr.probe.offset); + MSG("%ssymbol: %s", indent8, event->attr.probe.symbol_name); + } + break; case LTTNG_EVENT_PROBE: - MSG("%s%s (type: probe)%s", indent6, - event->name, enabled_string(event->enabled)); + MSG("%s%s (type: probe)%s%s", indent6, + event->name, enabled_string(event->enabled), + filter_string(event->filter)); if (event->attr.probe.addr != 0) { MSG("%saddr: 0x%" PRIx64, indent8, event->attr.probe.addr); } else { @@ -214,19 +252,21 @@ static void print_events(struct lttng_event *event) MSG("%ssymbol: %s", indent8, event->attr.probe.symbol_name); } break; - case LTTNG_EVENT_FUNCTION: case LTTNG_EVENT_FUNCTION_ENTRY: - MSG("%s%s (type: function)%s", indent6, - event->name, enabled_string(event->enabled)); + MSG("%s%s (type: function)%s%s", indent6, + event->name, enabled_string(event->enabled), + filter_string(event->filter)); MSG("%ssymbol: \"%s\"", indent8, event->attr.ftrace.symbol_name); break; case LTTNG_EVENT_SYSCALL: - MSG("%s (type: syscall)%s", indent6, - enabled_string(event->enabled)); + MSG("%ssyscalls (type: syscall)%s%s", indent6, + enabled_string(event->enabled), + filter_string(event->filter)); break; case LTTNG_EVENT_NOOP: - MSG("%s (type: noop)%s", indent6, - enabled_string(event->enabled)); + MSG("%s (type: noop)%s%s", indent6, + enabled_string(event->enabled), + filter_string(event->filter)); break; case LTTNG_EVENT_ALL: /* We should never have "all" events in list. */ @@ -235,6 +275,35 @@ static void print_events(struct lttng_event *event) } } +static const char *field_type(struct lttng_event_field *field) +{ + switch(field->type) { + case LTTNG_EVENT_FIELD_INTEGER: + return "integer"; + case LTTNG_EVENT_FIELD_ENUM: + return "enum"; + case LTTNG_EVENT_FIELD_FLOAT: + return "float"; + case LTTNG_EVENT_FIELD_STRING: + return "string"; + case LTTNG_EVENT_FIELD_OTHER: + default: /* fall-through */ + return "unknown"; + } +} + +/* + * Pretty print single event fields. + */ +static void print_event_field(struct lttng_event_field *field) +{ + if (!field->field_name[0]) { + return; + } + MSG("%sfield: %s (%s)%s", indent8, field->field_name, + field_type(field), field->nowrite ? " [no write]" : ""); +} + /* * Ask session daemon for all user space tracepoints available. */ @@ -245,6 +314,7 @@ static int list_ust_events(void) struct lttng_handle *handle; struct lttng_event *event_list; pid_t cur_pid = 0; + char *cmdline = NULL; memset(&domain, 0, sizeof(domain)); @@ -259,7 +329,8 @@ static int list_ust_events(void) size = lttng_list_tracepoints(handle, &event_list); if (size < 0) { - ERR("Unable to list UST events"); + ERR("Unable to list UST events: %s", lttng_strerror(size)); + lttng_destroy_handle(handle); return size; } @@ -272,7 +343,9 @@ static int list_ust_events(void) for (i = 0; i < size; i++) { if (cur_pid != event_list[i].pid) { cur_pid = event_list[i].pid; - MSG("\nPID: %d - Name: %s", cur_pid, get_cmdline_by_pid(cur_pid)); + cmdline = get_cmdline_by_pid(cur_pid); + MSG("\nPID: %d - Name: %s", cur_pid, cmdline); + free(cmdline); } print_events(&event_list[i]); } @@ -280,10 +353,78 @@ static int list_ust_events(void) MSG(""); free(event_list); + lttng_destroy_handle(handle); return CMD_SUCCESS; error: + lttng_destroy_handle(handle); + return -1; +} + +/* + * Ask session daemon for all user space tracepoint fields available. + */ +static int list_ust_event_fields(void) +{ + int i, size; + struct lttng_domain domain; + struct lttng_handle *handle; + struct lttng_event_field *event_field_list; + pid_t cur_pid = 0; + char *cmdline = NULL; + + struct lttng_event cur_event; + + memset(&domain, 0, sizeof(domain)); + memset(&cur_event, 0, sizeof(cur_event)); + + DBG("Getting UST tracing event fields"); + + domain.type = LTTNG_DOMAIN_UST; + + handle = lttng_create_handle(NULL, &domain); + if (handle == NULL) { + goto error; + } + + size = lttng_list_tracepoint_fields(handle, &event_field_list); + if (size < 0) { + ERR("Unable to list UST event fields: %s", lttng_strerror(size)); + lttng_destroy_handle(handle); + return size; + } + + MSG("UST events:\n-------------"); + + if (size == 0) { + MSG("None"); + } + + for (i = 0; i < size; i++) { + if (cur_pid != event_field_list[i].event.pid) { + cur_pid = event_field_list[i].event.pid; + cmdline = get_cmdline_by_pid(cur_pid); + MSG("\nPID: %d - Name: %s", cur_pid, cmdline); + free(cmdline); + } + if (strcmp(cur_event.name, event_field_list[i].event.name) != 0) { + print_events(&event_field_list[i].event); + memcpy(&cur_event, &event_field_list[i].event, + sizeof(cur_event)); + } + print_event_field(&event_field_list[i]); + } + + MSG(""); + + free(event_field_list); + lttng_destroy_handle(handle); + + return CMD_SUCCESS; + +error: + lttng_destroy_handle(handle); return -1; } @@ -310,7 +451,8 @@ static int list_kernel_events(void) size = lttng_list_tracepoints(handle, &event_list); if (size < 0) { - ERR("Unable to list kernel events"); + ERR("Unable to list kernel events: %s", lttng_strerror(size)); + lttng_destroy_handle(handle); return size; } @@ -324,9 +466,11 @@ static int list_kernel_events(void) free(event_list); + lttng_destroy_handle(handle); return CMD_SUCCESS; error: + lttng_destroy_handle(handle); return -1; } @@ -341,6 +485,7 @@ static int list_events(const char *channel_name) count = lttng_list_events(handle, channel_name, &events); if (count < 0) { ret = count; + ERR("%s", lttng_strerror(ret)); goto error; } @@ -357,9 +502,7 @@ static int list_events(const char *channel_name) MSG(""); end: - if (events) { - free(events); - } + free(events); ret = CMD_SUCCESS; error: @@ -404,11 +547,18 @@ static int list_channels(const char *channel_name) count = lttng_list_channels(handle, &channels); if (count < 0) { - ret = count; + switch (-count) { + case LTTNG_ERR_KERN_CHAN_NOT_FOUND: + ret = CMD_SUCCESS; + WARN("No kernel channel"); + break; + default: + /* We had a real error */ + ret = count; + ERR("%s", lttng_strerror(ret)); + break; + } goto error_channels; - } else if (count == 0) { - ERR("Channel %s not found", channel_name); - goto error; } if (channel_name == NULL) { @@ -428,7 +578,7 @@ static int list_channels(const char *channel_name) /* Listing events per channel */ ret = list_events(channels[i].name); if (ret < 0) { - MSG("%s", lttng_strerror(ret)); + ERR("%s", lttng_strerror(ret)); } if (chan_found) { @@ -465,7 +615,11 @@ static int list_sessions(const char *session_name) DBG("Session count %d", count); if (count < 0) { ret = count; + ERR("%s", lttng_strerror(ret)); goto error; + } else if (count == 0) { + MSG("Currently no available tracing session"); + goto end; } if (session_name == NULL) { @@ -476,18 +630,16 @@ static int list_sessions(const char *session_name) if (session_name != NULL) { if (strncmp(sessions[i].name, session_name, NAME_MAX) == 0) { session_found = 1; - MSG("Tracing session %s:%s", session_name, active_string(sessions[i].enabled)); + MSG("Tracing session %s: [%s%s]", session_name, + active_string(sessions[i].enabled), + snapshot_string(sessions[i].snapshot_mode)); MSG("%sTrace path: %s\n", indent4, sessions[i].path); break; } - continue; - } - - MSG(" %d) %s (%s)%s", i + 1, sessions[i].name, sessions[i].path, - active_string(sessions[i].enabled)); - - if (session_found) { - break; + } else { + MSG(" %d) %s (%s) [%s%s]", i + 1, sessions[i].name, sessions[i].path, + active_string(sessions[i].enabled), + snapshot_string(sessions[i].snapshot_mode)); } } @@ -503,6 +655,7 @@ static int list_sessions(const char *session_name) MSG("\nUse lttng list for more details"); } +end: return CMD_SUCCESS; error: @@ -522,6 +675,7 @@ static int list_domains(const char *session_name) count = lttng_list_domains(session_name, &domains); if (count < 0) { ret = count; + ERR("%s", lttng_strerror(ret)); goto error; } else if (count == 0) { MSG(" None"); @@ -553,8 +707,7 @@ error: */ int cmd_list(int argc, const char **argv) { - int opt, i, ret = CMD_SUCCESS; - int nb_domain; + int opt, ret = CMD_SUCCESS; const char *session_name; static poptContext pc; struct lttng_domain domain; @@ -598,16 +751,14 @@ int cmd_list(int argc, const char **argv) } else if (opt_userspace) { DBG2("Listing userspace global domain"); domain.type = LTTNG_DOMAIN_UST; - } else { - usage(stderr); - ret = CMD_UNDEFINED; - goto end; } - handle = lttng_create_handle(session_name, &domain); - if (handle == NULL) { - ret = CMD_FATAL; - goto end; + if (opt_kernel || opt_userspace) { + handle = lttng_create_handle(session_name, &domain); + if (handle == NULL) { + ret = CMD_FATAL; + goto end; + } } if (session_name == NULL) { @@ -620,12 +771,18 @@ int cmd_list(int argc, const char **argv) if (opt_kernel) { ret = list_kernel_events(); if (ret < 0) { + ret = CMD_ERROR; goto end; } } if (opt_userspace) { - ret = list_ust_events(); + if (opt_fields) { + ret = list_ust_event_fields(); + } else { + ret = list_ust_events(); + } if (ret < 0) { + ret = CMD_ERROR; goto end; } } @@ -649,10 +806,13 @@ int cmd_list(int argc, const char **argv) goto end; } } else { + int i, nb_domain; + /* We want all domain(s) */ nb_domain = lttng_list_domains(session_name, &domains); if (nb_domain < 0) { ret = nb_domain; + ERR("%s", lttng_strerror(ret)); goto end; } @@ -663,6 +823,9 @@ int cmd_list(int argc, const char **argv) break; case LTTNG_DOMAIN_UST: MSG("=== Domain: UST global ===\n"); + MSG("Buffer type: %s\n", + domains[i].buf_type == + LTTNG_BUFFER_PER_PID ? "per PID" : "per UID"); break; default: MSG("=== Domain: Unimplemented ===\n"); @@ -670,7 +833,9 @@ int cmd_list(int argc, const char **argv) } /* Clean handle before creating a new one */ - lttng_destroy_handle(handle); + if (handle) { + lttng_destroy_handle(handle); + } handle = lttng_create_handle(session_name, &domains[i]); if (handle == NULL) { @@ -687,10 +852,10 @@ int cmd_list(int argc, const char **argv) } end: - if (domains) { - free(domains); + free(domains); + if (handle) { + lttng_destroy_handle(handle); } - lttng_destroy_handle(handle); poptFreeContext(pc); return ret;