From 3c6a091f88fa6b237729cab17d6f6d227da82f59 Mon Sep 17 00:00:00 2001 From: David Goulet Date: Thu, 3 Oct 2013 15:20:07 -0400 Subject: [PATCH] Add lttng list -j command to list possible events For the JUL domain, add the -j/--jul support for lttng list. Signed-off-by: David Goulet --- src/bin/lttng-sessiond/cmd.c | 72 ++++++++++++++++++++ src/bin/lttng-sessiond/jul.c | 91 ++++++++++++++++++++++++- src/bin/lttng-sessiond/jul.h | 8 +++ src/bin/lttng/commands/list.c | 123 +++++++++++++++++++++++++++++++++- 4 files changed, 290 insertions(+), 4 deletions(-) diff --git a/src/bin/lttng-sessiond/cmd.c b/src/bin/lttng-sessiond/cmd.c index 8051973de..8dd3fcc60 100644 --- a/src/bin/lttng-sessiond/cmd.c +++ b/src/bin/lttng-sessiond/cmd.c @@ -182,6 +182,55 @@ static void list_lttng_channels(int domain, struct ltt_session *session, } } +/* + * Create a list of JUL domain events. + * + * Return number of events in list on success or else a negative value. + */ +static int list_lttng_jul_events(struct jul_domain *dom, + struct lttng_event **events) +{ + int i = 0, ret = 0; + unsigned int nb_event = 0; + struct jul_event *event; + struct lttng_event *tmp_events; + struct lttng_ht_iter iter; + + assert(dom); + assert(events); + + DBG3("Listing JUL events"); + + nb_event = lttng_ht_get_count(dom->events); + if (nb_event == 0) { + ret = nb_event; + goto error; + } + + tmp_events = zmalloc(nb_event * sizeof(*tmp_events)); + if (!tmp_events) { + PERROR("zmalloc JUL events session"); + ret = -LTTNG_ERR_FATAL; + goto error; + } + + rcu_read_lock(); + cds_lfht_for_each_entry(dom->events->ht, &iter.iter, event, node.node) { + strncpy(tmp_events[i].name, event->name, sizeof(tmp_events[i].name)); + tmp_events[i].name[sizeof(tmp_events[i].name) - 1] = '\0'; + tmp_events[i].enabled = event->enabled; + i++; + } + rcu_read_unlock(); + + *events = tmp_events; + ret = nb_event; + +error: + assert(nb_event == i); + return ret; +} + /* * Create a list of ust global domain events. */ @@ -1664,6 +1713,13 @@ ssize_t cmd_list_tracepoints(int domain, struct lttng_event **events) goto error; } break; + case LTTNG_DOMAIN_JUL: + nb_events = jul_list_events(events); + if (nb_events < 0) { + ret = LTTNG_ERR_UST_LIST_FAIL; + goto error; + } + break; default: ret = LTTNG_ERR_UND; goto error; @@ -2212,6 +2268,10 @@ ssize_t cmd_list_domains(struct ltt_session *session, if (session->ust_session != NULL) { DBG3("Listing domains found UST global domain"); nb_dom++; + + if (session->ust_session->domain_jul.being_used) { + nb_dom++; + } } *domains = zmalloc(nb_dom * sizeof(struct lttng_domain)); @@ -2229,6 +2289,12 @@ ssize_t cmd_list_domains(struct ltt_session *session, (*domains)[index].type = LTTNG_DOMAIN_UST; (*domains)[index].buf_type = session->ust_session->buffer_type; index++; + + if (session->ust_session->domain_jul.being_used) { + (*domains)[index].type = LTTNG_DOMAIN_JUL; + (*domains)[index].buf_type = session->ust_session->buffer_type; + index++; + } } return nb_dom; @@ -2319,6 +2385,12 @@ ssize_t cmd_list_events(int domain, struct ltt_session *session, } break; } + case LTTNG_DOMAIN_JUL: + if (session->ust_session) { + nb_event = list_lttng_jul_events( + &session->ust_session->domain_jul, events); + } + break; default: ret = LTTNG_ERR_UND; goto error; diff --git a/src/bin/lttng-sessiond/jul.c b/src/bin/lttng-sessiond/jul.c index 87ab654a3..4f2250dff 100644 --- a/src/bin/lttng-sessiond/jul.c +++ b/src/bin/lttng-sessiond/jul.c @@ -133,6 +133,92 @@ error: return ret; } + +/* + * Internal call to list events on a given app. Populate events. + * + * Return number of element in the list or else a negative LTTNG_ERR* code. + */ +static ssize_t list_events(struct jul_app *app, struct lttng_event **events) +{ + int ret, i, len = 0, offset = 0; + uint32_t nb_event; + size_t data_size; + struct lttng_event *tmp_events = NULL; + struct lttcomm_jul_list_reply *reply = NULL; + struct lttcomm_jul_list_reply_hdr reply_hdr; + + assert(app); + assert(app->sock); + assert(events); + + DBG2("JUL listing events for app pid: %d and socket %d", app->pid, + app->sock->fd); + + ret = send_header(app->sock, 0, JUL_CMD_LIST, 0); + if (ret < 0) { + goto error_io; + } + + /* Get list header so we know how much we'll receive. */ + ret = recv_reply(app->sock, &reply_hdr, sizeof(reply_hdr)); + if (ret < 0) { + goto error_io; + } + + switch (be32toh(reply_hdr.ret_code)) { + case JUL_RET_CODE_SUCCESS: + data_size = be32toh(reply_hdr.data_size) + sizeof(*reply); + break; + default: + ERR("Java agent returned an unknown code: %" PRIu32, + be32toh(reply_hdr.ret_code)); + ret = LTTNG_ERR_FATAL; + goto error; + } + + reply = zmalloc(data_size); + if (!reply) { + ret = LTTNG_ERR_NOMEM; + goto error; + } + + /* Get the list with the appropriate data size. */ + ret = recv_reply(app->sock, reply, data_size); + if (ret < 0) { + goto error_io; + } + + nb_event = be32toh(reply->nb_event); + tmp_events = zmalloc(sizeof(*tmp_events) * nb_event); + if (!tmp_events) { + ret = LTTNG_ERR_NOMEM; + goto error; + } + + for (i = 0; i < nb_event; i++) { + offset += len; + strncpy(tmp_events[i].name, reply->payload + offset, + sizeof(tmp_events[i].name)); + tmp_events[i].pid = app->pid; + tmp_events[i].enabled = -1; + len = strlen(reply->payload + offset) + 1; + } + + *events = tmp_events; + + free(reply); + return nb_event; + +error_io: + ret = LTTNG_ERR_UST_LIST_FAIL; +error: + free(reply); + free(tmp_events); + return -ret; + +} + /* * Internal enable JUL event call on a JUL application. This function * communicates with the Java agent to enable a given event (Logger name). @@ -274,9 +360,9 @@ int jul_enable_event(struct jul_event *event) if (ret != LTTNG_OK) { goto error; } - event->enabled = 1; } + event->enabled = 1; ret = LTTNG_OK; error: @@ -307,9 +393,9 @@ int jul_disable_event(struct jul_event *event) if (ret != LTTNG_OK) { goto error; } - event->enabled = 0; } + event->enabled = 0; ret = LTTNG_OK; error: @@ -608,6 +694,7 @@ void jul_add_event(struct jul_event *event, struct jul_domain *dom) rcu_read_lock(); lttng_ht_add_unique_str(dom->events, &event->node); rcu_read_unlock(); + dom->being_used = 1; } /* diff --git a/src/bin/lttng-sessiond/jul.h b/src/bin/lttng-sessiond/jul.h index f7d3c48f8..1e32ea555 100644 --- a/src/bin/lttng-sessiond/jul.h +++ b/src/bin/lttng-sessiond/jul.h @@ -91,6 +91,13 @@ struct jul_event { * for it. */ struct jul_domain { + /* + * This indicates if that domain is being used meaning if at least one + * event has been at some point in time added to it. This is used so when + * listing domains for a session, we can tell or not if the JUL is actually + * enabled. + */ + unsigned int being_used:1; /* * Contains JUL event indexed by name. */ @@ -124,5 +131,6 @@ void jul_destroy_app(struct jul_app *app); int jul_enable_event(struct jul_event *event); int jul_disable_event(struct jul_event *event); void jul_update(struct jul_domain *domain, int sock); +int jul_list_events(struct lttng_event **events); #endif /* _JUL_H */ diff --git a/src/bin/lttng/commands/list.c b/src/bin/lttng/commands/list.c index 1c7085dd7..bca06e75d 100644 --- a/src/bin/lttng/commands/list.c +++ b/src/bin/lttng/commands/list.c @@ -27,6 +27,7 @@ static int opt_userspace; static int opt_kernel; +static int opt_jul; static char *opt_channel; static int opt_domain; static int opt_fields; @@ -52,6 +53,7 @@ static struct poptOption long_options[] = { /* longName, shortName, argInfo, argPtr, value, descrip, argDesc */ {"help", 'h', POPT_ARG_NONE, 0, OPT_HELP, 0, 0}, {"kernel", 'k', POPT_ARG_VAL, &opt_kernel, 1, 0, 0}, + {"jul", 'j', POPT_ARG_VAL, &opt_jul, 1, 0, 0}, #if 0 /* Not implemented yet */ {"userspace", 'u', POPT_ARG_STRING | POPT_ARGFLAG_OPTIONAL, &opt_cmd_name, OPT_USERSPACE, 0, 0}, @@ -82,6 +84,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, " -j, --jul Apply for Java application using JUL\n"); fprintf(ofp, " -f, --fields List event fields.\n"); #if 0 fprintf(ofp, " -p, --pid PID List user-space events by PID\n"); @@ -304,6 +307,60 @@ static void print_event_field(struct lttng_event_field *field) field_type(field), field->nowrite ? " [no write]" : ""); } +static int list_jul_events(void) +{ + int i, size; + struct lttng_domain domain; + struct lttng_handle *handle; + struct lttng_event *event_list; + pid_t cur_pid = 0; + char *cmdline = NULL; + + DBG("Getting JUL tracing events"); + + memset(&domain, 0, sizeof(domain)); + domain.type = LTTNG_DOMAIN_JUL; + + handle = lttng_create_handle(NULL, &domain); + if (handle == NULL) { + goto error; + } + + size = lttng_list_tracepoints(handle, &event_list); + if (size < 0) { + ERR("Unable to list JUL events: %s", lttng_strerror(size)); + lttng_destroy_handle(handle); + return size; + } + + MSG("JUL events (Logger name):\n-------------------------"); + + if (size == 0) { + MSG("None"); + } + + for (i = 0; i < size; i++) { + if (cur_pid != event_list[i].pid) { + cur_pid = event_list[i].pid; + cmdline = get_cmdline_by_pid(cur_pid); + MSG("\nPID: %d - Name: %s", cur_pid, cmdline); + free(cmdline); + } + MSG("%s- %s", indent6, event_list[i].name); + } + + 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 tracepoints available. */ @@ -474,6 +531,44 @@ error: return -1; } +/* + * List JUL events for a specific session using the handle. + * + * Return CMD_SUCCESS on success else a negative value. + */ +static int list_session_jul_events(void) +{ + int ret, count, i; + struct lttng_event *events = NULL; + + count = lttng_list_events(handle, "", &events); + if (count < 0) { + ret = count; + ERR("%s", lttng_strerror(ret)); + goto error; + } + + MSG("Events (Logger name):\n---------------------"); + if (count == 0) { + MSG("%sNone\n", indent6); + goto end; + } + + for (i = 0; i < count; i++) { + MSG("%s- %s%s", indent4, events[i].name, + enabled_string(events[i].enabled)); + } + + MSG(""); + +end: + free(events); + ret = CMD_SUCCESS; + +error: + return ret; +} + /* * List events of channel of session and domain. */ @@ -690,6 +785,9 @@ static int list_domains(const char *session_name) case LTTNG_DOMAIN_UST: MSG(" - UST global"); break; + case LTTNG_DOMAIN_JUL: + MSG(" - JUL (Java Util Logging)"); + break; default: break; } @@ -751,9 +849,12 @@ int cmd_list(int argc, const char **argv) } else if (opt_userspace) { DBG2("Listing userspace global domain"); domain.type = LTTNG_DOMAIN_UST; + } else if (opt_jul) { + DBG2("Listing JUL domain"); + domain.type = LTTNG_DOMAIN_JUL; } - if (opt_kernel || opt_userspace) { + if (opt_kernel || opt_userspace || opt_jul) { handle = lttng_create_handle(session_name, &domain); if (handle == NULL) { ret = CMD_FATAL; @@ -762,7 +863,7 @@ int cmd_list(int argc, const char **argv) } if (session_name == NULL) { - if (!opt_kernel && !opt_userspace) { + if (!opt_kernel && !opt_userspace && !opt_jul) { ret = list_sessions(NULL); if (ret != 0) { goto end; @@ -786,6 +887,13 @@ int cmd_list(int argc, const char **argv) goto end; } } + if (opt_jul) { + ret = list_jul_events(); + if (ret < 0) { + ret = CMD_ERROR; + goto end; + } + } } else { /* List session attributes */ ret = list_sessions(session_name); @@ -827,6 +935,9 @@ int cmd_list(int argc, const char **argv) domains[i].buf_type == LTTNG_BUFFER_PER_PID ? "per PID" : "per UID"); break; + case LTTNG_DOMAIN_JUL: + MSG("=== Domain: JUL (Java Util Logging) ===\n"); + break; default: MSG("=== Domain: Unimplemented ===\n"); break; @@ -843,6 +954,14 @@ int cmd_list(int argc, const char **argv) goto end; } + if (domains[i].type == LTTNG_DOMAIN_JUL) { + ret = list_session_jul_events(); + if (ret < 0) { + goto end; + } + continue; + } + ret = list_channels(opt_channel); if (ret < 0) { goto end; -- 2.34.1