[ltt-dev] [PATCH] Add formatted dump module (real) v4

Robert Ellis rellis14 at gmail.com
Thu Jan 20 11:11:56 EST 2011


Hey guys, not sure how I got on this discussion site but can someone please remove me from it, thanks!!!

Robbie

On Jan 19, 2011, at 3:31 PM, Mathieu Desnoyers <compudj at krystal.dyndns.org> wrote:

> * Vincent Attard (vincent.attard at polymtl.ca) wrote:
>> 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.
>> Updated: Use glib functions for solving buffer overflow problem and correct
>> indentation. Add another format called "strace-like".
>> 
>> 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/formattedDump.c |  380 +++++++++++++++++++++++++++++++++++++
>> 2 files changed, 382 insertions(+), 1 deletions(-)
>> create mode 100644 lttv/modules/text/formattedDump.c
>> 
>> diff --git a/lttv/modules/text/Makefile.am b/lttv/modules/text/Makefile.am
>> index 29e8990..4f11cb6 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 libformattedDump.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
>> +libformattedDump_la_SOURCES = formattedDump.c
>> 
>> noinst_HEADERS = \
>>    batchanalysis.h \
>> diff --git a/lttv/modules/text/formattedDump.c b/lttv/modules/text/formattedDump.c
>> new file mode 100644
>> index 0000000..fa3fe53
>> --- /dev/null
>> +++ b/lttv/modules/text/formattedDump.c
>> @@ -0,0 +1,380 @@
> 
> /*
> * 
> 
> comments.
> 
>> +/* This file is part of the Linux Trace Toolkit viewer
>> + * Copyright (C) 2003-2004 Michel Dagenais
>> + *               2005 Mathieu Desnoyers
>> + *               2011 Vincent Attard <vinc.attard at gmail.com>
>> + *
>> + * 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.
>> + */
>> +
>> +/*
>> + * Formatted dump plugin prints a formatted output of each events in a trace.
>> + * The output format is defined as a parameter. It provides a default format
>> + * easy to read, a "strace-like" format 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_no_field_names;
>> +static gboolean a_state;
>> +static gboolean a_text;
>> +static gboolean a_strace;
>> +
>> +static char *a_file_name = NULL;
>> +static char *a_format = NULL;
>> +
>> +static LttvHooks *before_traceset;
>> +static LttvHooks *event_hook;
>> +
>> +static const char default_format[] =
>> +        "channel:%c event:%e timestamp:%t elapsed:%l cpu:%u pid:%d ppid:%i "
>> +        "tgpid:%g process:%p brand:%b state:%a payload:{ %m }";
>> +static const char textDump_format[] =
>> +        "%c.%e: %s.%n (%r/%c_%u), %d, %g, %p, %b, %i, %y, %a { %m }";
>> +static const char strace_format[] = "%e(%m) %s.%n";
>> +
>> +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];
>> +
>> +    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;
> 
> indentation problem.
> 
>> +        }
>> +    }
>> +
>> +    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 *string_buffer, gboolean mandatory_fields,
>> +        gboolean field_names, LttvTracefileState *tfs)
>> +{
>> +    struct marker_field *field;
>> +    struct marker_info *info;
>> +    LttTime time;
>> +
>> +    static LttTime time_prev = {0, 0};
>> +    /*
>> +     * TODO:
>> +     * Added this static value into state.c and reset each time you do a
>> +     * seek for using it in the GUI.
>> +     */
>> +    LttTime elapse;
>> +    const char *fmt;
>> +    int i;
>> +
>> +    guint cpu = tfs->cpu;
>> +    LttvTraceState *ts = (LttvTraceState *)tfs->parent.t_context;
>> +    LttvProcessState *process = ts->running_process[cpu];
>> +
>> +    info = marker_get_info_from_id(tfs->parent.tf->mdata, e->event_id);
>> +    if (mandatory_fields) {
>> +        time = ltt_event_time(e);
>> +        /* Calculate elapsed time between current and previous event */
>> +        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;
>> +        /*
>> +         * TODO:
>> +         * Keep in mind that you should add the ability to restore the previous
>> +         * event time to state.c if you want to reuse this code into the GUI.
>> +         */
> 
> indent problem.
> 
>> +        } else {
>> +            elapse = ltt_time_sub(time, time_prev);
>> +            time_prev = time;
>> +        }
>> +    }
>> +    if (a_text) {
>> +        /* textDump format (used with -T command option) */
>> +        fmt = textDump_format;
>> +    } else if (a_strace) {
>> +        /* strace-like format (used with -S command option) */
>> +        fmt = strace_format;
>> +    } else if (!a_format) {
>> +        /* Default format (used if no option) */
>> +        fmt = default_format;
>> +    } else {
>> +        /*
>> +         * formattedDump format
>> +         * (used with -F command option following by the desired format)
>> +         */
>> +        fmt = a_format;
>> +    }
>> +
>> +    g_string_set_size(string_buffer, 0);
>> +    /*
>> +     * Switch case:
>> +     * all '%-' are replaced by the desired value in 'string_buffer'
>> +     */
>> +    int len;
> 
> local variables should be declared at the beginning of a block
> (beginning of function or beginning of { } block), never within the
> function code.
> 
>> +    len = strlen(fmt);
>> +    for (i = 0; i < len; i++) {
>> +        if (fmt[i] == '%') {
>> +            switch (fmt[++i]) {
>> +            case 't':
>> +                g_string_append_printf(string_buffer,
>> +                                    "%ld:%02ld:%02ld.%09ld",
> 
> please remove some tabs here.
> 
>> +                                    time.tv_sec/3600,
>> +                                    (time.tv_sec%3600)/60,
>> +                                    time.tv_sec%60,
>> +                                    time.tv_nsec);
>> +                break;
>> +            case 'c':
>> +                g_string_append(string_buffer,
>> +                        g_quark_to_string(ltt_tracefile_name(tfs->parent.tf)));
>> +                break;
>> +            case 'e':
>> +                g_string_append(string_buffer,
>> +                        g_quark_to_string(info->name));
>> +                break;
>> +            case 'd':
>> +                g_string_append_printf(string_buffer, "%u", process->pid);
>> +                break;
>> +            case 's':
>> +                g_string_append_printf(string_buffer, "%ld", time.tv_sec);
>> +                break;
>> +            case 'n':
>> +                g_string_append_printf(string_buffer, "%ld", time.tv_nsec);
>> +                break;
>> +            case 'i':
>> +                g_string_append_printf(string_buffer, "%u", process->ppid);
>> +                break;
>> +            case 'g':
>> +                g_string_append_printf(string_buffer, "%u", process->tgid);
>> +                break;
>> +            case 'p':
>> +                g_string_append(string_buffer,
>> +                        g_quark_to_string(process->name));
>> +                break;
>> +            case 'b':
>> +                g_string_append_printf(string_buffer, "%u", process->brand);
>> +                break;
>> +            case 'u':
>> +                g_string_append_printf(string_buffer, "%u", cpu);
>> +                break;
>> +            case 'l':
>> +                g_string_append_printf(string_buffer, "%ld.%09ld",
>> +                        elapse.tv_sec, elapse.tv_nsec);
>> +                break;
>> +            case 'a':
>> +                g_string_append(string_buffer,
>> +                        g_quark_to_string(process->state->t));
>> +                break;
>> +            case 'm':
>> +                {
>> +                    /*
>> +                     * Get and print markers and tracepoints fields into
>> +                     * 'string_buffer'
>> +                     */
>> +                    if (marker_get_num_fields(info) == 0)
>> +                        break;
>> +                    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(string_buffer, ", ");
>> +                        }
>> +
>> +                        lttv_print_field(e, field, string_buffer, field_names, tfs);
>> +                    }
>> +                }
>> +                break;
>> +            case 'r':
>> +                g_string_append(string_buffer, g_quark_to_string(
>> +                        ltt_trace_name(ltt_tracefile_get_trace(tfs->parent.tf))));
>> +                break;
>> +            case '%':
>> +                g_string_append_c(string_buffer, '%');
>> +                break;
>> +            case 'y':
>> +                g_string_append_printf(string_buffer, "0x%" PRIx64,
>> +                        process->current_function);
>> +                break;
>> +            }
>> +        } else {
>> +            /* Copy every character if not equals to '%' */
> 
> "if not equal"
> 
>> +            g_string_append_c(string_buffer, fmt[i]);
>> +        }
>> +    }
>> +}
>> +
>> +static void init()
>> +{
>> +    gboolean result;
>> +
>> +    LttvAttributeValue value;
>> +
>> +    LttvIAttribute *attributes = LTTV_IATTRIBUTE(lttv_global_attributes());
>> +
>> +    g_info("Init formattedDump.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_text = FALSE;
>> +        lttv_option_add("text", 'T',
> 
> indent problem.
> 
>> +                "output the textDump format",
>> +                "",
>> +                LTTV_OPT_NONE, &a_text, NULL, NULL);
>> +
>> +    a_strace = FALSE;
>> +        lttv_option_add("strace", 'S',
> 
> indent problem.
> 
> Thanks,
> 
> Mathieu
> 
>> +                "output a \"strace-like\" format",
>> +                "",
>> +                LTTV_OPT_NONE, &a_strace, NULL, NULL);
>> +
>> +    a_format = NULL;
>> +    lttv_option_add("format", 'F',
>> +            "output the desired format\n"
>> +            "        FORMAT controls the output.  Interpreted sequences are:\n"
>> +            "\n"
>> +            "        %c   channel name\n"
>> +            "        %p   process name\n"
>> +            "        %e   event name\n"
>> +            "        %r   path to trace\n"
>> +            "        %t   timestamp  (e.g., 2:08:54.025684145)\n"
>> +            "        %s   seconds\n"
>> +            "        %n   nanoseconds\n"
>> +            "        %l   elapsed time with the previous event\n"
>> +            "        %d   pid\n"
>> +            "        %i   ppid\n"
>> +            "        %g   tgid\n"
>> +            "        %u   cpu\n"
>> +            "        %b   brand\n"
>> +            "        %a   state\n"
>> +            "        %y   memory address\n"
>> +            "        %m   markers and tracepoints fields\n",
>> +            "format string (e.g., \"channel:%c event:%e process:%p\")",
>> +            LTTV_OPT_STRING, &a_format, 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 formattedDump");
>> +
>> +    lttv_option_remove("format");
>> +
>> +    lttv_option_remove("output");
>> +
>> +    lttv_option_remove("text");
>> +
>> +    lttv_option_remove("strace");
>> +
>> +    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("formattedDump", "Print events with desired format in a file",
>> +        "Produce a detailed formatted text printout of a trace",
>> +        init, destroy, "batchAnalysis", "option")
>> -- 
>> 1.7.0.4
>> 
>> 
>> _______________________________________________
>> ltt-dev mailing list
>> ltt-dev at lists.casi.polymtl.ca
>> http://lists.casi.polymtl.ca/cgi-bin/mailman/listinfo/ltt-dev
>> 
> 
> -- 
> Mathieu Desnoyers
> Operating System Efficiency R&D Consultant
> EfficiOS Inc.
> http://www.efficios.com
> 
> _______________________________________________
> ltt-dev mailing list
> ltt-dev at lists.casi.polymtl.ca
> http://lists.casi.polymtl.ca/cgi-bin/mailman/listinfo/ltt-dev




More information about the lttng-dev mailing list