Print other fields
[babeltrace.git] / plugins / text / text.c
1 /*
2 * text.c
3 *
4 * Babeltrace CTF Text Output Plugin
5 *
6 * Copyright 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com>
7 *
8 * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
9 *
10 * Permission is hereby granted, free of charge, to any person obtaining a copy
11 * of this software and associated documentation files (the "Software"), to deal
12 * in the Software without restriction, including without limitation the rights
13 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 * copies of the Software, and to permit persons to whom the Software is
15 * furnished to do so, subject to the following conditions:
16 *
17 * The above copyright notice and this permission notice shall be included in
18 * all copies or substantial portions of the Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 * SOFTWARE.
27 */
28
29 #include <babeltrace/plugin/plugin-macros.h>
30 #include <babeltrace/plugin/component.h>
31 #include <babeltrace/plugin/sink.h>
32 #include <babeltrace/plugin/notification/notification.h>
33 #include <babeltrace/plugin/notification/iterator.h>
34 #include <babeltrace/plugin/notification/event.h>
35 #include <babeltrace/values.h>
36 #include <babeltrace/compiler.h>
37 #include <stdio.h>
38 #include <stdbool.h>
39 #include <glib.h>
40 #include "text.h"
41
42 #define PLUGIN_NAME "text"
43
44 static
45 const char *plugin_options[] = {
46 "output-path",
47 "debug-info-dir",
48 "debug-info-target-prefix",
49 "debug-info-full-path",
50 "no-delta",
51 "clock-cycles",
52 "clock-seconds",
53 "clock-date",
54 "clock-gmt",
55 "name-default", /* show/hide */
56 "name-payload",
57 "name-context",
58 "name-scope",
59 "name-header",
60 "field-default", /* show/hide */
61 "field-trace",
62 "field-trace:hostname",
63 "field-trace:domain",
64 "field-trace:procname",
65 "field-trace:vpid",
66 "field-loglevel",
67 "field-emf",
68 "field-callsite",
69 };
70
71 static
72 void destroy_text_data(struct text_component *text)
73 {
74 (void) g_string_free(text->string, TRUE);
75 g_free(text->options.output_path);
76 g_free(text->options.debug_info_dir);
77 g_free(text->options.debug_info_target_prefix);
78 g_free(text);
79 }
80
81 static
82 struct text_component *create_text(void)
83 {
84 struct text_component *text;
85
86 text = g_new0(struct text_component, 1);
87 if (!text) {
88 goto end;
89 }
90 text->string = g_string_new("");
91 if (!text->string) {
92 goto error;
93 }
94 end:
95 return text;
96
97 error:
98 g_free(text);
99 return NULL;
100 }
101
102 static
103 void destroy_text(struct bt_component *component)
104 {
105 void *data = bt_component_get_private_data(component);
106
107 destroy_text_data(data);
108 }
109
110 static
111 enum bt_component_status handle_notification(struct text_component *text,
112 struct bt_notification *notification)
113 {
114 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
115
116 if (!text) {
117 ret = BT_COMPONENT_STATUS_ERROR;
118 goto end;
119 }
120
121 switch (bt_notification_get_type(notification)) {
122 case BT_NOTIFICATION_TYPE_PACKET_START:
123 puts("<packet>");
124 break;
125 case BT_NOTIFICATION_TYPE_PACKET_END:
126 puts("</packet>");
127 break;
128 case BT_NOTIFICATION_TYPE_EVENT:
129 {
130 struct bt_ctf_event *event = bt_notification_event_get_event(
131 notification);
132
133 if (!event) {
134 ret = BT_COMPONENT_STATUS_ERROR;
135 goto end;
136 }
137 ret = text_print_event(text, event);
138 bt_put(event);
139 if (ret != BT_COMPONENT_STATUS_OK) {
140 goto end;
141 }
142 break;
143 }
144 case BT_NOTIFICATION_TYPE_STREAM_END:
145 puts("</stream>");
146 break;
147 default:
148 puts("Unhandled notification type");
149 }
150 end:
151 return ret;
152 }
153
154 static
155 enum bt_component_status run(struct bt_component *component)
156 {
157 enum bt_component_status ret;
158 struct bt_notification *notification = NULL;
159 struct bt_notification_iterator *it;
160 struct text_component *text = bt_component_get_private_data(component);
161
162 ret = bt_component_sink_get_input_iterator(component, 0, &it);
163 if (ret != BT_COMPONENT_STATUS_OK) {
164 goto end;
165 }
166
167 if (!text->processed_first_event) {
168 ret = bt_notification_iterator_next(it);
169 if (ret != BT_COMPONENT_STATUS_OK) {
170 goto end;
171 }
172 } else {
173 text->processed_first_event = true;
174 }
175
176 notification = bt_notification_iterator_get_notification(it);
177 if (!notification) {
178 ret = BT_COMPONENT_STATUS_ERROR;
179 goto end;
180 }
181
182 ret = handle_notification(text, notification);
183 end:
184 bt_put(it);
185 bt_put(notification);
186 return ret;
187 }
188
189 static
190 enum bt_component_status add_params_to_map(struct bt_value *plugin_opt_map)
191 {
192 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
193 unsigned int i;
194
195 for (i = 0; i < BT_ARRAY_SIZE(plugin_options); i++) {
196 const char *key = plugin_options[i];
197 enum bt_value_status status;
198
199 status = bt_value_map_insert(plugin_opt_map, key, bt_value_null);
200 switch (status) {
201 case BT_VALUE_STATUS_OK:
202 break;
203 default:
204 ret = BT_COMPONENT_STATUS_ERROR;
205 goto end;
206 }
207 }
208 end:
209 return ret;
210 }
211
212 static
213 bool check_param_exists(const char *key, struct bt_value *object, void *data)
214 {
215 struct text_component *text = data;
216 struct bt_value *plugin_opt_map = text->plugin_opt_map;
217
218 if (!bt_value_map_get(plugin_opt_map, key)) {
219 fprintf(text->err,
220 "[warning] Parameter \"%s\" unknown to \"%s\" plugin\n",
221 key, PLUGIN_NAME);
222 }
223 return true;
224 }
225
226 static
227 enum bt_component_status apply_one_string(const char *key,
228 struct bt_value *params,
229 char **option)
230 {
231 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
232 struct bt_value *value = NULL;
233 enum bt_value_status status;
234 const char *str;
235
236 value = bt_value_map_get(params, key);
237 if (!value) {
238 goto end;
239 }
240 if (bt_value_is_null(value)) {
241 goto end;
242 }
243 status = bt_value_string_get(value, &str);
244 switch (status) {
245 case BT_VALUE_STATUS_OK:
246 break;
247 default:
248 ret = BT_COMPONENT_STATUS_ERROR;
249 goto end;
250 }
251 *option = g_strdup(str);
252 end:
253 bt_put(value);
254 return ret;
255 }
256
257 static
258 enum bt_component_status apply_one_bool(const char *key,
259 struct bt_value *params,
260 bool *option,
261 bool *found)
262 {
263 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
264 struct bt_value *value = NULL;
265 enum bt_value_status status;
266
267 value = bt_value_map_get(params, key);
268 if (!value) {
269 goto end;
270 }
271 status = bt_value_bool_get(value, option);
272 switch (status) {
273 case BT_VALUE_STATUS_OK:
274 break;
275 default:
276 ret = BT_COMPONENT_STATUS_ERROR;
277 goto end;
278 }
279 if (found) {
280 *found = true;
281 }
282 end:
283 bt_put(value);
284 return ret;
285 }
286
287 static
288 enum bt_component_status apply_params(struct text_component *text,
289 struct bt_value *params)
290 {
291 enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
292 enum bt_value_status status;
293 bool value, found;
294 char *str = NULL;
295
296 text->plugin_opt_map = bt_value_map_create();
297 if (!text->plugin_opt_map) {
298 ret = BT_COMPONENT_STATUS_ERROR;
299 goto end;
300 }
301 ret = add_params_to_map(text->plugin_opt_map);
302 if (ret != BT_COMPONENT_STATUS_OK) {
303 goto end;
304 }
305 /* Report unknown parameters. */
306 status = bt_value_map_foreach(params, check_param_exists, text);
307 switch (status) {
308 case BT_VALUE_STATUS_OK:
309 break;
310 default:
311 ret = BT_COMPONENT_STATUS_ERROR;
312 goto end;
313 }
314 /* Known parameters. */
315 ret = apply_one_string("output-path",
316 params,
317 &text->options.output_path);
318 if (ret != BT_COMPONENT_STATUS_OK) {
319 goto end;
320 }
321
322 ret = apply_one_string("debug-info-dir",
323 params,
324 &text->options.debug_info_dir);
325 if (ret != BT_COMPONENT_STATUS_OK) {
326 goto end;
327 }
328
329 ret = apply_one_string("debug-info-target-prefix",
330 params,
331 &text->options.debug_info_target_prefix);
332 if (ret != BT_COMPONENT_STATUS_OK) {
333 goto end;
334 }
335
336 value = false; /* Default. */
337 ret = apply_one_bool("debug-info-full-path", params, &value, NULL);
338 if (ret != BT_COMPONENT_STATUS_OK) {
339 goto end;
340 }
341 text->options.debug_info_full_path = value;
342
343 value = false; /* Default. */
344 ret = apply_one_bool("no-delta", params, &value, NULL);
345 if (ret != BT_COMPONENT_STATUS_OK) {
346 goto end;
347 }
348 text->options.print_delta_field = !value; /* Reverse logic. */
349
350 value = false; /* Default. */
351 ret = apply_one_bool("clock-cycles", params, &value, NULL);
352 if (ret != BT_COMPONENT_STATUS_OK) {
353 goto end;
354 }
355 text->options.print_timestamp_cycles = value;
356
357 value = false; /* Default. */
358 ret = apply_one_bool("clock-seconds", params, &value, NULL);
359 if (ret != BT_COMPONENT_STATUS_OK) {
360 goto end;
361 }
362 text->options.clock_seconds = value;
363
364 value = false; /* Default. */
365 ret = apply_one_bool("clock-date", params, &value, NULL);
366 if (ret != BT_COMPONENT_STATUS_OK) {
367 goto end;
368 }
369 text->options.clock_date = value;
370
371 value = false; /* Default. */
372 ret = apply_one_bool("clock-gmt", params, &value, NULL);
373 if (ret != BT_COMPONENT_STATUS_OK) {
374 goto end;
375 }
376 text->options.clock_gmt = value;
377
378 /* Names. */
379 ret = apply_one_string("name-default", params, &str);
380 if (ret != BT_COMPONENT_STATUS_OK) {
381 goto end;
382 }
383 if (!str) {
384 text->options.name_default = TEXT_DEFAULT_UNSET;
385 } else if (!strcmp(str, "show")) {
386 text->options.name_default = TEXT_DEFAULT_SHOW;
387 } else if (!strcmp(str, "hide")) {
388 text->options.name_default = TEXT_DEFAULT_HIDE;
389 } else {
390 ret = BT_COMPONENT_STATUS_ERROR;
391 goto end;
392 }
393 g_free(str);
394 str = NULL;
395
396 switch (text->options.name_default) {
397 case TEXT_DEFAULT_UNSET:
398 text->options.print_payload_field_names = true;
399 text->options.print_context_field_names = true;
400 text->options.print_header_field_names = false;
401 text->options.print_scope_field_names = false;
402 break;
403 case TEXT_DEFAULT_SHOW:
404 text->options.print_payload_field_names = true;
405 text->options.print_context_field_names = true;
406 text->options.print_header_field_names = true;
407 text->options.print_scope_field_names = true;
408 break;
409 case TEXT_DEFAULT_HIDE:
410 text->options.print_payload_field_names = false;
411 text->options.print_context_field_names = false;
412 text->options.print_header_field_names = false;
413 text->options.print_scope_field_names = false;
414 break;
415 default:
416 ret = BT_COMPONENT_STATUS_ERROR;
417 goto end;
418 }
419
420 value = false;
421 found = false;
422 ret = apply_one_bool("name-payload", params, &value, &found);
423 if (ret != BT_COMPONENT_STATUS_OK) {
424 goto end;
425 }
426 if (found) {
427 text->options.print_payload_field_names = value;
428 }
429
430 value = false;
431 found = false;
432 ret = apply_one_bool("name-context", params, &value, &found);
433 if (ret != BT_COMPONENT_STATUS_OK) {
434 goto end;
435 }
436 if (found) {
437 text->options.print_context_field_names = value;
438 }
439
440 value = false;
441 found = false;
442 ret = apply_one_bool("name-header", params, &value, &found);
443 if (ret != BT_COMPONENT_STATUS_OK) {
444 goto end;
445 }
446 if (found) {
447 text->options.print_header_field_names = value;
448 }
449
450 value = false;
451 found = false;
452 ret = apply_one_bool("name-scope", params, &value, &found);
453 if (ret != BT_COMPONENT_STATUS_OK) {
454 goto end;
455 }
456 if (found) {
457 text->options.print_scope_field_names = value;
458 }
459
460 /* Fields. */
461 ret = apply_one_string("field-default", params, &str);
462 if (ret != BT_COMPONENT_STATUS_OK) {
463 goto end;
464 }
465 if (!str) {
466 text->options.field_default = TEXT_DEFAULT_UNSET;
467 } else if (!strcmp(str, "show")) {
468 text->options.field_default = TEXT_DEFAULT_SHOW;
469 } else if (!strcmp(str, "hide")) {
470 text->options.field_default = TEXT_DEFAULT_HIDE;
471 } else {
472 ret = BT_COMPONENT_STATUS_ERROR;
473 goto end;
474 }
475 g_free(str);
476 str = NULL;
477
478 switch (text->options.field_default) {
479 case TEXT_DEFAULT_UNSET:
480 text->options.print_trace_field = false;
481 text->options.print_trace_hostname_field = true;
482 text->options.print_trace_domain_field = false;
483 text->options.print_trace_procname_field = true;
484 text->options.print_trace_vpid_field = true;
485 text->options.print_loglevel_field = false;
486 text->options.print_emf_field = false;
487 text->options.print_emf_field = false;
488 text->options.print_callsite_field = false;
489 break;
490 case TEXT_DEFAULT_SHOW:
491 text->options.print_trace_field = true;
492 text->options.print_trace_hostname_field = true;
493 text->options.print_trace_domain_field = true;
494 text->options.print_trace_procname_field = true;
495 text->options.print_trace_vpid_field = true;
496 text->options.print_loglevel_field = true;
497 text->options.print_emf_field = true;
498 text->options.print_emf_field = true;
499 text->options.print_callsite_field = true;
500 break;
501 case TEXT_DEFAULT_HIDE:
502 text->options.print_trace_field = false;
503 text->options.print_trace_hostname_field = false;
504 text->options.print_trace_domain_field = false;
505 text->options.print_trace_procname_field = false;
506 text->options.print_trace_vpid_field = false;
507 text->options.print_loglevel_field = false;
508 text->options.print_emf_field = false;
509 text->options.print_emf_field = false;
510 text->options.print_callsite_field = false;
511 break;
512 default:
513 ret = BT_COMPONENT_STATUS_ERROR;
514 goto end;
515 }
516
517 value = false;
518 found = false;
519 ret = apply_one_bool("field-trace", params, &value, &found);
520 if (ret != BT_COMPONENT_STATUS_OK) {
521 goto end;
522 }
523 if (found) {
524 text->options.print_trace_field = value;
525 }
526
527 value = false;
528 found = false;
529 ret = apply_one_bool("field-trace:hostname", params, &value, &found);
530 if (ret != BT_COMPONENT_STATUS_OK) {
531 goto end;
532 }
533 if (found) {
534 text->options.print_trace_hostname_field = value;
535 }
536
537 value = false;
538 found = false;
539 ret = apply_one_bool("field-trace:domain", params, &value, &found);
540 if (ret != BT_COMPONENT_STATUS_OK) {
541 goto end;
542 }
543 if (found) {
544 text->options.print_trace_domain_field = value;
545 }
546
547 value = false;
548 found = false;
549 ret = apply_one_bool("field-trace:procname", params, &value, &found);
550 if (ret != BT_COMPONENT_STATUS_OK) {
551 goto end;
552 }
553 if (found) {
554 text->options.print_trace_procname_field = value;
555 }
556
557 value = false;
558 found = false;
559 ret = apply_one_bool("field-trace:vpid", params, &value, &found);
560 if (ret != BT_COMPONENT_STATUS_OK) {
561 goto end;
562 }
563 if (found) {
564 text->options.print_trace_vpid_field = value;
565 }
566
567 value = false;
568 found = false;
569 ret = apply_one_bool("field-loglevel", params, &value, &found);
570 if (ret != BT_COMPONENT_STATUS_OK) {
571 goto end;
572 }
573 if (found) {
574 text->options.print_loglevel_field = value;
575 }
576
577 value = false;
578 found = false;
579 ret = apply_one_bool("field-emf", params, &value, &found);
580 if (ret != BT_COMPONENT_STATUS_OK) {
581 goto end;
582 }
583 if (found) {
584 text->options.print_emf_field = value;
585 }
586
587 value = false;
588 found = false;
589 ret = apply_one_bool("field-emf", params, &value, &found);
590 if (ret != BT_COMPONENT_STATUS_OK) {
591 goto end;
592 }
593 if (found) {
594 text->options.print_emf_field = value;
595 }
596
597 value = false;
598 found = false;
599 ret = apply_one_bool("field-callsite", params, &value, &found);
600 if (ret != BT_COMPONENT_STATUS_OK) {
601 goto end;
602 }
603 if (found) {
604 text->options.print_callsite_field = value;
605 }
606 end:
607 bt_put(text->plugin_opt_map);
608 text->plugin_opt_map = NULL;
609 g_free(str);
610 return ret;
611 }
612
613 static
614 enum bt_component_status text_component_init(
615 struct bt_component *component, struct bt_value *params)
616 {
617 enum bt_component_status ret;
618 struct text_component *text = create_text();
619
620 if (!text) {
621 ret = BT_COMPONENT_STATUS_NOMEM;
622 goto end;
623 }
624
625 text->out = stdout;
626 text->err = stderr;
627
628 ret = apply_params(text, params);
629 if (ret != BT_COMPONENT_STATUS_OK) {
630 goto error;
631 }
632
633 ret = bt_component_set_destroy_cb(component,
634 destroy_text);
635 if (ret != BT_COMPONENT_STATUS_OK) {
636 goto error;
637 }
638
639 ret = bt_component_set_private_data(component, text);
640 if (ret != BT_COMPONENT_STATUS_OK) {
641 goto error;
642 }
643
644 ret = bt_component_sink_set_consume_cb(component,
645 run);
646 if (ret != BT_COMPONENT_STATUS_OK) {
647 goto error;
648 }
649 end:
650 return ret;
651 error:
652 destroy_text_data(text);
653 return ret;
654 }
655
656 /* Initialize plug-in entry points. */
657 BT_PLUGIN_NAME("text");
658 BT_PLUGIN_DESCRIPTION("Babeltrace text output plug-in.");
659 BT_PLUGIN_AUTHOR("Jérémie Galarneau");
660 BT_PLUGIN_LICENSE("MIT");
661
662 BT_PLUGIN_COMPONENT_CLASSES_BEGIN
663 BT_PLUGIN_SINK_COMPONENT_CLASS_ENTRY(PLUGIN_NAME,
664 "Formats CTF-IR to text. Formerly known as ctf-text.",
665 text_component_init)
666 BT_PLUGIN_COMPONENT_CLASSES_END
This page took 0.042761 seconds and 5 git commands to generate.