[ltt-dev] [PATCH] Add formated dump module
Vincent Attard
vincent.attard at polymtl.ca
Thu Jan 13 16:44:59 EST 2011
This new plugin prints a formated output of each events in a trace. The
output format is defined as a parameter with printf like syntax.It provides
a default format easy to read and the original textDump format for backward
compatibility.
Signed-off-by: Vincent Attard <vincent.attard at polymtl.ca>
Reviewed-by: Yannick Brosseau <yannick.brosseau at polymtl.ca>
---
lttv/modules/text/Makefile.am | 3 +-
lttv/modules/text/formatedDump.c | 377 ++++++++++++++++++++++++++++++++++++++
2 files changed, 379 insertions(+), 1 deletions(-)
create mode 100644 lttv/modules/text/formatedDump.c
diff --git a/lttv/modules/text/Makefile.am b/lttv/modules/text/Makefile.am
index 29e8990..d95a4a0 100644
--- a/lttv/modules/text/Makefile.am
+++ b/lttv/modules/text/Makefile.am
@@ -3,7 +3,7 @@ AM_LDFLAGS = $(MODULE_LDFLAGS)
libdir = ${lttvplugindir}
-lib_LTLIBRARIES = libtextDump.la libbatchAnalysis.la libtextFilter.la libprecomputeState.la libdepanalysis.la libsync_chain_batch.la
+lib_LTLIBRARIES = libtextDump.la libbatchAnalysis.la libtextFilter.la libprecomputeState.la libdepanalysis.la libsync_chain_batch.la libformatedDump.la
libtextDump_la_SOURCES = textDump.c
libbatchAnalysis_la_SOURCES = batchAnalysis.c
@@ -11,6 +11,7 @@ libtextFilter_la_SOURCES = textFilter.c
libprecomputeState_la_SOURCES = precomputeState.c
libdepanalysis_la_SOURCES = depanalysis.c sstack.c
libsync_chain_batch_la_SOURCES = sync_chain_batch.c
+libformatedDump_la_SOURCES = formatedDump.c
noinst_HEADERS = \
batchanalysis.h \
diff --git a/lttv/modules/text/formatedDump.c b/lttv/modules/text/formatedDump.c
new file mode 100644
index 0000000..44f6589
--- /dev/null
+++ b/lttv/modules/text/formatedDump.c
@@ -0,0 +1,377 @@
+/* This file is part of the Linux Trace Toolkit viewer
+ * Copyright (C) 2003-2004 Michel Dagenais
+ * 2005 Mathieu Desnoyers
+ * 2011 Vincent Attard
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License Version 2 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.
+ */
+
+/* Formated dump plugin prints a formated output of each events in a trace. The
+ * output format is defined as a parameter. It provides a default format easy to
+ * read and the original textDump format for backward compatibility.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <lttv/lttv.h>
+#include <lttv/option.h>
+#include <lttv/module.h>
+#include <lttv/hook.h>
+#include <lttv/attribute.h>
+#include <lttv/iattribute.h>
+#include <lttv/stats.h>
+#include <lttv/filter.h>
+#include <lttv/print.h>
+#include <ltt/ltt.h>
+#include <ltt/event.h>
+#include <ltt/trace.h>
+#include <stdio.h>
+#include <inttypes.h>
+#include <string.h>
+#include <stdlib.h>
+
+static gboolean
+a_noevent,
+a_no_field_names,
+a_state,
+a_text;
+
+static char
+*a_file_name = NULL;
+static char
+*a_format = NULL;
+
+static LttvHooks
+*before_traceset,
+*event_hook;
+
+static char default_format[] =
+ "tracefile:%f envent:%e timestamp:%t elapse:%l cpu:%c pid:%d tgpid:%g "\
+ "process:%p brand:%b ppid:%i state:%a";
+
+static char textDump_format[] =
+ "%f.%e: %s.%n (%r/%f_%c), %d, %g, %p, %b, %i, %y, %a { %m }";
+
+static FILE *a_file;
+
+static GString *a_string;
+
+static gboolean open_output_file(void *hook_data, void *call_data)
+{
+ g_info("Open the output file");
+
+ if(a_file_name == NULL) a_file = stdout;
+ else a_file = fopen(a_file_name, "w");
+
+ if(a_file == NULL) g_error("cannot open file %s", a_file_name);
+ return FALSE;
+}
+
+static int write_event_content(void *hook_data, void *call_data)
+{
+ gboolean result;
+
+ LttvIAttribute *attributes = LTTV_IATTRIBUTE(lttv_global_attributes());
+
+ LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
+
+ LttvTracefileState *tfs = (LttvTracefileState *)call_data;
+
+ LttEvent *e;
+
+ LttvAttributeValue value_filter;
+
+ LttvFilter *filter;
+
+ guint cpu = tfs->cpu;
+ LttvTraceState *ts = (LttvTraceState*)tfc->t_context;
+ LttvProcessState *process = ts->running_process[cpu];
+
+ if (a_noevent)
+ return FALSE;
+
+ e = ltt_tracefile_get_event(tfc->tf);
+
+ result = lttv_iattribute_find_by_path(attributes, "filter/lttv_filter",
+ LTTV_POINTER, &value_filter);
+ g_assert(result);
+ filter = (LttvFilter*)*(value_filter.v_pointer);
+
+ /*
+ * call to the filter if available
+ */
+ if(filter->head != NULL)
+ if(!lttv_filter_tree_parse(filter->head,e,tfc->tf,
+ tfc->t_context->t,tfc,NULL,NULL))
+ return FALSE;
+
+ lttv_event_to_string(e, a_string, TRUE, !a_no_field_names, tfs);
+
+ if(a_state) {
+ g_string_append_printf(a_string, "%s ",
+ g_quark_to_string(process->state->s));
+ }
+
+
+ g_string_append_printf(a_string,"\n");
+
+ fputs(a_string->str, a_file);
+ return FALSE;
+}
+
+void lttv_event_to_string(LttEvent *e, GString *s, gboolean mandatory_fields,
+ gboolean field_names, LttvTracefileState *tfs)
+{
+ struct marker_field *field;
+ struct marker_info *info;
+ LttTime time;
+ static LttTime time_prev = {0,0};
+ LttTime elapse;
+
+
+ guint cpu = tfs->cpu;
+ LttvTraceState *ts = (LttvTraceState*)tfs->parent.t_context;
+ LttvProcessState *process = ts->running_process[cpu];
+
+ s = g_string_set_size(s,0);
+
+ info = marker_get_info_from_id(tfs->parent.tf->mdata, e->event_id);
+ if(mandatory_fields) {
+ time = ltt_event_time(e);
+ /* Calculate elapse between current and previous event time */
+ if (time_prev.tv_sec==0 && time_prev.tv_nsec == 0) {
+ time_prev = ltt_event_time(e);
+ elapse.tv_sec = 0;
+ elapse.tv_nsec = 0;
+ } else {
+ elapse = ltt_time_sub(time, time_prev);
+ time_prev = time;
+ }
+ }
+
+ char * fmt;
+ int i;
+ int fmt_len = 0;
+ if(a_text) {
+ /* textDump format (used with -T command option) */
+ fmt = textDump_format;
+ fmt_len = strlen(textDump_format);
+ }
+
+ else if (!a_format) {
+ /* Default format (used if no option) */
+ fmt = default_format;
+ fmt_len = strlen(default_format);
+ } else {
+ /* formatedDump format
+ * (used with -F command option following by the desired format) */
+ fmt = a_format;
+ fmt_len = strlen(a_format);
+ }
+
+ char str[1024] = {0};
+ /* Switch case:
+ * all '%-' are replaced by the desired value in 'str' */
+ char *str_pos = str;
+ for (i = 0; i < strlen(fmt); i++){
+ if (fmt[i] == '%'){
+
+ switch (fmt[++i]){
+ case 't':
+ str_pos += sprintf(str_pos, "%ldh%02ldm%02lds%09ldns",
+ time.tv_sec/3600, (time.tv_sec%3600)/60, time.tv_sec%60,
+ time.tv_nsec);
+ break;
+ case 'f':
+ strcpy(str_pos,
+ g_quark_to_string(ltt_tracefile_name(tfs->parent.tf)));
+ str_pos = str_pos + strlen(g_quark_to_string(ltt_tracefile_name(tfs->parent.tf)));
+ break;
+ case 'e':
+ strcpy(str_pos,
+ g_quark_to_string(info->name));
+ str_pos = str_pos + strlen(g_quark_to_string(info->name));
+ break;
+ case 'd':
+ str_pos += sprintf(str_pos, "%u", process->pid);
+ break;
+ case 's':
+ str_pos += sprintf(str_pos, "%lu", time.tv_sec);
+ break;
+ case 'n':
+ str_pos += sprintf(str_pos, "%lu", time.tv_nsec);
+ break;
+ case 'i':
+ str_pos += sprintf(str_pos, "%u", process->ppid);
+ break;
+ case 'g':
+ str_pos += sprintf(str_pos, "%u", process->tgid);
+ break;
+ case 'p':
+ strcpy(str_pos,g_quark_to_string(process->name));
+ str_pos = str_pos + strlen(g_quark_to_string(process->name));
+ break;
+ case 'b':
+ strcpy(str_pos,g_quark_to_string(process->brand));
+ str_pos = str_pos + strlen(g_quark_to_string(process->brand));
+ break;
+ case 'c':
+ str_pos += sprintf(str_pos,"%u", cpu);
+ break;
+ case 'l':
+ str_pos += sprintf(str_pos, "%lds%09ldns",
+ elapse.tv_sec, elapse.tv_nsec);
+ break;
+ case 'a':
+ strcpy(str_pos,g_quark_to_string(process->state->t));
+ str_pos = str_pos + strlen(g_quark_to_string(process->state->t));
+ break;
+ case 'm':
+ {
+ GString *marker = g_string_new(0);
+
+ /* Get and print markers and tracepoints fields into 'marker' */
+ if(marker_get_num_fields(info) == 0) return;
+ for (field = marker_get_field(info, 0);
+ field != marker_get_field(info, marker_get_num_fields(info));
+ field++) {
+ if(field != marker_get_field(info, 0)) {
+ g_string_append_printf(marker, ", ");
+ }
+ lttv_print_field(e, field, marker, field_names, tfs);
+
+ }
+ strcpy(str_pos,marker->str);
+ str_pos = str_pos + marker->len;
+ g_string_free(marker,0);
+ }
+ break;
+ case 'r':
+ strcpy(str_pos,g_quark_to_string(ltt_trace_name
+ (ltt_tracefile_get_trace(tfs->parent.tf))));
+ str_pos = str_pos + strlen(g_quark_to_string(ltt_trace_name
+ (ltt_tracefile_get_trace(tfs->parent.tf))));
+ break;
+ case '%':
+ *str_pos = '%';
+ str_pos = str_pos + 1;
+ break;
+ case 'y':
+ str_pos += sprintf(str_pos, "0x%" PRIx64,
+ process->current_function);
+ break;
+
+ }
+ }
+ else
+ {
+ /* Copy every character if not equals to '%' */
+ *str_pos = fmt[i];
+ str_pos++;
+ }
+ }
+ *str_pos = '\0';
+ g_string_append_printf(s, "%s", str);
+}
+
+static void init()
+{
+ gboolean result;
+
+ LttvAttributeValue value;
+
+ LttvIAttribute *attributes = LTTV_IATTRIBUTE(lttv_global_attributes());
+
+ g_info("Init formatedDump.c");
+
+ a_string = g_string_new("");
+
+ a_file_name = NULL;
+ lttv_option_add("output", 'o',
+ "output file where the text is written",
+ "file name",
+ LTTV_OPT_STRING, &a_file_name, NULL, NULL);
+
+ a_format= NULL;
+ lttv_option_add("format", 'F',
+ "output the desired format\n\
+ FORMAT controls the output. Interpreted sequences are:\n\
+ \n\
+ %f tracefile name\n\
+ %r path to trace\n\
+ %e event name\n\
+ %p process name\n\
+ %t timestamp (e.g., 2h08m54s025684145ns)\n\
+ %s seconds\n\
+ %n nanoseconds\n\
+ %l elapsed time with the previous event\n\
+ %d pid\n\
+ %i ppid\n\
+ %g tgid\n\
+ %c cpu\n\
+ %b brand\n\
+ %a state\n\
+ %m markers and tracepoints fields\n",
+ "format string",
+ LTTV_OPT_STRING, &a_format, NULL, NULL);
+
+ a_text = FALSE;
+ lttv_option_add("text", 'T',
+ "output the textDump format",
+ "",
+ LTTV_OPT_NONE, &a_text, NULL, NULL);
+
+ result = lttv_iattribute_find_by_path(attributes, "hooks/event",
+ LTTV_POINTER, &value);
+ g_assert(result);
+ event_hook = *(value.v_pointer);
+ g_assert(event_hook);
+ lttv_hooks_add(event_hook, write_event_content, NULL, LTTV_PRIO_DEFAULT);
+
+ result = lttv_iattribute_find_by_path(attributes, "hooks/traceset/before",
+ LTTV_POINTER, &value);
+ g_assert(result);
+ before_traceset = *(value.v_pointer);
+ g_assert(before_traceset);
+ lttv_hooks_add(before_traceset, open_output_file, NULL,
+ LTTV_PRIO_DEFAULT);
+
+}
+
+static void destroy()
+{
+ g_info("Destroy formatedDump");
+
+ lttv_option_remove("format");
+
+ lttv_option_remove("output");
+
+ lttv_option_remove("text");
+
+ g_string_free(a_string, TRUE);
+
+ lttv_hooks_remove_data(event_hook, write_event_content, NULL);
+
+ lttv_hooks_remove_data(before_traceset, open_output_file, NULL);
+
+}
+
+
+LTTV_MODULE("formatedDump", "Print events with desired format in a file", \
+ "Produce a detailed formated text printout of a trace", \
+ init, destroy, "batchAnalysis", "option")
+
--
1.7.0.4
More information about the lttng-dev
mailing list