From f37d259d342af1ff8855d9eaa578cb7a3cfcc4f2 Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Wed, 30 May 2012 16:27:39 -0400 Subject: [PATCH] Implement event fields listing Signed-off-by: Mathieu Desnoyers --- include/lttng/lttng.h | 25 ++++++ src/bin/lttng-sessiond/lttng-ust-ctl.h | 13 +++ src/bin/lttng-sessiond/main.c | 63 ++++++++++++++ src/bin/lttng-sessiond/ust-app.c | 76 +++++++++++++++++ src/bin/lttng-sessiond/ust-app.h | 1 + src/bin/lttng/commands/list.c | 100 ++++++++++++++++++++++- src/common/error.h | 2 + src/common/sessiond-comm/sessiond-comm.h | 1 + src/lib/lttng-ctl/lttng-ctl.c | 27 ++++++ 9 files changed, 307 insertions(+), 1 deletion(-) diff --git a/include/lttng/lttng.h b/include/lttng/lttng.h index f621fa80d..3b1be6197 100644 --- a/include/lttng/lttng.h +++ b/include/lttng/lttng.h @@ -228,6 +228,22 @@ struct lttng_event { } attr; }; +enum lttng_event_field_type { + LTTNG_EVENT_FIELD_OTHER = 0, + LTTNG_EVENT_FIELD_INTEGER = 1, + LTTNG_EVENT_FIELD_ENUM = 2, + LTTNG_EVENT_FIELD_FLOAT = 3, + LTTNG_EVENT_FIELD_STRING = 4, +}; + +#define LTTNG_EVENT_FIELD_PADDING LTTNG_SYMBOL_NAME_LEN + 32 +struct lttng_event_field { + char field_name[LTTNG_SYMBOL_NAME_LEN]; + enum lttng_event_field_type type; + char padding[LTTNG_EVENT_FIELD_PADDING]; + struct lttng_event event; +}; + /* * Tracer channel attributes. For both kernel and user-space. * @@ -387,6 +403,15 @@ extern int lttng_list_events(struct lttng_handle *handle, extern int lttng_list_tracepoints(struct lttng_handle *handle, struct lttng_event **events); +/* + * List the available tracepoints fields of a specific lttng domain. + * + * Return the size (number of entries) of the "lttng_event_field" array. + * Caller must free(3). + */ +extern int lttng_list_tracepoint_fields(struct lttng_handle *handle, + struct lttng_event_field **fields); + /* * Check if a session daemon is alive. * diff --git a/src/bin/lttng-sessiond/lttng-ust-ctl.h b/src/bin/lttng-sessiond/lttng-ust-ctl.h index a4f9c3fb4..c3479c97b 100644 --- a/src/bin/lttng-sessiond/lttng-ust-ctl.h +++ b/src/bin/lttng-sessiond/lttng-ust-ctl.h @@ -55,6 +55,19 @@ int ustctl_tracepoint_list(int sock); int ustctl_tracepoint_list_get(int sock, int tp_list_handle, struct lttng_ust_tracepoint_iter *iter); +/* + * ustctl_tracepoint_field_list returns a tracepoint field list handle, + * or negative error value. + */ +int ustctl_tracepoint_field_list(int sock); + +/* + * ustctl_tracepoint_field_list_get is used to iterate on the tp field + * list handle. End is iteration is reached when -ENOENT is returned. + */ +int ustctl_tracepoint_field_list_get(int sock, int tp_field_list_handle, + struct lttng_ust_field_iter *iter); + int ustctl_tracer_version(int sock, struct lttng_ust_tracer_version *v); int ustctl_wait_quiescent(int sock); diff --git a/src/bin/lttng-sessiond/main.c b/src/bin/lttng-sessiond/main.c index 3b1611c0a..e8bd45f15 100644 --- a/src/bin/lttng-sessiond/main.c +++ b/src/bin/lttng-sessiond/main.c @@ -2890,6 +2890,36 @@ error: return -ret; } +/* + * Command LTTNG_LIST_TRACEPOINT_FIELDS processed by the client thread. + */ +static ssize_t cmd_list_tracepoint_fields(int domain, + struct lttng_event_field **fields) +{ + int ret; + ssize_t nb_fields = 0; + + switch (domain) { + case LTTNG_DOMAIN_UST: + nb_fields = ust_app_list_event_fields(fields); + if (nb_fields < 0) { + ret = LTTCOMM_UST_LIST_FAIL; + goto error; + } + break; + case LTTNG_DOMAIN_KERNEL: + default: /* fall-through */ + ret = LTTCOMM_UND; + goto error; + } + + return nb_fields; + +error: + /* Return negative value to differentiate return code */ + return -ret; +} + /* * Command LTTNG_START_TRACE processed by the client thread. */ @@ -3338,6 +3368,7 @@ static int process_client_msg(struct command_ctx *cmd_ctx) switch(cmd_ctx->lsm->cmd_type) { case LTTNG_LIST_SESSIONS: case LTTNG_LIST_TRACEPOINTS: + case LTTNG_LIST_TRACEPOINT_FIELDS: case LTTNG_LIST_DOMAINS: case LTTNG_LIST_CHANNELS: case LTTNG_LIST_EVENTS: @@ -3357,6 +3388,7 @@ static int process_client_msg(struct command_ctx *cmd_ctx) case LTTNG_CALIBRATE: case LTTNG_LIST_SESSIONS: case LTTNG_LIST_TRACEPOINTS: + case LTTNG_LIST_TRACEPOINT_FIELDS: need_tracing_session = 0; break; default: @@ -3613,6 +3645,37 @@ skip_domain: ret = LTTCOMM_OK; break; } + case LTTNG_LIST_TRACEPOINT_FIELDS: + { + struct lttng_event_field *fields; + ssize_t nb_fields; + + nb_fields = cmd_list_tracepoint_fields(cmd_ctx->lsm->domain.type, &fields); + if (nb_fields < 0) { + ret = -nb_fields; + goto error; + } + + /* + * Setup lttng message with payload size set to the event list size in + * bytes and then copy list into the llm payload. + */ + ret = setup_lttng_msg(cmd_ctx, sizeof(struct lttng_event_field) * nb_fields); + if (ret < 0) { + free(fields); + goto setup_error; + } + + /* Copy event list into message payload */ + memcpy(cmd_ctx->llm->payload, fields, + sizeof(struct lttng_event_field) * nb_fields); + + free(fields); + + ret = LTTCOMM_OK; + break; + } + case LTTNG_START_TRACE: { ret = cmd_start_trace(cmd_ctx->session); diff --git a/src/bin/lttng-sessiond/ust-app.c b/src/bin/lttng-sessiond/ust-app.c index 43caabf93..63b106ae4 100644 --- a/src/bin/lttng-sessiond/ust-app.c +++ b/src/bin/lttng-sessiond/ust-app.c @@ -1497,6 +1497,82 @@ error: return ret; } +/* + * Fill events array with all events name of all registered apps. + */ +int ust_app_list_event_fields(struct lttng_event_field **fields) +{ + int ret, handle; + size_t nbmem, count = 0; + struct lttng_ht_iter iter; + struct ust_app *app; + struct lttng_event_field *tmp; + + nbmem = UST_APP_EVENT_LIST_SIZE; + tmp = zmalloc(nbmem * sizeof(struct lttng_event_field)); + if (tmp == NULL) { + PERROR("zmalloc ust app event fields"); + ret = -ENOMEM; + goto error; + } + + rcu_read_lock(); + + cds_lfht_for_each_entry(ust_app_ht->ht, &iter.iter, app, pid_n.node) { + struct lttng_ust_field_iter uiter; + + if (!app->compatible) { + /* + * TODO: In time, we should notice the caller of this error by + * telling him that this is a version error. + */ + continue; + } + handle = ustctl_tracepoint_field_list(app->sock); + if (handle < 0) { + ERR("UST app list event fields getting handle failed for app pid %d", + app->pid); + continue; + } + + while ((ret = ustctl_tracepoint_field_list_get(app->sock, handle, + &uiter)) != -ENOENT) { + if (count >= nbmem) { + DBG2("Reallocating event field list from %zu to %zu entries", nbmem, + 2 * nbmem); + nbmem *= 2; + tmp = realloc(tmp, nbmem * sizeof(struct lttng_event_field)); + if (tmp == NULL) { + PERROR("realloc ust app event fields"); + ret = -ENOMEM; + goto rcu_error; + } + } + + + memcpy(tmp[count].field_name, uiter.field_name, LTTNG_UST_SYM_NAME_LEN); + tmp[count].type = uiter.type; + + memcpy(tmp[count].event.name, uiter.event_name, LTTNG_UST_SYM_NAME_LEN); + tmp[count].event.loglevel = uiter.loglevel; + tmp[count].event.type = LTTNG_UST_TRACEPOINT; + tmp[count].event.pid = app->pid; + tmp[count].event.enabled = -1; + count++; + } + } + + ret = count; + *fields = tmp; + + DBG2("UST app list event fields done (%zu events)", count); + +rcu_error: + rcu_read_unlock(); +error: + return ret; +} + /* * Free and clean all traceable apps of the global list. */ diff --git a/src/bin/lttng-sessiond/ust-app.h b/src/bin/lttng-sessiond/ust-app.h index 8e9808220..88539879a 100644 --- a/src/bin/lttng-sessiond/ust-app.h +++ b/src/bin/lttng-sessiond/ust-app.h @@ -140,6 +140,7 @@ int ust_app_stop_trace_all(struct ltt_ust_session *usess); int ust_app_destroy_trace(struct ltt_ust_session *usess, struct ust_app *app); int ust_app_destroy_trace_all(struct ltt_ust_session *usess); int ust_app_list_events(struct lttng_event **events); +int ust_app_list_event_fields(struct lttng_event_field **fields); int ust_app_create_channel_glb(struct ltt_ust_session *usess, struct ltt_ust_channel *uchan); int ust_app_create_event_glb(struct ltt_ust_session *usess, diff --git a/src/bin/lttng/commands/list.c b/src/bin/lttng/commands/list.c index 50d6114c3..826cef269 100644 --- a/src/bin/lttng/commands/list.c +++ b/src/bin/lttng/commands/list.c @@ -29,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; @@ -60,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} }; @@ -80,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 @@ -237,6 +240,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)", indent6, field->field_name, + field_type(field)); +} + /* * Ask session daemon for all user space tracepoints available. */ @@ -292,6 +324,68 @@ error: 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; + 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"); + 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; + MSG("\nPID: %d - Name: %s", cur_pid, get_cmdline_by_pid(cur_pid)); + } + 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; +} + /* * Ask for all trace events in the kernel and pretty print them. */ @@ -634,7 +728,11 @@ int cmd_list(int argc, const char **argv) } } if (opt_userspace) { - ret = list_ust_events(); + if (opt_fields) { + ret = list_ust_event_fields(); + } else { + ret = list_ust_events(); + } if (ret < 0) { goto end; } diff --git a/src/common/error.h b/src/common/error.h index 5837d1cc3..4350408e6 100644 --- a/src/common/error.h +++ b/src/common/error.h @@ -64,6 +64,8 @@ extern int lttng_opt_verbose; #define MSG(fmt, args...) \ __lttng_print(PRINT_MSG, fmt "\n", ## args) +#define _MSG(fmt, args...) \ + __lttng_print(PRINT_MSG, fmt, ## args) #define ERR(fmt, args...) \ __lttng_print(PRINT_ERR, "Error: " fmt "\n", ## args) #define WARN(fmt, args...) \ diff --git a/src/common/sessiond-comm/sessiond-comm.h b/src/common/sessiond-comm/sessiond-comm.h index 4d31289a4..afdeee7da 100644 --- a/src/common/sessiond-comm/sessiond-comm.h +++ b/src/common/sessiond-comm/sessiond-comm.h @@ -62,6 +62,7 @@ enum lttcomm_sessiond_command { LTTNG_REGISTER_CONSUMER, LTTNG_START_TRACE, LTTNG_STOP_TRACE, + LTTNG_LIST_TRACEPOINT_FIELDS, }; /* diff --git a/src/lib/lttng-ctl/lttng-ctl.c b/src/lib/lttng-ctl/lttng-ctl.c index 36069ef28..96a54f881 100644 --- a/src/lib/lttng-ctl/lttng-ctl.c +++ b/src/lib/lttng-ctl/lttng-ctl.c @@ -680,6 +680,33 @@ int lttng_list_tracepoints(struct lttng_handle *handle, return ret / sizeof(struct lttng_event); } +/* + * Lists all available tracepoint fields of domain. + * Sets the contents of the event field array. + * Returns the number of lttng_event_field entries in events; + * on error, returns a negative value. + */ +int lttng_list_tracepoint_fields(struct lttng_handle *handle, + struct lttng_event_field **fields) +{ + int ret; + struct lttcomm_session_msg lsm; + + if (handle == NULL) { + return -1; + } + + lsm.cmd_type = LTTNG_LIST_TRACEPOINT_FIELDS; + copy_lttng_domain(&lsm.domain, &handle->domain); + + ret = ask_sessiond(&lsm, (void **) fields); + if (ret < 0) { + return ret; + } + + return ret / sizeof(struct lttng_event_field); +} + /* * Returns a human readable string describing * the error code (a negative value). -- 2.34.1