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