filter core:
[lttv.git] / ltt / branches / poly / lttv / modules / text / textDump.c
1 /* This file is part of the Linux Trace Toolkit viewer
2 * Copyright (C) 2003-2004 Michel Dagenais
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License Version 2 as
6 * published by the Free Software Foundation;
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
16 * MA 02111-1307, USA.
17 */
18
19 /* The text dump facility needs to print headers before the trace set and
20 before each trace, to print each event, and to print statistics
21 after each trace. */
22
23 #include <lttv/lttv.h>
24 #include <lttv/option.h>
25 #include <lttv/module.h>
26 #include <lttv/hook.h>
27 #include <lttv/attribute.h>
28 #include <lttv/iattribute.h>
29 #include <lttv/stats.h>
30 #include <lttv/filter.h>
31 #include <ltt/ltt.h>
32 #include <ltt/event.h>
33 #include <ltt/type.h>
34 #include <ltt/trace.h>
35 #include <ltt/facility.h>
36 #include <stdio.h>
37
38 static gboolean
39 a_field_names,
40 a_state,
41 a_cpu_stats,
42 a_process_stats;
43
44 static char
45 *a_file_name = NULL;
46
47 static LttvHooks
48 *before_traceset,
49 *after_traceset,
50 *before_trace,
51 *event_hook;
52
53 extern LttvFilter *a_lttv_filter;
54
55 void print_field(LttEvent *e, LttField *f, GString *s, gboolean field_names) {
56
57 LttType *type;
58
59 LttField *element;
60
61 char *name;
62
63 int nb, i;
64
65 type = ltt_field_type(f);
66 switch(ltt_type_class(type)) {
67 case LTT_INT:
68 g_string_append_printf(s, " %lld", ltt_event_get_long_int(e,f));
69 break;
70
71 case LTT_UINT:
72 g_string_append_printf(s, " %llu", ltt_event_get_long_unsigned(e,f));
73 break;
74
75 case LTT_FLOAT:
76 g_string_append_printf(s, " %g", ltt_event_get_double(e,f));
77 break;
78
79 case LTT_STRING:
80 g_string_append_printf(s, " \"%s\"", ltt_event_get_string(e,f));
81 break;
82
83 case LTT_ENUM:
84 g_string_append_printf(s, " %s", ltt_enum_string_get(type,
85 ltt_event_get_unsigned(e,f)-1));
86 break;
87
88 case LTT_ARRAY:
89 case LTT_SEQUENCE:
90 g_string_append_printf(s, " {");
91 nb = ltt_event_field_element_number(e,f);
92 element = ltt_field_element(f);
93 for(i = 0 ; i < nb ; i++) {
94 ltt_event_field_element_select(e,f,i);
95 print_field(e, element, s, field_names);
96 }
97 g_string_append_printf(s, " }");
98 break;
99
100 case LTT_STRUCT:
101 g_string_append_printf(s, " {");
102 nb = ltt_type_member_number(type);
103 for(i = 0 ; i < nb ; i++) {
104 element = ltt_field_member(f,i);
105 if(field_names) {
106 ltt_type_member_type(type, i, &name);
107 g_string_append_printf(s, " %s = ", name);
108 }
109 print_field(e, element, s, field_names);
110 }
111 g_string_append_printf(s, " }");
112 break;
113
114 case LTT_UNION:
115 g_string_append_printf(s, " {");
116 nb = ltt_type_member_number(type);
117 for(i = 0 ; i < nb ; i++) {
118 element = ltt_field_member(f,i);
119 if(field_names) {
120 ltt_type_member_type(type, i, &name);
121 g_string_append_printf(s, " %s = ", name);
122 }
123 print_field(e, element, s, field_names);
124 }
125 g_string_append_printf(s, " }");
126 break;
127
128 }
129 }
130
131
132 void lttv_event_to_string(LttEvent *e, GString *s,
133 gboolean mandatory_fields, gboolean field_names, LttvTracefileState *tfs)
134 {
135 LttFacility *facility;
136
137 LttEventType *event_type;
138
139 LttType *type;
140
141 LttField *field;
142
143 LttTime time;
144
145 g_string_set_size(s,0);
146
147 facility = ltt_event_facility(e);
148 event_type = ltt_event_eventtype(e);
149 field = ltt_event_field(e);
150
151 if(mandatory_fields) {
152 time = ltt_event_time(e);
153 g_string_append_printf(s,"%s.%s: %ld.%09ld (%s)",
154 ltt_facility_name(facility),
155 ltt_eventtype_name(event_type), (long)time.tv_sec, time.tv_nsec,
156 g_quark_to_string(tfs->cpu_name));
157 /* Print the process id and the state/interrupt type of the process */
158 g_string_append_printf(s,", %u, %u, %s", tfs->process->pid,
159 tfs->process->ppid,
160 g_quark_to_string(tfs->process->state->t));
161 }
162
163 if(field)
164 print_field(e, field, s, field_names);
165 }
166
167
168 static void
169 print_tree(FILE *fp, GString *indent, LttvAttribute *tree)
170 {
171 int i, nb, saved_length;
172
173 LttvAttribute *subtree;
174
175 LttvAttributeName name;
176
177 LttvAttributeValue value;
178
179 LttvAttributeType type;
180
181 nb = lttv_attribute_get_number(tree);
182 for(i = 0 ; i < nb ; i++) {
183 type = lttv_attribute_get(tree, i, &name, &value);
184 fprintf(fp, "%s%s: ", indent->str, g_quark_to_string(name));
185
186 switch(type) {
187 case LTTV_INT:
188 fprintf(fp, "%d\n", *value.v_int);
189 break;
190 case LTTV_UINT:
191 fprintf(fp, "%u\n", *value.v_uint);
192 break;
193 case LTTV_LONG:
194 fprintf(fp, "%ld\n", *value.v_long);
195 break;
196 case LTTV_ULONG:
197 fprintf(fp, "%lu\n", *value.v_ulong);
198 break;
199 case LTTV_FLOAT:
200 fprintf(fp, "%f\n", (double)*value.v_float);
201 break;
202 case LTTV_DOUBLE:
203 fprintf(fp, "%f\n", *value.v_double);
204 break;
205 case LTTV_TIME:
206 fprintf(fp, "%10lu.%09lu\n", value.v_time->tv_sec,
207 value.v_time->tv_nsec);
208 break;
209 case LTTV_POINTER:
210 fprintf(fp, "POINTER\n");
211 break;
212 case LTTV_STRING:
213 fprintf(fp, "%s\n", *value.v_string);
214 break;
215 case LTTV_GOBJECT:
216 if(LTTV_IS_ATTRIBUTE(*(value.v_gobject))) {
217 fprintf(fp, "\n");
218 subtree = (LttvAttribute *)*(value.v_gobject);
219 saved_length = indent->len;
220 g_string_append(indent, " ");
221 print_tree(fp, indent, subtree);
222 g_string_truncate(indent, saved_length);
223 }
224 else fprintf(fp, "GOBJECT\n");
225 break;
226 case LTTV_NONE:
227 break;
228 }
229 }
230 }
231
232
233 static void
234 print_stats(FILE *fp, LttvTracesetStats *tscs)
235 {
236 int i, nb, saved_length;
237
238 LttvTraceset *ts;
239
240 LttvTraceStats *tcs;
241
242 GString *indent;
243
244 LttSystemDescription *desc;
245
246 if(tscs->stats == NULL) return;
247 indent = g_string_new("");
248 fprintf(fp, "Traceset statistics:\n\n");
249 print_tree(fp, indent, tscs->stats);
250
251 ts = tscs->parent.parent.ts;
252 nb = lttv_traceset_number(ts);
253
254 for(i = 0 ; i < nb ; i++) {
255 tcs = (LttvTraceStats *)(LTTV_TRACESET_CONTEXT(tscs)->traces[i]);
256 desc = ltt_trace_system_description(tcs->parent.parent.t);
257 LttTime start_time = ltt_trace_system_description_trace_start_time(desc);
258 fprintf(fp, "Trace on system %s at time %lu.%09lu :\n",
259 ltt_trace_system_description_node_name(desc),
260 start_time.tv_sec,
261 start_time.tv_nsec);
262 saved_length = indent->len;
263 g_string_append(indent, " ");
264 print_tree(fp, indent, tcs->stats);
265 g_string_truncate(indent, saved_length);
266 }
267 g_string_free(indent, TRUE);
268 }
269
270
271 /* Insert the hooks before and after each trace and tracefile, and for each
272 event. Print a global header. */
273
274 static FILE *a_file;
275
276 static GString *a_string;
277
278 static gboolean write_traceset_header(void *hook_data, void *call_data)
279 {
280 LttvTracesetContext *tc = (LttvTracesetContext *)call_data;
281
282 g_info("TextDump traceset header");
283
284 if(a_file_name == NULL) a_file = stdout;
285 else a_file = fopen(a_file_name, "w");
286
287 if(a_file == NULL) g_error("cannot open file %s", a_file_name);
288
289 /* Print the trace set header */
290 fprintf(a_file,"Trace set contains %d traces\n\n",
291 lttv_traceset_number(tc->ts));
292
293 return FALSE;
294 }
295
296
297 static gboolean write_traceset_footer(void *hook_data, void *call_data)
298 {
299 LttvTracesetContext *tc = (LttvTracesetContext *)call_data;
300
301 g_info("TextDump traceset footer");
302
303 fprintf(a_file,"End trace set\n\n");
304
305 if(LTTV_IS_TRACESET_STATS(tc)) {
306 lttv_stats_sum_traceset((LttvTracesetStats *)tc);
307 print_stats(a_file, (LttvTracesetStats *)tc);
308 }
309
310 if(a_file_name != NULL) fclose(a_file);
311
312 return FALSE;
313 }
314
315
316 static gboolean write_trace_header(void *hook_data, void *call_data)
317 {
318 LttvTraceContext *tc = (LttvTraceContext *)call_data;
319
320 LttSystemDescription *system = ltt_trace_system_description(tc->t);
321
322 fprintf(a_file," Trace from %s in %s\n%s\n\n",
323 ltt_trace_system_description_node_name(system),
324 ltt_trace_system_description_domain_name(system),
325 ltt_trace_system_description_description(system));
326 return FALSE;
327 }
328
329
330 static int write_event_content(void *hook_data, void *call_data)
331 {
332 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
333
334 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
335
336 LttEvent *e;
337
338 e = tfc->e;
339
340 /*
341 * call to the filter if available
342 */
343 if(!lttv_filter_tree_parse(a_lttv_filter->head,e,NULL,NULL,NULL)) {
344 return FALSE;
345 }
346
347 lttv_event_to_string(e, a_string, TRUE, a_field_names, tfs);
348 g_string_append_printf(a_string,"\n");
349
350 if(a_state) {
351 g_string_append_printf(a_string, " %s ",
352 g_quark_to_string(tfs->process->state->s));
353 }
354
355 fputs(a_string->str, a_file);
356 return FALSE;
357 }
358
359
360 static void init()
361 {
362 LttvAttributeValue value;
363
364 LttvIAttribute *attributes = LTTV_IATTRIBUTE(lttv_global_attributes());
365
366 g_info("Init textDump.c");
367
368 a_string = g_string_new("");
369
370 a_file_name = NULL;
371 lttv_option_add("output", 'o',
372 "output file where the text is written",
373 "file name",
374 LTTV_OPT_STRING, &a_file_name, NULL, NULL);
375
376 a_field_names = FALSE;
377 lttv_option_add("field_names", 'l',
378 "write the field names for each event",
379 "",
380 LTTV_OPT_NONE, &a_field_names, NULL, NULL);
381
382 a_state = FALSE;
383 lttv_option_add("process_state", 's',
384 "write the pid and state for each event",
385 "",
386 LTTV_OPT_NONE, &a_state, NULL, NULL);
387
388 a_cpu_stats = FALSE;
389 lttv_option_add("cpu_stats", 'c',
390 "write the per cpu statistics",
391 "",
392 LTTV_OPT_NONE, &a_cpu_stats, NULL, NULL);
393
394 a_process_stats = FALSE;
395 lttv_option_add("process_stats", 'p',
396 "write the per process statistics",
397 "",
398 LTTV_OPT_NONE, &a_process_stats, NULL, NULL);
399
400 g_assert(lttv_iattribute_find_by_path(attributes, "hooks/event",
401 LTTV_POINTER, &value));
402 g_assert((event_hook = *(value.v_pointer)) != NULL);
403 lttv_hooks_add(event_hook, write_event_content, NULL, LTTV_PRIO_DEFAULT);
404
405 g_assert(lttv_iattribute_find_by_path(attributes, "hooks/trace/before",
406 LTTV_POINTER, &value));
407 g_assert((before_trace = *(value.v_pointer)) != NULL);
408 lttv_hooks_add(before_trace, write_trace_header, NULL, LTTV_PRIO_DEFAULT);
409
410 g_assert(lttv_iattribute_find_by_path(attributes, "hooks/traceset/before",
411 LTTV_POINTER, &value));
412 g_assert((before_traceset = *(value.v_pointer)) != NULL);
413 lttv_hooks_add(before_traceset, write_traceset_header, NULL,
414 LTTV_PRIO_DEFAULT);
415
416 g_assert(lttv_iattribute_find_by_path(attributes, "hooks/traceset/after",
417 LTTV_POINTER, &value));
418 g_assert((after_traceset = *(value.v_pointer)) != NULL);
419 lttv_hooks_add(after_traceset, write_traceset_footer, NULL,
420 LTTV_PRIO_DEFAULT);
421 }
422
423
424 static void destroy()
425 {
426 g_info("Destroy textDump");
427
428 lttv_option_remove("output");
429
430 lttv_option_remove("field_names");
431
432 lttv_option_remove("process_state");
433
434 lttv_option_remove("cpu_stats");
435
436 lttv_option_remove("process_stats");
437
438 g_string_free(a_string, TRUE);
439
440 lttv_hooks_remove_data(event_hook, write_event_content, NULL);
441
442 lttv_hooks_remove_data(before_trace, write_trace_header, NULL);
443
444 lttv_hooks_remove_data(before_trace, write_traceset_header, NULL);
445
446 lttv_hooks_remove_data(before_trace, write_traceset_footer, NULL);
447 }
448
449
450 LTTV_MODULE("textDump", "Print events in a file", \
451 "Produce a detailed text printout of a trace", \
452 init, destroy, "stats", "batchAnalysis", "option")
453
This page took 0.052449 seconds and 4 git commands to generate.