From 1657e9bb835a28e66396deac871270fe373d5ff4 Mon Sep 17 00:00:00 2001 From: David Goulet Date: Mon, 2 May 2011 15:34:25 -0400 Subject: [PATCH] Add trace listing feature This patch adds the possibility to list the available traces for a specific session. The new lttng_trace data structure is a representation of a trace for use for 'human output'. Some fct are added to trace.c to get the trace count of a session and list those traces. Also, trace counter are added to a ltt_session. Some renaming is done to make things clearer. A name is added to a userspace trace also. Signed-off-by: David Goulet --- include/lttng/liblttngctl.h | 15 ++++++++ liblttngctl/liblttngctl.c | 22 +++++++++++ liblttsessiondcomm/liblttsessiondcomm.h | 1 + ltt-sessiond/main.c | 27 ++++++++++++- ltt-sessiond/session.c | 8 +++- ltt-sessiond/session.h | 6 ++- ltt-sessiond/trace.c | 50 ++++++++++++++++++++++++ ltt-sessiond/trace.h | 7 +++- lttng/lttng.c | 51 ++++++++++++++++++++++++- lttng/lttng.h | 1 + lttng/options.c | 3 ++ 11 files changed, 182 insertions(+), 9 deletions(-) diff --git a/include/lttng/liblttngctl.h b/include/lttng/liblttngctl.h index aeb822010..0ffa6f258 100644 --- a/include/lttng/liblttngctl.h +++ b/include/lttng/liblttngctl.h @@ -35,6 +35,12 @@ */ #define UUID_STR_LEN 37 +/* Trace type for lttng_trace. + */ +enum lttng_trace_type { + KERNEL, USERSPACE, +}; + /* Simple structure representing a session. */ struct lttng_session { @@ -42,6 +48,14 @@ struct lttng_session { char uuid[UUID_STR_LEN]; }; +/* Simple trace representation. + */ +struct lttng_trace { + char name[NAME_MAX]; + pid_t pid; + enum lttng_trace_type type; +}; + extern int lttng_create_session(char *name, uuid_t *session_id); extern int lttng_destroy_session(uuid_t *uuid); extern int lttng_connect_sessiond(void); @@ -51,6 +65,7 @@ extern int lttng_check_session_daemon(void); extern const char *lttng_get_readable_code(int code); extern int lttng_ust_list_apps(pid_t **pids); extern int lttng_list_sessions(struct lttng_session **sessions); +extern int lttng_list_traces(uuid_t *uuid, struct lttng_trace **traces); extern void lttng_set_current_session_uuid(char *uuid); extern int lttng_ust_create_trace(pid_t pid); extern int lttng_ust_start_trace(pid_t pid); diff --git a/liblttngctl/liblttngctl.c b/liblttngctl/liblttngctl.c index 64764682b..7d020daad 100644 --- a/liblttngctl/liblttngctl.c +++ b/liblttngctl/liblttngctl.c @@ -218,6 +218,28 @@ int lttng_ust_list_apps(pid_t **pids) return ret / sizeof(pid_t); } +/* + * lttng_list_traces + * + * Ask the session daemon for all traces (kernel and ust) + * for the session identified by uuid. + * + * Return the number of traces. + */ +int lttng_list_traces(uuid_t *uuid, struct lttng_trace **traces) +{ + int ret; + + uuid_copy(lsm.session_id, *uuid); + + ret = ask_sessiond(LTTNG_LIST_TRACES, (void **) traces); + if (ret < 0) { + return ret; + } + + return ret / sizeof(struct lttng_trace); +} + /* * lttng_create_session * diff --git a/liblttsessiondcomm/liblttsessiondcomm.h b/liblttsessiondcomm/liblttsessiondcomm.h index ce85e8292..bd17a2ac6 100644 --- a/liblttsessiondcomm/liblttsessiondcomm.h +++ b/liblttsessiondcomm/liblttsessiondcomm.h @@ -45,6 +45,7 @@ enum lttcomm_command_type { LTTNG_GET_SUBBUF_NUM_SIZE, LTTNG_LIST_MARKERS, LTTNG_LIST_SESSIONS, + LTTNG_LIST_TRACES, LTTNG_LIST_TRACE_EVENTS, LTTNG_SETUP_TRACE, LTTNG_SET_SOCK_PATH, diff --git a/ltt-sessiond/main.c b/ltt-sessiond/main.c index 76834558a..70ce53c8b 100644 --- a/ltt-sessiond/main.c +++ b/ltt-sessiond/main.c @@ -309,6 +309,11 @@ static int ust_create_trace(pid_t pid) /* Init */ trace->pid = pid; trace->shmid = 0; + /* NOTE: to be removed. Trace name will no longer be + * required for LTTng userspace tracer. For now, we set it + * to 'auto' for API compliance. + */ + snprintf(trace->name, 5, "auto"); /* Connect to app using ustctl API */ sock = connect_app(pid); @@ -317,7 +322,7 @@ static int ust_create_trace(pid_t pid) goto error; } - ret = ustctl_create_trace(sock, "auto"); + ret = ustctl_create_trace(sock, trace->name); if (ret < 0) { ret = LTTCOMM_CREATE_FAIL; goto error; @@ -326,6 +331,7 @@ static int ust_create_trace(pid_t pid) /* Check if current session is valid */ if (current_session) { cds_list_add(&trace->list, ¤t_session->ust_traces); + current_session->ust_trace_count++; } error: @@ -497,6 +503,25 @@ static int process_client_msg(int sock, struct lttcomm_session_msg *lsm) /* No auxiliary data so only send the llm struct. */ goto end; } + case LTTNG_LIST_TRACES: + { + unsigned int trace_count = get_trace_count_per_session(current_session); + + if (trace_count == 0) { + ret = LTTCOMM_NO_TRACE; + goto end; + } + + buf_size = setup_data_buffer(&send_buf, + sizeof(struct lttng_trace) * trace_count, &llm); + if (buf_size < 0) { + ret = LTTCOMM_FATAL; + goto end; + } + + get_traces_per_session(current_session, (struct lttng_trace *)(send_buf + header_size)); + break; + } case UST_CREATE_TRACE: { ret = ust_create_trace(lsm->pid); diff --git a/ltt-sessiond/session.c b/ltt-sessiond/session.c index da1ceee4a..bf5f618a8 100644 --- a/ltt-sessiond/session.c +++ b/ltt-sessiond/session.c @@ -198,11 +198,15 @@ int create_session(char *name, uuid_t *session_id) * NO consumer attach to that session yet. */ new_session->ust_consumer = 0; - new_session->lttng_consumer = 0; + new_session->kernel_consumer = 0; /* Init list */ CDS_INIT_LIST_HEAD(&new_session->ust_traces); - CDS_INIT_LIST_HEAD(&new_session->lttng_traces); + CDS_INIT_LIST_HEAD(&new_session->kernel_traces); + + /* Set trace list counter */ + new_session->ust_trace_count = 0; + new_session->kern_trace_count = 0; /* Add new session to the global session list */ add_session_list(new_session); diff --git a/ltt-sessiond/session.h b/ltt-sessiond/session.h index 6bc7c4799..00e8ef1e7 100644 --- a/ltt-sessiond/session.h +++ b/ltt-sessiond/session.h @@ -35,9 +35,11 @@ struct ltt_session { struct cds_list_head list; uuid_t uuid; struct cds_list_head ust_traces; - struct cds_list_head lttng_traces; + struct cds_list_head kernel_traces; + unsigned int ust_trace_count; + unsigned int kern_trace_count; pid_t ust_consumer; - pid_t lttng_consumer; + pid_t kernel_consumer; }; /* Prototypes */ diff --git a/ltt-sessiond/trace.c b/ltt-sessiond/trace.c index 7d9c40cc0..c5d700fd1 100644 --- a/ltt-sessiond/trace.c +++ b/ltt-sessiond/trace.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include "lttngerr.h" @@ -47,3 +48,52 @@ struct ltt_ust_trace *find_session_ust_trace_by_pid(struct ltt_session *session, return NULL; } +/* + * get_trace_count_per_session + * + * Return the total count of traces (ust and kernel) + * for the specified session. + */ +int get_trace_count_per_session(struct ltt_session *session) +{ + return session->ust_trace_count + session->kern_trace_count; +} + +/* + * get_traces_per_session + * + * Fill the lttng_trace array of all the + * available trace of the session. + */ +void get_traces_per_session(struct ltt_session *session, struct lttng_trace *traces) +{ + int i = 0; + struct ltt_ust_trace *ust_iter; + struct ltt_kernel_trace *kern_iter; + struct lttng_trace trace; + + DBG("Getting userspace traces for session %s", session->name); + + /* Getting userspace traces */ + cds_list_for_each_entry(ust_iter, &session->ust_traces, list) { + trace.type = USERSPACE; + trace.pid = ust_iter->pid; + strncpy(trace.name, ust_iter->name, sizeof(trace.name)); + trace.name[sizeof(trace.name) - 1] = '\0'; + memcpy(&traces[i], &trace, sizeof(trace)); + memset(&trace, 0, sizeof(trace)); + i++; + } + + DBG("Getting kernel traces for session %s", session->name); + + /* Getting kernel traces */ + cds_list_for_each_entry(kern_iter, &session->kernel_traces, list) { + trace.type = KERNEL; + strncpy(trace.name, kern_iter->name, sizeof(trace.name)); + trace.name[sizeof(trace.name) - 1] = '\0'; + memcpy(&traces[i], &trace, sizeof(trace)); + memset(&trace, 0, sizeof(trace)); + i++; + } +} diff --git a/ltt-sessiond/trace.h b/ltt-sessiond/trace.h index 36b2f2270..755f8dfdf 100644 --- a/ltt-sessiond/trace.h +++ b/ltt-sessiond/trace.h @@ -22,15 +22,16 @@ #include "session.h" /* LTTng trace representation */ -struct ltt_lttng_trace { +struct ltt_kernel_trace { struct cds_list_head list; - char trace_name[NAME_MAX]; + char name[NAME_MAX]; struct cds_list_head marker_list; }; /* UST trace representation */ struct ltt_ust_trace { struct cds_list_head list; + char name[NAME_MAX]; int shmid; pid_t pid; struct cds_list_head markers; @@ -43,5 +44,7 @@ struct ltt_ust_marker { }; struct ltt_ust_trace *find_session_ust_trace_by_pid(struct ltt_session *session, pid_t pid); +int get_trace_count_per_session(struct ltt_session *session); +void get_traces_per_session(struct ltt_session *session, struct lttng_trace *traces); #endif /* _LTT_TRACE_H */ diff --git a/lttng/lttng.c b/lttng/lttng.c index e538df2fd..16487ff74 100644 --- a/lttng/lttng.c +++ b/lttng/lttng.c @@ -42,6 +42,7 @@ static char *progname; static int process_client_opt(void); static int process_opt_list_apps(void); static int process_opt_list_sessions(void); +static int process_opt_list_traces(void); static int process_opt_create_session(void); static void sighandler(int sig); static int set_signal_handler(void); @@ -80,6 +81,13 @@ static int process_client_opt(void) } } + if (opt_list_traces) { + ret = process_opt_list_traces(); + if (ret < 0) { + goto end; + } + } + if (opt_create_session != NULL) { ret = process_opt_create_session(); if (ret < 0) { @@ -125,6 +133,45 @@ end: return ret; } +/* + * process_opt_list_traces + * + * Get list of all traces for a specific session uuid. + */ +static int process_opt_list_traces(void) +{ + int ret, i; + uuid_t uuid; + struct lttng_trace *traces; + + uuid_parse(opt_session_uuid, uuid); + ret = lttng_list_traces(&uuid, &traces); + if (ret < 0) { + goto error; + } + + MSG("Userspace traces:"); + for (i = 0; i < ret; i++) { + if (traces[i].type == USERSPACE) { + MSG("\t%d) %s (pid: %d)", i, traces[i].name, traces[i].pid); + } else { + break; + } + } + + MSG("Kernel traces:"); + for (;i < ret; i++) { + if (traces[i].type == KERNEL) { + MSG("\t%d) %s", i, traces[i].name); + } + } + + free(traces); + +error: + return ret; +} + /* * process_opt_create_session * @@ -265,8 +312,8 @@ not_running: static int validate_options(void) { if ((opt_session_uuid == NULL) && - (opt_create_trace || opt_start_trace)) { - ERR("Can't act on trace without a session ID.\nPlease specify using --session UUID"); + (opt_create_trace || opt_start_trace || opt_list_traces)) { + ERR("You need to specify a session UUID.\nPlease use --session UUID to do so."); goto error; } diff --git a/lttng/lttng.h b/lttng/lttng.h index 4f16c8d1f..cb4196818 100644 --- a/lttng/lttng.h +++ b/lttng/lttng.h @@ -34,6 +34,7 @@ extern char *opt_destroy_session; extern int opt_list_apps; extern int opt_no_sessiond; extern int opt_list_session; +extern int opt_list_traces; extern pid_t opt_create_trace; extern pid_t opt_start_trace; diff --git a/lttng/options.c b/lttng/options.c index 183c54dcf..1ed0aca7d 100644 --- a/lttng/options.c +++ b/lttng/options.c @@ -33,6 +33,7 @@ int opt_verbose = 0; int opt_list_apps = 0; int opt_no_sessiond = 0; int opt_list_session = 0; +int opt_list_traces = 0; pid_t opt_create_trace = 0; pid_t opt_start_trace = 0; @@ -50,6 +51,7 @@ static struct poptOption long_options[] = { {"kernel", 0, POPT_ARG_VAL, &opt_trace_kernel, 1, 0, 0}, {"list-apps", 'L', POPT_ARG_VAL, &opt_list_apps, 1, 0, 0}, {"list-sessions", 'l', POPT_ARG_VAL, &opt_list_session, 1, 0, 0}, + {"list-traces", 't', POPT_ARG_VAL, &opt_list_traces, 1, 0, 0}, {"no-kernel", 0, POPT_ARG_VAL, &opt_trace_kernel, 0, 0, 0}, {"no-sessiond", 0, POPT_ARG_VAL, &opt_no_sessiond, 1, 0, 0}, {"quiet", 'q', POPT_ARG_VAL, &opt_quiet, 1, 0, 0}, @@ -88,6 +90,7 @@ static void usage(FILE *ofp) //fprintf(ofp, " --kernel Enable kernel tracing\n"); //fprintf(ofp, " --no-kernel Disable kernel tracing\n"); fprintf(ofp, " -L, --list-apps List traceable UST applications\n"); + fprintf(ofp, " -t, --list-traces List session's traces. Use -s to specify the session\n"); fprintf(ofp, " -C, --create-trace PID Create trace for PID\n"); fprintf(ofp, " --start PID Start trace for PID\n"); fprintf(ofp, "\n"); -- 2.34.1