2 * This file is part of the Linux Trace Toolkit viewer
3 * Copyright (C) 2003-2004 Michel Dagenais
4 * 2005 Mathieu Desnoyers
5 * 2011 Vincent Attard <vinc.attard@gmail.com>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License Version 2 as
9 * published by the Free Software Foundation;
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
23 * Formatted dump plugin prints a formatted output of each events in a trace.
24 * The output format is defined as a parameter. It provides a default format
25 * easy to read, a "strace-like" format and the original textDump format for
26 * backward compatibility.
33 #include <lttv/lttv.h>
34 #include <lttv/option.h>
35 #include <lttv/module.h>
36 #include <lttv/hook.h>
37 #include <lttv/attribute.h>
38 #include <lttv/iattribute.h>
39 #include <lttv/stats.h>
40 #include <lttv/filter.h>
41 #include <lttv/print.h>
43 #include <ltt/event.h>
44 #include <ltt/trace.h>
50 static gboolean a_no_field_names
;
51 static gboolean a_state
;
52 static gboolean a_text
;
53 static gboolean a_strace
;
55 static char *a_file_name
;
56 static char *a_format
;
58 static LttvHooks
*before_traceset
;
59 static LttvHooks
*event_hook
;
61 static const char default_format
[] =
62 "channel:%c event:%e timestamp:%t elapsed:%l cpu:%u pid:%d ppid:%i "
63 "tgpid:%g process:%p brand:%b state:%a payload:{ %m }";
64 static const char textDump_format
[] =
65 "%c.%e: %s.%n (%r/%c_%u), %d, %g, %p, %b, %i, %y, %a { %m }";
66 static const char strace_format
[] = "%e(%m) %s.%n";
70 static GString
*a_string
;
72 static gboolean
open_output_file(void *hook_data
, void *call_data
)
74 g_info("Open the output file");
75 if (a_file_name
== NULL
) {
78 a_file
= fopen(a_file_name
, "w");
81 g_error("cannot open file %s", a_file_name
);
86 static int write_event_content(void *hook_data
, void *call_data
)
90 LttvIAttribute
*attributes
= LTTV_IATTRIBUTE(lttv_global_attributes());
92 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
94 LttvTracefileState
*tfs
= (LttvTracefileState
*)call_data
;
98 LttvAttributeValue value_filter
;
102 guint cpu
= tfs
->cpu
;
103 LttvTraceState
*ts
= (LttvTraceState
*)tfc
->t_context
;
104 LttvProcessState
*process
= ts
->running_process
[cpu
];
106 e
= ltt_tracefile_get_event(tfc
->tf
);
108 result
= lttv_iattribute_find_by_path(attributes
, "filter/lttv_filter",
109 LTTV_POINTER
, &value_filter
);
111 filter
= (LttvFilter
*)*(value_filter
.v_pointer
);
113 /* call to the filter if available */
114 if (filter
->head
!= NULL
) {
115 if (!lttv_filter_tree_parse(filter
->head
, e
, tfc
->tf
,
116 tfc
->t_context
->t
, tfc
, NULL
, NULL
)) {
121 lttv_event_to_string(e
, a_string
, TRUE
, !a_no_field_names
, tfs
);
124 g_string_append_printf(a_string
, "%s ",
125 g_quark_to_string(process
->state
->s
));
128 g_string_append_printf(a_string
, "\n");
130 fputs(a_string
->str
, a_file
);
134 void lttv_event_to_string(LttEvent
*e
, GString
*string_buffer
, gboolean mandatory_fields
,
135 gboolean field_names
, LttvTracefileState
*tfs
)
137 struct marker_field
*field
;
138 struct marker_info
*info
;
141 static LttTime time_prev
= {0, 0};
144 * Added this static value into state.c and reset each time you do a
145 * seek for using it in the GUI.
151 guint cpu
= tfs
->cpu
;
152 LttvTraceState
*ts
= (LttvTraceState
*)tfs
->parent
.t_context
;
153 LttvProcessState
*process
= ts
->running_process
[cpu
];
155 info
= marker_get_info_from_id(tfs
->parent
.tf
->mdata
, e
->event_id
);
156 if (mandatory_fields
) {
157 time
= ltt_event_time(e
);
158 /* Calculate elapsed time between current and previous event */
159 if (time_prev
.tv_sec
== 0 && time_prev
.tv_nsec
== 0) {
160 time_prev
= ltt_event_time(e
);
165 * Keep in mind that you should add the ability to
166 * restore the previous event time to state.c if you
167 * want to reuse this code into the GUI.
170 elapse
= ltt_time_sub(time
, time_prev
);
175 /* textDump format (used with -T command option) */
176 fmt
= textDump_format
;
177 } else if (a_strace
) {
178 /* strace-like format (used with -S command option) */
180 } else if (!a_format
) {
181 /* Default format (used if no option) */
182 fmt
= default_format
;
185 * formattedDump format
186 * (used with -F command option following by the desired format)
191 g_string_set_size(string_buffer
, 0);
194 * all '%-' are replaced by the desired value in 'string_buffer'
197 for (i
= 0; i
< len
; i
++) {
201 g_string_append_printf(string_buffer
,
202 "%ld:%02ld:%02ld.%09ld",
204 (time
.tv_sec
%3600)/60,
209 g_string_append(string_buffer
,
210 g_quark_to_string(ltt_tracefile_name(tfs
->parent
.tf
)));
213 g_string_append(string_buffer
,
214 g_quark_to_string(info
->name
));
217 g_string_append_printf(string_buffer
, "%u",
221 g_string_append_printf(string_buffer
, "%ld",
225 g_string_append_printf(string_buffer
, "%ld",
229 g_string_append_printf(string_buffer
, "%u",
233 g_string_append_printf(string_buffer
, "%u",
237 g_string_append(string_buffer
,
238 g_quark_to_string(process
->name
));
241 g_string_append_printf(string_buffer
, "%u",
245 g_string_append_printf(string_buffer
, "%u", cpu
);
248 g_string_append_printf(string_buffer
,
250 elapse
.tv_sec
, elapse
.tv_nsec
);
253 g_string_append(string_buffer
,
254 g_quark_to_string(process
->state
->t
));
259 * Get and print markers and tracepoints fields
260 * into 'string_buffer'
262 if (marker_get_num_fields(info
) == 0)
264 for (field
= marker_get_field(info
, 0);
265 field
!= marker_get_field(info
, marker_get_num_fields(info
));
267 if (field
!= marker_get_field(info
, 0)) {
268 g_string_append(string_buffer
, ", ");
271 lttv_print_field(e
, field
, string_buffer
, field_names
, tfs
);
276 g_string_append(string_buffer
, g_quark_to_string(
277 ltt_trace_name(ltt_tracefile_get_trace(tfs
->parent
.tf
))));
280 g_string_append_c(string_buffer
, '%');
283 g_string_append_printf(string_buffer
,
285 process
->current_function
);
289 /* Copy every character if different of '%' */
290 g_string_append_c(string_buffer
, fmt
[i
]);
299 LttvAttributeValue value
;
301 LttvIAttribute
*attributes
= LTTV_IATTRIBUTE(lttv_global_attributes());
303 g_info("Init formattedDump.c");
305 a_string
= g_string_new("");
308 lttv_option_add("output", 'o',
309 "output file where the text is written",
311 LTTV_OPT_STRING
, &a_file_name
, NULL
, NULL
);
314 lttv_option_add("text", 'T',
315 "output the textDump format",
317 LTTV_OPT_NONE
, &a_text
, NULL
, NULL
);
320 lttv_option_add("strace", 'S',
321 "output a \"strace-like\" format",
323 LTTV_OPT_NONE
, &a_strace
, NULL
, NULL
);
326 lttv_option_add("format", 'F',
327 "output the desired format\n"
328 " FORMAT controls the output. "
329 "Interpreted sequences are:\n"
334 " %r path to trace\n"
335 " %t timestamp (e.g., 2:08:54.025684145)\n"
338 " %l elapsed time with the previous event\n"
345 " %y memory address\n"
346 " %m markers and tracepoints fields\n",
347 "format string (e.g., \"channel:%c event:%e process:%p\")",
348 LTTV_OPT_STRING
, &a_format
, NULL
, NULL
);
350 result
= lttv_iattribute_find_by_path(attributes
, "hooks/event",
351 LTTV_POINTER
, &value
);
353 event_hook
= *(value
.v_pointer
);
354 g_assert(event_hook
);
355 lttv_hooks_add(event_hook
, write_event_content
, NULL
, LTTV_PRIO_DEFAULT
);
357 result
= lttv_iattribute_find_by_path(attributes
, "hooks/traceset/before",
358 LTTV_POINTER
, &value
);
360 before_traceset
= *(value
.v_pointer
);
361 g_assert(before_traceset
);
362 lttv_hooks_add(before_traceset
, open_output_file
, NULL
,
367 static void destroy()
369 g_info("Destroy formattedDump");
371 lttv_option_remove("format");
373 lttv_option_remove("output");
375 lttv_option_remove("text");
377 lttv_option_remove("strace");
379 g_string_free(a_string
, TRUE
);
381 lttv_hooks_remove_data(event_hook
, write_event_content
, NULL
);
383 lttv_hooks_remove_data(before_traceset
, open_output_file
, NULL
);
388 LTTV_MODULE("formattedDump", "Print events with desired format in a file",
389 "Produce a detailed formatted text printout of a trace",
390 init
, destroy
, "batchAnalysis", "option")