X-Git-Url: https://git.lttng.org/?p=lttngtop.git;a=blobdiff_plain;f=src%2Flttngtop.c;h=c29c5a5443efc9a7d5e3c8f49d2a6ba4f67cb67b;hp=957d03aaea902abb507a50323e02e72572e406d2;hb=09e7f98e84338afb3f6959a19df84ec4b4c1c012;hpb=bca0e79c3ab65b13f2e3d3711ddb17661052f24a diff --git a/src/lttngtop.c b/src/lttngtop.c index 957d03a..c29c5a5 100644 --- a/src/lttngtop.c +++ b/src/lttngtop.c @@ -63,8 +63,11 @@ const char *opt_input_path; int opt_textdump; int opt_child; int opt_begin; +int opt_all; int quit = 0; +/* We need at least one valid trace to start processing. */ +int valid_trace = 0; struct lttngtop *copy; pthread_t display_thread; @@ -97,6 +100,9 @@ enum { OPT_RELAY_HOSTNAME, OPT_KPROBES, OPT_BEGIN, + OPT_ALL, + OPT_OUTPUT_FILE, + OPT_VERBOSE, }; static struct poptOption long_options[] = { @@ -110,6 +116,9 @@ static struct poptOption long_options[] = { { "relay-hostname", 'r', POPT_ARG_STRING, &opt_relay_hostname, OPT_RELAY_HOSTNAME, NULL, NULL }, { "kprobes", 'k', POPT_ARG_STRING, &opt_kprobes, OPT_KPROBES, NULL, NULL }, + { "all", 'a', POPT_ARG_NONE, NULL, OPT_ALL, NULL, NULL }, + { "output", 'o', POPT_ARG_STRING, &opt_output, OPT_OUTPUT_FILE, NULL, NULL }, + { "verbose", 'v', POPT_ARG_NONE, NULL, OPT_VERBOSE, NULL, NULL }, { NULL, 0, 0, NULL, 0, NULL, NULL }, }; @@ -176,7 +185,8 @@ void *ncurses_display(void *p) } } -void print_fields(struct bt_ctf_event *event) +void print_fields(struct bt_ctf_event *event, const char *procname, + int pid) { unsigned int cnt, i; const struct bt_definition *const * list; @@ -184,27 +194,46 @@ void print_fields(struct bt_ctf_event *event) const struct bt_definition *scope; enum ctf_type_id type; const char *str; + struct processtop *current_proc; + struct files *current_file; + int fd, fd_value = -1; scope = bt_ctf_get_top_level_scope(event, BT_EVENT_FIELDS); bt_ctf_get_field_list(event, scope, &list, &cnt); for (i = 0; i < cnt; i++) { if (i != 0) - printf(", "); - printf("%s = ", bt_ctf_field_name(list[i])); + fprintf(output, ", "); + fprintf(output, "%s = ", bt_ctf_field_name(list[i])); l = bt_ctf_get_decl_from_def(list[i]); + if (strncmp(bt_ctf_field_name(list[i]), "fd", 2) == 0) + fd = 1; + else + fd = 0; type = bt_ctf_field_type(l); if (type == CTF_TYPE_INTEGER) { - if (bt_ctf_get_int_signedness(l) == 0) - printf("%" PRIu64 "", bt_ctf_get_uint64(list[i])); - else - printf("%" PRId64 "", bt_ctf_get_int64(list[i])); + if (bt_ctf_get_int_signedness(l) == 0) { + fd_value = bt_ctf_get_uint64(list[i]); + fprintf(output, "%" PRIu64, bt_ctf_get_uint64(list[i])); + } else { + fd_value = bt_ctf_get_int64(list[i]); + fprintf(output, "%" PRId64, bt_ctf_get_int64(list[i])); + } } else if (type == CTF_TYPE_STRING) { - printf("%s", bt_ctf_get_string(list[i])); + fprintf(output, "%s", bt_ctf_get_string(list[i])); } else if (type == CTF_TYPE_ARRAY) { str = bt_ctf_get_char_array(list[i]); if (!bt_ctf_field_get_error() && str) - printf("%s", str); + fprintf(output, "%s", str); + } + if (fd) { + current_proc = find_process_tid(<tngtop, pid, procname); + if (!current_proc) + continue; + current_file = get_file(current_proc, fd_value); + if (!current_file || !current_file->name) + continue; + fprintf(output, "<%s>", current_file->name); } } } @@ -263,18 +292,25 @@ enum bt_cb_ret textdump(struct bt_ctf_event *call_data, void *private_data) goto error; } if (!lookup_filter_tid_list(next_tid)) { - goto end; + if (!opt_all) + goto end; + } else { + if (opt_all) + fprintf(output, "%c[1m", 27); } - } else { + } else if (!opt_all) { goto end; } + } else { + if (opt_all) + fprintf(output, "%c[1m", 27); } } if (last_syscall && (strncmp(bt_ctf_event_name(call_data), "exit_syscall", 12)) != 0) { last_syscall = NULL; - printf(" ...interrupted...\n"); + fprintf(output, " ...interrupted...\n"); } cpu_id = get_cpu_id(call_data); @@ -301,14 +337,14 @@ enum bt_cb_ret textdump(struct bt_ctf_event *call_data, void *private_data) syscall_ret = bt_ctf_get_int64(bt_ctf_get_field(call_data, scope, "_ret")); - printf(" = %" PRId64 " (+%" PRIu64 ".%09" PRIu64 ")\n", + fprintf(output, "= %" PRId64 " (%" PRIu64 ".%09" PRIu64 "s)\n", syscall_ret, delta / NSEC_PER_SEC, delta % NSEC_PER_SEC); last_syscall = NULL; goto end; } else { last_syscall = NULL; - printf(" ...interrupted...\n"); + fprintf(output, " ...interrupted...\n"); } } @@ -337,18 +373,20 @@ enum bt_cb_ret textdump(struct bt_ctf_event *call_data, void *private_data) delta = timestamp - prev_ts; prev_ts = timestamp; - printf("%02d:%02d:%02d.%09" PRIu64 " (+%" PRIu64 ".%09" PRIu64 ") %s%s" + fprintf(output, "%02d:%02d:%02d.%09" PRIu64 " (+%" PRIu64 ".%09" PRIu64 ") %s%s" "(cpu %d) [%s (%d/%d)] %s (", start.tm_hour, start.tm_min, start.tm_sec, ts_nsec_start, delta / NSEC_PER_SEC, delta % NSEC_PER_SEC, (hostname) ? hostname : "", (hostname) ? " ": "", cpu_id, procname, pid, tid, bt_ctf_event_name(call_data)); - print_fields(call_data); - printf(")%s%c", (from_syscall) ? from_syscall : "", - (current_syscall) ? '\0' : '\n'); + print_fields(call_data, procname, pid); + fprintf(output, ")%s%c", (from_syscall) ? from_syscall : "", + (!current_syscall) ? '\n' : ' '); free(from_syscall); + if (opt_all && (opt_tid || opt_hostname || opt_exec_name)) + fprintf(output, "%c[0m", 27); end: return BT_CB_OK; @@ -537,7 +575,7 @@ enum bt_cb_ret fix_process_table(struct bt_ctf_event *call_data, } ppid = get_context_ppid(call_data); if (ppid == -1ULL) { - goto error; + goto end; } vpid = get_context_vpid(call_data); if (pid == -1ULL) { @@ -629,9 +667,11 @@ void usage(FILE *fp) fprintf(fp, " -p, --pid Comma-separated list of PIDs to display\n"); fprintf(fp, " -f, --child Follow threads associated with selected PIDs\n"); fprintf(fp, " -n, --hostname Comma-separated list of hostnames to display (require hostname context in trace)\n"); + fprintf(fp, " -a, --all In textdump mode, display all events but write in bold the processes we are interested in (-f, -p and -n)\n"); fprintf(fp, " -k, --kprobes Comma-separated list of kprobes to insert (same format as lttng enable-event)\n"); fprintf(fp, " -r, --relay-hostname Network live streaming : hostname of the lttng-relayd (default port)\n"); fprintf(fp, " -b, --begin Network live streaming : read the trace for the beginning of the recording\n"); + fprintf(fp, " -o, --output In textdump, output the log in \n"); } /* @@ -735,6 +775,9 @@ static int parse_options(int argc, char **argv) case OPT_TEXTDUMP: opt_textdump = 1; break; + case OPT_ALL: + opt_all = 1; + break; case OPT_CHILD: opt_child = 1; break; @@ -782,6 +825,11 @@ static int parse_options(int argc, char **argv) tmp_str = strtok(NULL, ","); } break; + case OPT_OUTPUT_FILE: + break; + case OPT_VERBOSE: + babeltrace_verbose = 1; + break; default: ret = -EINVAL; goto end; @@ -800,6 +848,15 @@ static int parse_options(int argc, char **argv) if (!opt_exec_name) { opt_input_path = poptGetArg(pc); } + if (!opt_output) { + opt_output = strdup("/dev/stdout"); + } + output = fopen(opt_output, "w"); + if (!output) { + perror("Error opening output file"); + ret = -1; + goto end; + } end: if (pc) { @@ -832,6 +889,26 @@ void iter_trace(struct bt_context *bt_ctx) bt_ctf_iter_add_callback(iter, g_quark_from_static_string("sched_process_free"), NULL, 0, handle_sched_process_free, NULL, NULL, NULL); + /* to get all the process from the statedumps */ + bt_ctf_iter_add_callback(iter, + g_quark_from_static_string( + "lttng_statedump_process_state"), + NULL, 0, handle_statedump_process_state, + NULL, NULL, NULL); + bt_ctf_iter_add_callback(iter, + g_quark_from_static_string( + "lttng_statedump_file_descriptor"), + NULL, 0, handle_statedump_file_descriptor, + NULL, NULL, NULL); + bt_ctf_iter_add_callback(iter, + g_quark_from_static_string("sys_open"), + NULL, 0, handle_sys_open, NULL, NULL, NULL); + bt_ctf_iter_add_callback(iter, + g_quark_from_static_string("sys_close"), + NULL, 0, handle_sys_close, NULL, NULL, NULL); + bt_ctf_iter_add_callback(iter, + g_quark_from_static_string("exit_syscall"), + NULL, 0, handle_exit_syscall, NULL, NULL, NULL); if (opt_textdump) { bt_ctf_iter_add_callback(iter, 0, NULL, 0, textdump, @@ -845,34 +922,13 @@ void iter_trace(struct bt_context *bt_ctx) bt_ctf_iter_add_callback(iter, g_quark_from_static_string("sched_switch"), NULL, 0, handle_sched_switch, NULL, NULL, NULL); - /* to get all the process from the statedumps */ - bt_ctf_iter_add_callback(iter, - g_quark_from_static_string( - "lttng_statedump_process_state"), - NULL, 0, handle_statedump_process_state, - NULL, NULL, NULL); - /* for IO top */ - bt_ctf_iter_add_callback(iter, - g_quark_from_static_string("exit_syscall"), - NULL, 0, handle_exit_syscall, NULL, NULL, NULL); bt_ctf_iter_add_callback(iter, g_quark_from_static_string("sys_write"), NULL, 0, handle_sys_write, NULL, NULL, NULL); bt_ctf_iter_add_callback(iter, g_quark_from_static_string("sys_read"), NULL, 0, handle_sys_read, NULL, NULL, NULL); - bt_ctf_iter_add_callback(iter, - g_quark_from_static_string("sys_open"), - NULL, 0, handle_sys_open, NULL, NULL, NULL); - bt_ctf_iter_add_callback(iter, - g_quark_from_static_string("sys_close"), - NULL, 0, handle_sys_close, NULL, NULL, NULL); - bt_ctf_iter_add_callback(iter, - g_quark_from_static_string( - "lttng_statedump_file_descriptor"), - NULL, 0, handle_statedump_file_descriptor, - NULL, NULL, NULL); /* for kprobes */ if (lttngtop.kprobes_table) { @@ -1128,6 +1184,9 @@ int check_requirements(struct bt_context *ctx) ret = -1; fprintf(stderr, "[error] missing procname context information\n"); } + if (ret == 0) { + valid_trace = 1; + } end: return ret; @@ -1145,7 +1204,6 @@ int main(int argc, char **argv, char **envp) int ret; struct bt_context *bt_ctx = NULL; - //babeltrace_verbose = 1; init_lttngtop(); ret = parse_options(argc, argv); if (ret < 0) { @@ -1204,10 +1262,10 @@ int main(int argc, char **argv, char **envp) } ret = check_requirements(bt_ctx); - if (ret < 0) { + if (ret < 0 && !valid_trace) { fprintf(stderr, "[error] some mandatory contexts " "were missing, exiting.\n"); - goto end; + //goto end; } if (!opt_textdump) {