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
5 void init(int argc
, char **argv
)
8 lttv_hooks
*before
, *after
;
10 a
= lttv_global_attributes();
11 before
= (lttv_hooks
*)lttv_attributes_get_pointer_pathname(a
,
12 "hooks/trace_set/before");
13 after
= (lttv_hooks
*)lttv_attributes_get_pointer_pathname(a
,
14 "hooks/trace_set/after");
15 lttv_hooks_add(before
, textDump_trace_set_before
, NULL
);
16 lttv_hooks_add(after
, textDump_trace_set_after
, NULL
);
23 lttv_hooks
*before
, *after
;
25 a
= lttv_global_attributes();
26 before
= (lttv_hooks
*)lttv_attributes_get_pointer_pathname(a
,
27 "hooks/trace_set/before");
28 after
= (lttv_hooks
*)lttv_attributes_get_pointer_pathname(a
,
29 "hooks/trace_set/after");
30 lttv_hooks_remove(before
, textDump_trace_set_before
, NULL
);
31 lttv_hooks_remove(after
, textDump_trace_set_after
, NULL
);
34 /* Insert the hooks before and after each trace and tracefile, and for each
35 event. Print a global header. */
37 typedef struct _trace_context
{
40 bool mandatory_fields
;
44 static bool textDump_trace_set_before(void *hook_data
, void *call_data
)
52 a
= lttv_global_attributes();
53 s
= (lttv_trace_set
*)call_data
55 /* Get the file pointer */
57 fp
= (FILE *)lttv_attributes_get_pointer_pathname(a
, "textDump/file");
59 /* For each trace prepare the contexts and insert the hooks */
61 nb
= lttv_trace_set_number(s
);
62 for(i
= 0 ; i
< nb
; i
++) {
63 c
= g_new(trace_context
);
64 a
= lttv_trace_set_trace_attributes(s
, i
);
66 if(lttv_attributes_get_pointer_pathname(a
, "textDump/context") != NULL
) {
67 g_error("Recursive call to TextDump");
71 c
->mandatory_fields
= TRUE
;
72 c
->s
= g_string_new();
75 lttv_attributes_set_pointer_pathname(a
, "textDump/context", c
);
77 h
= lttv_attributes_get_hooks(a
, "hooks/before");
78 lttv_hooks_add(h
, textDump_trace_before
, c
);
79 h
= lttv_attributes_get_hooks(a
, "hooks/after");
80 lttv_hooks_add(h
, textDump_trace_after
, c
);
81 h
= lttv_attributes_get_hooks(a
, "hooks/tacefile/before");
82 lttv_hooks_add(h
, textDump_tracefile_before
, c
);
83 h
= lttv_attributes_get_hooks(a
, "hooks/tracefile/after");
84 lttv_hooks_add(h
, textDump_tracefile_after
, c
);
85 h
= lttv_attributes_get_hooks(a
, "hooks/event/selected");
86 lttv_hooks_add(h
, textDump_event
, c
);
89 /* Print the trace set header */
90 fprintf(fp
,"Trace set contains %d traces\n\n", nb
);
96 /* Remove the hooks before and after each trace and tracefile, and for each
97 event. Print trace set level statistics. */
99 static bool textDump_trace_set_after(void *hook_data
, void *call_data
)
104 lttv_attributes
*ga
, *a
;
107 ga
= lttv_global_attributes();
108 s
= (lttv_trace_set
*)lttv_attributes_get_pointer_pathname(ga
,
111 /* Get the file pointer */
113 fp
= (FILE *)lttv_attributes_get_pointer_pathname(ga
, "textDump/file");
115 /* For each trace remove the hooks */
117 nb
= lttv_trace_set_number(s
);
118 for(i
= 0 ; i
< nb
; i
++) {
119 a
= lttv_trace_set_trace_attributes(s
, i
);
120 c
= (trace_context
*)lttv_attributes_get_pointer_pathname(a
,
122 lttv_attributes_set_pointer_pathname(a
, "textDump/context", NULL
);
125 h
= lttv_attributes_get_hooks(a
, "hooks/before");
126 lttv_hooks_remove(h
, textDump_trace_before
, c
);
127 h
= lttv_attributes_get_hooks(a
, "hooks/after");
128 lttv_hooks_remove(h
, textDump_trace_after
, c
);
129 h
= lttv_attributes_get_hooks(a
, "hooks/tacefile/before");
130 lttv_hooks_remove(h
, textDump_tracefile_before
, c
);
131 h
= lttv_attributes_get_hooks(a
, "hooks/tracefile/after");
132 lttv_hooks_remove(h
, textDump_tracefile_after
, c
);
133 h
= lttv_attributes_get_hooks(a
, "hooks/event/selected");
134 lttv_hooks_remove(h
, textDump_event
, c
);
138 /* Print the trace set statistics */
140 fprintf(fp
,"Trace set contains %d traces\n\n", nb
);
148 /* Print a trace level header */
150 static bool textDump_trace_before(void *hook_data
, void *call_data
)
155 c
= (trace_context
*)hook_data
;
156 t
= (ltt_trace
*)call_data
;
157 fprintf(c
->fp
,"Start trace\n");
162 /* Print trace level statistics */
164 static bool textDump_trace_after(void *hook_data
, void *call_data
)
169 c
= (trace_context
*)hook_data
;
170 t
= (ltt_trace
*)call_data
;
171 fprintf(c
->fp
,"End trace\n");
172 print_stats(c
->fp
,c
->a
);
177 static bool textDump_tracefile_before(void *hook_data
, void *call_data
)
182 c
= (trace_context
*)hook_data
;
183 tf
= (ltt_tracefile
*)call_data
;
184 fprintf(c
->fp
,"Start tracefile\n");
189 static bool textDump_tracefile_after(void *hook_data
, void *call_data
)
194 c
= (trace_context
*)hook_data
;
195 tf
= (ltt_tracefile
*)call_data
;
196 fprintf(c
->fp
,"End tracefile\n");
201 /* Print the event content */
203 static bool textDump_event(void *hook_data
, void *call_data
)
208 e
= (ltt_event
*)call_data
;
209 c
= (event_context
*)hook_data
;
210 lttv_event_to_string(e
,c
->s
,c
->mandatory_fields
);
216 static void print_stats(FILE *fp
, lttv_attributes
*a
)
218 int i
, j
, k
, nb
, nbc
;
220 lttv_attributes
*sa
, *ra
;
221 lttv_attribute
*reports
, *content
;
222 lttv_key
*key
, *previous_key
, null_key
;
224 null_key
= lttv_key_new_pathname("");
225 sa
= (lttv_attributes
*)lttv_attributes_get_pointer_pathname(a
,"stats");
226 reports
= lttv_attributes_array_get(sa
);
227 nb
= lttv_attributes_number(sa
);
229 for(i
= 0 ; i
< nb
; i
++) {
230 ra
= (lttv_attributes
*)reports
[i
].v
.p
;
231 key
= reports
[i
].key
;
232 g_assert(reports
[i
].t
== LTTV_POINTER
);
234 /* CHECK maybe have custom handlers registered for some specific reports */
238 content
= lttv_attributes_array_get(ra
);
239 nbc
= lttv_attributes_number(ra
);
240 lttv_attribute_array_sort_lexicographic(content
, nbc
, NULL
, 0);
241 previous_key
= nullKey
;
242 for(j
= 0 ; j
< nbc
; j
++) {
243 key
= content
[j
].key
;
244 for(k
= 0 ; lttv_key_index(previous_key
,k
) == lttv_index(key
,k
) ; k
++)
245 for(; k
< lttv_key_number(key
) ; k
++) {
246 for(l
= 0 ; l
< k
; l
++) fprintf(fp
," ");
247 fprintf(fp
, "%s", lttv_string_id_to_string(lttv_index(key
,k
)));
248 if(k
== lttv_key_number(key
)) {
249 switch(content
[j
].t
) {
251 fprintf(fp
," %d\n", content
[j
].v
.i
);
254 fprintf(fp
," %d.%09d\n", content
[j
].v
.t
.tv_sec
,
255 content
[j
].v
.t
.tv_nsec
);
258 fprintf(fp
," %g\n", content
[j
].v
.d
);
261 fprintf(fp
," pointer\n");
265 else fprintf(fp
,"\n");
268 lttv_attribute_array_destroy(content
);
270 lttv_attribute_array_destroy(reports
);
271 lttv_key_destroy(null_key
);
275 void lttv_event_to_string(ltt_event
*e
, lttv_string
*s
, bool mandatory_fields
)
277 ltt_facility
*facility
;
278 ltt_eventtype
*eventtype
;
283 g_string_set_size(s
,0);
285 facility
= lttv_event_facility(e
);
286 eventtype
= ltt_event_eventtype(e
);
287 field
= ltt_event_field(e
);
289 if(mandatory_fields
) {
290 time
= ltt_event_time(e
);
291 g_string_append_printf(s
,"%s.%s: %ld.%ld",ltt_facility_name(facility
),
292 ltt_eventtype_name(eventtype
), (long)time
.tv_sec
, time
.tv_nsec
);
298 void print_field(ltt_event
*e
, ltt_field
*f
, lttv_string
*s
) {
304 type
= ltt_field_type(f
);
305 switch(ltt_type_class(type
)) {
307 g_string_append_printf(s
, " %ld", ltt_event_get_long_int(e
,f
));
311 g_string_append_printf(s
, " %lu", ltt_event_get_long_unsigned(e
,f
));
315 g_string_append_printf(s
, " %g", ltt_event_get_double(e
,f
));
319 g_string_append_printf(s
, " \"%s\"", ltt_event_get_string(e
,f
));
323 g_string_append_printf(s
, " %s", ltt_enum_string_get(type
,
324 event_get_unsigned(e
,f
));
329 g_string_append_printf(s
, " {");
330 nb
= ltt_event_field_element_number(e
,f
);
331 element
= ltt_field_element(f
);
332 for(i
= 0 ; i
< nb
; i
++) {
333 ltt_event_field_element_select(e
,f
,i
);
334 print_field(e
,element
,s
);
336 g_string_append_printf(s
, " }");
340 g_string_append_printf(s
, " {");
341 nb
= ltt_type_member_number(type
);
342 for(i
= 0 ; i
< nb
; i
++) {
343 element
= ltt_field_member(f
,i
);
344 print_field(e
,element
,s
);
346 g_string_append_printf(s
, " }");