Filter for selecting trace and tracefile
[lttv.git] / ltt / branches / poly / lttv / textDump.c
CommitLineData
48f6f3c2 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
996acd92 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>
b445142a 11#include <lttv/stats.h>
ffd54a90 12#include <ltt/ltt.h>
13#include <ltt/event.h>
14#include <ltt/type.h>
15#include <ltt/trace.h>
16#include <stdio.h>
996acd92 17
dc877563 18static gboolean
19 a_field_names,
b445142a 20 a_state,
21 a_cpu_stats,
22 a_process_stats;
dc877563 23
24static char
b445142a 25 *a_file_name = NULL;
dc877563 26
27static LttvHooks
28 *before_traceset,
29 *after_traceset,
30 *before_trace,
31 *before_event;
32
f60d7a47 33
ffd54a90 34void print_field(LttEvent *e, LttField *f, GString *s, gboolean field_names) {
dc877563 35
ffd54a90 36 LttType *type;
dc877563 37
ffd54a90 38 LttField *element;
dc877563 39
ffd54a90 40 char *name;
dc877563 41
ffd54a90 42 int nb, i;
dc877563 43
ffd54a90 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;
dc877563 49
ffd54a90 50 case LTT_UINT:
51 g_string_append_printf(s, " %lu", ltt_event_get_long_unsigned(e,f));
52 break;
dc877563 53
ffd54a90 54 case LTT_FLOAT:
55 g_string_append_printf(s, " %g", ltt_event_get_double(e,f));
56 break;
dc877563 57
ffd54a90 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,
c6bc9cb9 64 ltt_event_get_unsigned(e,f)-1));
ffd54a90 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);
c432246e 84 if(field_names) {
ffd54a90 85 ltt_type_member_type(type, i, &name);
c432246e 86 g_string_append_printf(s, " %s = ", name);
ffd54a90 87 }
88 print_field(e, element, s, field_names);
89 }
90 g_string_append_printf(s, " }");
91 break;
92 }
48f6f3c2 93}
94
95
ffd54a90 96void lttv_event_to_string(LttEvent *e, LttTracefile *tf, GString *s,
3d27549e 97 gboolean mandatory_fields, gboolean field_names, LttvTracefileState *tfs)
98{
ffd54a90 99 LttFacility *facility;
48f6f3c2 100
ffd54a90 101 LttEventType *event_type;
48f6f3c2 102
ffd54a90 103 LttType *type;
104
105 LttField *field;
48f6f3c2 106
ffd54a90 107 LttTime time;
48f6f3c2 108
ffd54a90 109 g_string_set_size(s,0);
dc877563 110
ffd54a90 111 facility = ltt_event_facility(e);
112 event_type = ltt_event_eventtype(e);
113 field = ltt_event_field(e);
48f6f3c2 114
ffd54a90 115 if(mandatory_fields) {
116 time = ltt_event_time(e);
b445142a 117 g_string_append_printf(s,"%s.%s: %ld.%09ld (%s)",
118 ltt_facility_name(facility),
ffd54a90 119 ltt_eventtype_name(event_type), (long)time.tv_sec, time.tv_nsec,
b445142a 120 g_quark_to_string(tfs->cpu_name));
c432246e 121 /* Print the process id and the state/interrupt type of the process */
07bb8c8f 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));
ffd54a90 125 }
126
c6bc9cb9 127 if(field)
128 print_field(e, field, s, field_names);
ffd54a90 129}
48f6f3c2 130
131
b445142a 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
dc877563 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;
48f6f3c2 236
dc877563 237static GString *a_string;
238
ffd54a90 239static gboolean write_traceset_header(void *hook_data, void *call_data)
48f6f3c2 240{
dc877563 241 LttvTracesetContext *tc = (LttvTracesetContext *)call_data;
48f6f3c2 242
b445142a 243 g_info("TextDump traceset header");
244
dc877563 245 if(a_file_name == NULL) a_file = stdout;
246 else a_file = fopen(a_file_name, "w");
48f6f3c2 247
dc877563 248 if(a_file == NULL) g_error("cannot open file %s", a_file_name);
48f6f3c2 249
dc877563 250 /* Print the trace set header */
251 fprintf(a_file,"Trace set contains %d traces\n\n",
ffd54a90 252 lttv_traceset_number(tc->ts));
48f6f3c2 253
dc877563 254 return FALSE;
48f6f3c2 255}
256
257
ffd54a90 258static gboolean write_traceset_footer(void *hook_data, void *call_data)
48f6f3c2 259{
dc877563 260 LttvTracesetContext *tc = (LttvTracesetContext *)call_data;
48f6f3c2 261
b445142a 262 g_info("TextDump traceset footer");
263
dc877563 264 fprintf(a_file,"End trace set\n\n");
48f6f3c2 265
b445142a 266 if(LTTV_IS_TRACESET_STATS(tc)) {
267 print_stats(a_file, (LttvTracesetStats *)tc);
268 }
269
ffd54a90 270 if(a_file_name != NULL) fclose(a_file);
271
dc877563 272 return FALSE;
48f6f3c2 273}
274
275
dc877563 276static gboolean write_trace_header(void *hook_data, void *call_data)
48f6f3c2 277{
dc877563 278 LttvTraceContext *tc = (LttvTraceContext *)call_data;
279
280 LttSystemDescription *system = ltt_trace_system_description(tc->t);
48f6f3c2 281
dc877563 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;
48f6f3c2 285}
286
287
dc877563 288static int write_event_content(void *hook_data, void *call_data)
48f6f3c2 289{
dc877563 290 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
48f6f3c2 291
dc877563 292 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
48f6f3c2 293
dc877563 294 LttEvent *e;
48f6f3c2 295
dc877563 296 e = tfc->e;
48f6f3c2 297
3d27549e 298 lttv_event_to_string(e, tfc->tf, a_string, TRUE, a_field_names, tfs);
c6bc9cb9 299 g_string_append_printf(a_string,"\n");
dc877563 300
301 if(a_state) {
302 g_string_append_printf(a_string, " %s",
ffd54a90 303 g_quark_to_string(tfs->process->state->s));
dc877563 304 }
48f6f3c2 305
ffd54a90 306 fputs(a_string->str, a_file);
dc877563 307 return FALSE;
48f6f3c2 308}
309
310
d83f6739 311G_MODULE_EXPORT void init(LttvModule *self, int argc, char **argv)
48f6f3c2 312{
ffd54a90 313 LttvAttributeValue value;
48f6f3c2 314
ffd54a90 315 LttvIAttribute *attributes = LTTV_IATTRIBUTE(lttv_global_attributes());
48f6f3c2 316
b445142a 317 g_info("Init textDump.c");
9402662d 318
308711e5 319 lttv_module_require(self, "libbatchAnalysis", argc, argv);
320
c6bc9cb9 321 a_string = g_string_new("");
322
ffd54a90 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);
48f6f3c2 328
ffd54a90 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);
48f6f3c2 334
ffd54a90 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);
dc877563 340
b445142a 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
ffd54a90 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);
dc877563 357
ffd54a90 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);
dc877563 362
ffd54a90 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);
dc877563 367
ffd54a90 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}
48f6f3c2 373
48f6f3c2 374
d83f6739 375G_MODULE_EXPORT void destroy()
ffd54a90 376{
b445142a 377 g_info("Destroy textDump");
378
ffd54a90 379 lttv_option_remove("output");
48f6f3c2 380
ffd54a90 381 lttv_option_remove("field_names");
48f6f3c2 382
ffd54a90 383 lttv_option_remove("process_state");
48f6f3c2 384
b445142a 385 lttv_option_remove("cpu_stats");
386
387 lttv_option_remove("process_stats");
388
c6bc9cb9 389 g_string_free(a_string, TRUE);
390
ffd54a90 391 lttv_hooks_remove_data(before_event, write_event_content, NULL);
48f6f3c2 392
ffd54a90 393 lttv_hooks_remove_data(before_trace, write_trace_header, NULL);
48f6f3c2 394
ffd54a90 395 lttv_hooks_remove_data(before_trace, write_traceset_header, NULL);
48f6f3c2 396
ffd54a90 397 lttv_hooks_remove_data(before_trace, write_traceset_footer, NULL);
48f6f3c2 398}
399
400
401
402
This page took 0.04307 seconds and 4 git commands to generate.