4 * Babeltrace CTF Text Output Plugin
6 * Copyright 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com>
7 * Copyright 2016 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
9 * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
11 * Permission is hereby granted, free of charge, to any person obtaining a copy
12 * of this software and associated documentation files (the "Software"), to deal
13 * in the Software without restriction, including without limitation the rights
14 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 * copies of the Software, and to permit persons to whom the Software is
16 * furnished to do so, subject to the following conditions:
18 * The above copyright notice and this permission notice shall be included in
19 * all copies or substantial portions of the Software.
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30 #include <babeltrace/plugin/plugin-dev.h>
31 #include <babeltrace/component/component.h>
32 #include <babeltrace/component/component-sink.h>
33 #include <babeltrace/component/notification/notification.h>
34 #include <babeltrace/component/notification/iterator.h>
35 #include <babeltrace/component/notification/event.h>
36 #include <babeltrace/values.h>
37 #include <babeltrace/compiler.h>
38 #include <babeltrace/common-internal.h>
39 #include <plugins-common.h>
46 const char *plugin_options
[] = {
50 "debug-info-target-prefix",
51 "debug-info-full-path",
58 "name-default", /* show/hide */
63 "field-default", /* show/hide */
65 "field-trace:hostname",
67 "field-trace:procname",
74 void destroy_text_data(struct text_component
*text
)
76 (void) g_string_free(text
->string
, TRUE
);
77 g_free(text
->options
.output_path
);
78 g_free(text
->options
.debug_info_dir
);
79 g_free(text
->options
.debug_info_target_prefix
);
84 struct text_component
*create_text(void)
86 struct text_component
*text
;
88 text
= g_new0(struct text_component
, 1);
92 text
->string
= g_string_new("");
105 void destroy_text(struct bt_component
*component
)
107 void *data
= bt_component_get_private_data(component
);
109 destroy_text_data(data
);
113 enum bt_component_status
handle_notification(struct text_component
*text
,
114 struct bt_notification
*notification
)
116 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
119 ret
= BT_COMPONENT_STATUS_ERROR
;
123 switch (bt_notification_get_type(notification
)) {
124 case BT_NOTIFICATION_TYPE_PACKET_BEGIN
:
127 case BT_NOTIFICATION_TYPE_PACKET_END
:
130 case BT_NOTIFICATION_TYPE_EVENT
:
132 struct bt_ctf_event
*event
= bt_notification_event_get_event(
136 ret
= BT_COMPONENT_STATUS_ERROR
;
139 ret
= text_print_event(text
, event
);
141 if (ret
!= BT_COMPONENT_STATUS_OK
) {
146 case BT_NOTIFICATION_TYPE_STREAM_END
:
150 puts("Unhandled notification type");
157 enum bt_component_status
run(struct bt_component
*component
)
159 enum bt_component_status ret
;
160 struct bt_notification
*notification
= NULL
;
161 struct bt_notification_iterator
*it
;
162 struct text_component
*text
= bt_component_get_private_data(component
);
164 ret
= bt_component_sink_get_input_iterator(component
, 0, &it
);
165 if (ret
!= BT_COMPONENT_STATUS_OK
) {
169 if (likely(text
->processed_first_event
)) {
170 enum bt_notification_iterator_status it_ret
;
172 it_ret
= bt_notification_iterator_next(it
);
174 case BT_NOTIFICATION_ITERATOR_STATUS_ERROR
:
175 ret
= BT_COMPONENT_STATUS_ERROR
;
177 case BT_NOTIFICATION_ITERATOR_STATUS_END
:
178 ret
= BT_COMPONENT_STATUS_END
;
184 notification
= bt_notification_iterator_get_notification(it
);
186 ret
= BT_COMPONENT_STATUS_ERROR
;
190 ret
= handle_notification(text
, notification
);
191 text
->processed_first_event
= true;
194 bt_put(notification
);
199 enum bt_component_status
add_params_to_map(struct bt_value
*plugin_opt_map
)
201 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
204 for (i
= 0; i
< BT_ARRAY_SIZE(plugin_options
); i
++) {
205 const char *key
= plugin_options
[i
];
206 enum bt_value_status status
;
208 status
= bt_value_map_insert(plugin_opt_map
, key
, bt_value_null
);
210 case BT_VALUE_STATUS_OK
:
213 ret
= BT_COMPONENT_STATUS_ERROR
;
222 bool check_param_exists(const char *key
, struct bt_value
*object
, void *data
)
224 struct text_component
*text
= data
;
225 struct bt_value
*plugin_opt_map
= text
->plugin_opt_map
;
227 if (!bt_value_map_get(plugin_opt_map
, key
)) {
229 "[warning] Parameter \"%s\" unknown to \"text\" plugin\n", key
);
235 enum bt_component_status
apply_one_string(const char *key
,
236 struct bt_value
*params
,
239 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
240 struct bt_value
*value
= NULL
;
241 enum bt_value_status status
;
244 value
= bt_value_map_get(params
, key
);
248 if (bt_value_is_null(value
)) {
251 status
= bt_value_string_get(value
, &str
);
253 case BT_VALUE_STATUS_OK
:
256 ret
= BT_COMPONENT_STATUS_ERROR
;
259 *option
= g_strdup(str
);
266 enum bt_component_status
apply_one_bool(const char *key
,
267 struct bt_value
*params
,
271 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
272 struct bt_value
*value
= NULL
;
273 enum bt_value_status status
;
275 value
= bt_value_map_get(params
, key
);
279 status
= bt_value_bool_get(value
, option
);
281 case BT_VALUE_STATUS_OK
:
284 ret
= BT_COMPONENT_STATUS_ERROR
;
296 void warn_wrong_color_param(struct text_component
*text
)
299 "[warning] Accepted values for the \"color\" parameter are:\n \"always\", \"auto\", \"never\"\n");
303 enum bt_component_status
apply_params(struct text_component
*text
,
304 struct bt_value
*params
)
306 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
307 enum bt_value_status status
;
311 text
->plugin_opt_map
= bt_value_map_create();
312 if (!text
->plugin_opt_map
) {
313 ret
= BT_COMPONENT_STATUS_ERROR
;
316 ret
= add_params_to_map(text
->plugin_opt_map
);
317 if (ret
!= BT_COMPONENT_STATUS_OK
) {
320 /* Report unknown parameters. */
321 status
= bt_value_map_foreach(params
, check_param_exists
, text
);
323 case BT_VALUE_STATUS_OK
:
326 ret
= BT_COMPONENT_STATUS_ERROR
;
329 /* Known parameters. */
330 text
->options
.color
= TEXT_COLOR_OPT_AUTO
;
331 if (bt_value_map_has_key(params
, "color")) {
332 struct bt_value
*color_value
;
335 color_value
= bt_value_map_get(params
, "color");
340 ret
= bt_value_string_get(color_value
, &color
);
342 warn_wrong_color_param(text
);
344 if (strcmp(color
, "never") == 0) {
345 text
->options
.color
= TEXT_COLOR_OPT_NEVER
;
346 } else if (strcmp(color
, "auto") == 0) {
347 text
->options
.color
= TEXT_COLOR_OPT_AUTO
;
348 } else if (strcmp(color
, "always") == 0) {
349 text
->options
.color
= TEXT_COLOR_OPT_ALWAYS
;
351 warn_wrong_color_param(text
);
358 ret
= apply_one_string("output-path",
360 &text
->options
.output_path
);
361 if (ret
!= BT_COMPONENT_STATUS_OK
) {
365 ret
= apply_one_string("debug-info-dir",
367 &text
->options
.debug_info_dir
);
368 if (ret
!= BT_COMPONENT_STATUS_OK
) {
372 ret
= apply_one_string("debug-info-target-prefix",
374 &text
->options
.debug_info_target_prefix
);
375 if (ret
!= BT_COMPONENT_STATUS_OK
) {
379 value
= false; /* Default. */
380 ret
= apply_one_bool("debug-info-full-path", params
, &value
, NULL
);
381 if (ret
!= BT_COMPONENT_STATUS_OK
) {
384 text
->options
.debug_info_full_path
= value
;
386 value
= false; /* Default. */
387 ret
= apply_one_bool("no-delta", params
, &value
, NULL
);
388 if (ret
!= BT_COMPONENT_STATUS_OK
) {
391 text
->options
.print_delta_field
= !value
; /* Reverse logic. */
393 value
= false; /* Default. */
394 ret
= apply_one_bool("clock-cycles", params
, &value
, NULL
);
395 if (ret
!= BT_COMPONENT_STATUS_OK
) {
398 text
->options
.print_timestamp_cycles
= value
;
400 value
= false; /* Default. */
401 ret
= apply_one_bool("clock-seconds", params
, &value
, NULL
);
402 if (ret
!= BT_COMPONENT_STATUS_OK
) {
405 text
->options
.clock_seconds
= value
;
407 value
= false; /* Default. */
408 ret
= apply_one_bool("clock-date", params
, &value
, NULL
);
409 if (ret
!= BT_COMPONENT_STATUS_OK
) {
412 text
->options
.clock_date
= value
;
414 value
= false; /* Default. */
415 ret
= apply_one_bool("clock-gmt", params
, &value
, NULL
);
416 if (ret
!= BT_COMPONENT_STATUS_OK
) {
419 text
->options
.clock_gmt
= value
;
421 value
= false; /* Default. */
422 ret
= apply_one_bool("verbose", params
, &value
, NULL
);
423 if (ret
!= BT_COMPONENT_STATUS_OK
) {
426 text
->options
.verbose
= value
;
429 ret
= apply_one_string("name-default", params
, &str
);
430 if (ret
!= BT_COMPONENT_STATUS_OK
) {
434 text
->options
.name_default
= TEXT_DEFAULT_UNSET
;
435 } else if (!strcmp(str
, "show")) {
436 text
->options
.name_default
= TEXT_DEFAULT_SHOW
;
437 } else if (!strcmp(str
, "hide")) {
438 text
->options
.name_default
= TEXT_DEFAULT_HIDE
;
440 ret
= BT_COMPONENT_STATUS_ERROR
;
446 switch (text
->options
.name_default
) {
447 case TEXT_DEFAULT_UNSET
:
448 text
->options
.print_payload_field_names
= true;
449 text
->options
.print_context_field_names
= true;
450 text
->options
.print_header_field_names
= false;
451 text
->options
.print_scope_field_names
= false;
453 case TEXT_DEFAULT_SHOW
:
454 text
->options
.print_payload_field_names
= true;
455 text
->options
.print_context_field_names
= true;
456 text
->options
.print_header_field_names
= true;
457 text
->options
.print_scope_field_names
= true;
459 case TEXT_DEFAULT_HIDE
:
460 text
->options
.print_payload_field_names
= false;
461 text
->options
.print_context_field_names
= false;
462 text
->options
.print_header_field_names
= false;
463 text
->options
.print_scope_field_names
= false;
466 ret
= BT_COMPONENT_STATUS_ERROR
;
472 ret
= apply_one_bool("name-payload", params
, &value
, &found
);
473 if (ret
!= BT_COMPONENT_STATUS_OK
) {
477 text
->options
.print_payload_field_names
= value
;
482 ret
= apply_one_bool("name-context", params
, &value
, &found
);
483 if (ret
!= BT_COMPONENT_STATUS_OK
) {
487 text
->options
.print_context_field_names
= value
;
492 ret
= apply_one_bool("name-header", params
, &value
, &found
);
493 if (ret
!= BT_COMPONENT_STATUS_OK
) {
497 text
->options
.print_header_field_names
= value
;
502 ret
= apply_one_bool("name-scope", params
, &value
, &found
);
503 if (ret
!= BT_COMPONENT_STATUS_OK
) {
507 text
->options
.print_scope_field_names
= value
;
511 ret
= apply_one_string("field-default", params
, &str
);
512 if (ret
!= BT_COMPONENT_STATUS_OK
) {
516 text
->options
.field_default
= TEXT_DEFAULT_UNSET
;
517 } else if (!strcmp(str
, "show")) {
518 text
->options
.field_default
= TEXT_DEFAULT_SHOW
;
519 } else if (!strcmp(str
, "hide")) {
520 text
->options
.field_default
= TEXT_DEFAULT_HIDE
;
522 ret
= BT_COMPONENT_STATUS_ERROR
;
528 switch (text
->options
.field_default
) {
529 case TEXT_DEFAULT_UNSET
:
530 text
->options
.print_trace_field
= false;
531 text
->options
.print_trace_hostname_field
= true;
532 text
->options
.print_trace_domain_field
= false;
533 text
->options
.print_trace_procname_field
= true;
534 text
->options
.print_trace_vpid_field
= true;
535 text
->options
.print_loglevel_field
= false;
536 text
->options
.print_emf_field
= false;
537 text
->options
.print_emf_field
= false;
539 case TEXT_DEFAULT_SHOW
:
540 text
->options
.print_trace_field
= true;
541 text
->options
.print_trace_hostname_field
= true;
542 text
->options
.print_trace_domain_field
= true;
543 text
->options
.print_trace_procname_field
= true;
544 text
->options
.print_trace_vpid_field
= true;
545 text
->options
.print_loglevel_field
= true;
546 text
->options
.print_emf_field
= true;
547 text
->options
.print_emf_field
= true;
549 case TEXT_DEFAULT_HIDE
:
550 text
->options
.print_trace_field
= false;
551 text
->options
.print_trace_hostname_field
= false;
552 text
->options
.print_trace_domain_field
= false;
553 text
->options
.print_trace_procname_field
= false;
554 text
->options
.print_trace_vpid_field
= false;
555 text
->options
.print_loglevel_field
= false;
556 text
->options
.print_emf_field
= false;
557 text
->options
.print_emf_field
= false;
560 ret
= BT_COMPONENT_STATUS_ERROR
;
566 ret
= apply_one_bool("field-trace", params
, &value
, &found
);
567 if (ret
!= BT_COMPONENT_STATUS_OK
) {
571 text
->options
.print_trace_field
= value
;
576 ret
= apply_one_bool("field-trace:hostname", params
, &value
, &found
);
577 if (ret
!= BT_COMPONENT_STATUS_OK
) {
581 text
->options
.print_trace_hostname_field
= value
;
586 ret
= apply_one_bool("field-trace:domain", params
, &value
, &found
);
587 if (ret
!= BT_COMPONENT_STATUS_OK
) {
591 text
->options
.print_trace_domain_field
= value
;
596 ret
= apply_one_bool("field-trace:procname", params
, &value
, &found
);
597 if (ret
!= BT_COMPONENT_STATUS_OK
) {
601 text
->options
.print_trace_procname_field
= value
;
606 ret
= apply_one_bool("field-trace:vpid", params
, &value
, &found
);
607 if (ret
!= BT_COMPONENT_STATUS_OK
) {
611 text
->options
.print_trace_vpid_field
= value
;
616 ret
= apply_one_bool("field-loglevel", params
, &value
, &found
);
617 if (ret
!= BT_COMPONENT_STATUS_OK
) {
621 text
->options
.print_loglevel_field
= value
;
626 ret
= apply_one_bool("field-emf", params
, &value
, &found
);
627 if (ret
!= BT_COMPONENT_STATUS_OK
) {
631 text
->options
.print_emf_field
= value
;
636 ret
= apply_one_bool("field-emf", params
, &value
, &found
);
637 if (ret
!= BT_COMPONENT_STATUS_OK
) {
641 text
->options
.print_emf_field
= value
;
645 bt_put(text
->plugin_opt_map
);
646 text
->plugin_opt_map
= NULL
;
652 void set_use_colors(struct text_component
*text
)
654 switch (text
->options
.color
) {
655 case TEXT_COLOR_OPT_ALWAYS
:
656 text
->use_colors
= true;
658 case TEXT_COLOR_OPT_AUTO
:
659 text
->use_colors
= text
->out
== stdout
&&
660 bt_common_colors_supported();
662 case TEXT_COLOR_OPT_NEVER
:
663 text
->use_colors
= false;
669 enum bt_component_status
text_component_init(
670 struct bt_component
*component
, struct bt_value
*params
,
671 UNUSED_VAR
void *init_method_data
)
673 enum bt_component_status ret
;
674 struct text_component
*text
= create_text();
677 ret
= BT_COMPONENT_STATUS_NOMEM
;
684 text
->delta_cycles
= -1ULL;
685 text
->last_cycles_timestamp
= -1ULL;
687 text
->delta_real_timestamp
= -1ULL;
688 text
->last_real_timestamp
= -1ULL;
690 ret
= apply_params(text
, params
);
691 if (ret
!= BT_COMPONENT_STATUS_OK
) {
695 set_use_colors(text
);
697 ret
= bt_component_set_private_data(component
, text
);
698 if (ret
!= BT_COMPONENT_STATUS_OK
) {
704 destroy_text_data(text
);
708 /* Initialize plug-in entry points. */
710 BT_PLUGIN_DESCRIPTION("Babeltrace text output plug-in.");
711 BT_PLUGIN_AUTHOR("Jérémie Galarneau");
712 BT_PLUGIN_LICENSE("MIT");
713 BT_PLUGIN_SINK_COMPONENT_CLASS(text
, run
);
714 BT_PLUGIN_SINK_COMPONENT_CLASS_INIT_METHOD(text
, text_component_init
);
715 BT_PLUGIN_SINK_COMPONENT_CLASS_DESTROY_METHOD(text
, destroy_text
);
716 BT_PLUGIN_SINK_COMPONENT_CLASS_DESCRIPTION(text
,
717 "Formats CTF-IR to text. Formerly known as ctf-text.");