4 * Babeltrace CTF Text Output Plugin
6 * Copyright 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com>
8 * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
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:
17 * The above copyright notice and this permission notice shall be included in
18 * all copies or substantial portions of the Software.
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
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>
42 #define PLUGIN_NAME "text"
45 const char *plugin_options
[] = {
48 "debug-info-target-prefix",
49 "debug-info-full-path",
55 "name-default", /* show/hide */
60 "field-default", /* show/hide */
62 "field-trace:hostname",
64 "field-trace:procname",
71 void destroy_text_data(struct text_component
*text
)
73 (void) g_string_free(text
->string
, TRUE
);
74 g_free(text
->options
.output_path
);
75 g_free(text
->options
.debug_info_dir
);
76 g_free(text
->options
.debug_info_target_prefix
);
81 struct text_component
*create_text(void)
83 struct text_component
*text
;
85 text
= g_new0(struct text_component
, 1);
89 text
->string
= g_string_new("");
102 void destroy_text(struct bt_component
*component
)
104 void *data
= bt_component_get_private_data(component
);
106 destroy_text_data(data
);
110 enum bt_component_status
handle_notification(struct text_component
*text
,
111 struct bt_notification
*notification
)
113 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
116 ret
= BT_COMPONENT_STATUS_ERROR
;
120 switch (bt_notification_get_type(notification
)) {
121 case BT_NOTIFICATION_TYPE_PACKET_START
:
124 case BT_NOTIFICATION_TYPE_PACKET_END
:
127 case BT_NOTIFICATION_TYPE_EVENT
:
129 struct bt_ctf_event
*event
= bt_notification_event_get_event(
133 ret
= BT_COMPONENT_STATUS_ERROR
;
136 ret
= text_print_event(text
, event
);
138 if (ret
!= BT_COMPONENT_STATUS_OK
) {
143 case BT_NOTIFICATION_TYPE_STREAM_END
:
147 puts("Unhandled notification type");
154 enum bt_component_status
run(struct bt_component
*component
)
156 enum bt_component_status ret
;
157 struct bt_notification
*notification
= NULL
;
158 struct bt_notification_iterator
*it
;
159 struct text_component
*text
= bt_component_get_private_data(component
);
161 ret
= bt_component_sink_get_input_iterator(component
, 0, &it
);
162 if (ret
!= BT_COMPONENT_STATUS_OK
) {
166 if (!text
->processed_first_event
) {
167 ret
= bt_notification_iterator_next(it
);
168 if (ret
!= BT_COMPONENT_STATUS_OK
) {
172 text
->processed_first_event
= true;
175 notification
= bt_notification_iterator_get_notification(it
);
177 ret
= BT_COMPONENT_STATUS_ERROR
;
181 ret
= handle_notification(text
, notification
);
184 bt_put(notification
);
189 enum bt_component_status
add_params_to_map(struct bt_value
*plugin_opt_map
)
191 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
194 for (i
= 0; i
< BT_ARRAY_SIZE(plugin_options
); i
++) {
195 const char *key
= plugin_options
[i
];
196 enum bt_value_status status
;
198 status
= bt_value_map_insert(plugin_opt_map
, key
, bt_value_null
);
200 case BT_VALUE_STATUS_OK
:
203 ret
= BT_COMPONENT_STATUS_ERROR
;
212 bool check_param_exists(const char *key
, struct bt_value
*object
, void *data
)
214 struct text_component
*text
= data
;
215 struct bt_value
*plugin_opt_map
= text
->plugin_opt_map
;
217 if (!bt_value_map_get(plugin_opt_map
, key
)) {
219 "[warning] Parameter \"%s\" unknown to \"%s\" plugin\n",
226 enum bt_component_status
apply_one_string(const char *key
,
227 struct bt_value
*params
,
230 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
231 struct bt_value
*value
= NULL
;
232 enum bt_value_status status
;
235 value
= bt_value_map_get(params
, key
);
239 if (bt_value_is_null(value
)) {
242 status
= bt_value_string_get(value
, &str
);
244 case BT_VALUE_STATUS_OK
:
247 ret
= BT_COMPONENT_STATUS_ERROR
;
250 *option
= g_strdup(str
);
257 enum bt_component_status
apply_one_bool(const char *key
,
258 struct bt_value
*params
,
262 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
263 struct bt_value
*value
= NULL
;
264 enum bt_value_status status
;
266 value
= bt_value_map_get(params
, key
);
270 status
= bt_value_bool_get(value
, option
);
272 case BT_VALUE_STATUS_OK
:
275 ret
= BT_COMPONENT_STATUS_ERROR
;
287 enum bt_component_status
apply_params(struct text_component
*text
,
288 struct bt_value
*params
)
290 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
291 enum bt_value_status status
;
295 text
->plugin_opt_map
= bt_value_map_create();
296 if (!text
->plugin_opt_map
) {
297 ret
= BT_COMPONENT_STATUS_ERROR
;
300 ret
= add_params_to_map(text
->plugin_opt_map
);
301 if (ret
!= BT_COMPONENT_STATUS_OK
) {
304 /* Report unknown parameters. */
305 status
= bt_value_map_foreach(params
, check_param_exists
, text
);
307 case BT_VALUE_STATUS_OK
:
310 ret
= BT_COMPONENT_STATUS_ERROR
;
313 /* Known parameters. */
314 ret
= apply_one_string("output-path",
316 &text
->options
.output_path
);
317 if (ret
!= BT_COMPONENT_STATUS_OK
) {
321 ret
= apply_one_string("debug-info-dir",
323 &text
->options
.debug_info_dir
);
324 if (ret
!= BT_COMPONENT_STATUS_OK
) {
328 ret
= apply_one_string("debug-info-target-prefix",
330 &text
->options
.debug_info_target_prefix
);
331 if (ret
!= BT_COMPONENT_STATUS_OK
) {
335 value
= false; /* Default. */
336 ret
= apply_one_bool("debug-info-full-path", params
, &value
, NULL
);
337 if (ret
!= BT_COMPONENT_STATUS_OK
) {
340 text
->options
.debug_info_full_path
= value
;
342 value
= false; /* Default. */
343 ret
= apply_one_bool("no-delta", params
, &value
, NULL
);
344 if (ret
!= BT_COMPONENT_STATUS_OK
) {
347 text
->options
.print_delta_field
= !value
; /* Reverse logic. */
349 value
= false; /* Default. */
350 ret
= apply_one_bool("clock-cycles", params
, &value
, NULL
);
351 if (ret
!= BT_COMPONENT_STATUS_OK
) {
354 text
->options
.print_timestamp_cycles
= value
;
356 value
= false; /* Default. */
357 ret
= apply_one_bool("clock-seconds", params
, &value
, NULL
);
358 if (ret
!= BT_COMPONENT_STATUS_OK
) {
361 text
->options
.clock_seconds
= value
;
363 value
= false; /* Default. */
364 ret
= apply_one_bool("clock-date", params
, &value
, NULL
);
365 if (ret
!= BT_COMPONENT_STATUS_OK
) {
368 text
->options
.clock_date
= value
;
370 value
= false; /* Default. */
371 ret
= apply_one_bool("clock-gmt", params
, &value
, NULL
);
372 if (ret
!= BT_COMPONENT_STATUS_OK
) {
375 text
->options
.clock_gmt
= value
;
378 ret
= apply_one_string("name-default", params
, &str
);
379 if (ret
!= BT_COMPONENT_STATUS_OK
) {
383 text
->options
.name_default
= TEXT_DEFAULT_UNSET
;
384 } else if (!strcmp(str
, "show")) {
385 text
->options
.name_default
= TEXT_DEFAULT_SHOW
;
386 } else if (!strcmp(str
, "hide")) {
387 text
->options
.name_default
= TEXT_DEFAULT_HIDE
;
389 ret
= BT_COMPONENT_STATUS_ERROR
;
395 switch (text
->options
.name_default
) {
396 case TEXT_DEFAULT_UNSET
:
397 text
->options
.print_payload_field_names
= true;
398 text
->options
.print_context_field_names
= true;
399 text
->options
.print_header_field_names
= false;
400 text
->options
.print_scope_field_names
= false;
402 case TEXT_DEFAULT_SHOW
:
403 text
->options
.print_payload_field_names
= true;
404 text
->options
.print_context_field_names
= true;
405 text
->options
.print_header_field_names
= true;
406 text
->options
.print_scope_field_names
= true;
408 case TEXT_DEFAULT_HIDE
:
409 text
->options
.print_payload_field_names
= false;
410 text
->options
.print_context_field_names
= false;
411 text
->options
.print_header_field_names
= false;
412 text
->options
.print_scope_field_names
= false;
415 ret
= BT_COMPONENT_STATUS_ERROR
;
421 ret
= apply_one_bool("name-payload", params
, &value
, &found
);
422 if (ret
!= BT_COMPONENT_STATUS_OK
) {
426 text
->options
.print_payload_field_names
= value
;
431 ret
= apply_one_bool("name-context", params
, &value
, &found
);
432 if (ret
!= BT_COMPONENT_STATUS_OK
) {
436 text
->options
.print_context_field_names
= value
;
441 ret
= apply_one_bool("name-header", params
, &value
, &found
);
442 if (ret
!= BT_COMPONENT_STATUS_OK
) {
446 text
->options
.print_header_field_names
= value
;
451 ret
= apply_one_bool("name-scope", params
, &value
, &found
);
452 if (ret
!= BT_COMPONENT_STATUS_OK
) {
456 text
->options
.print_scope_field_names
= value
;
460 ret
= apply_one_string("field-default", params
, &str
);
461 if (ret
!= BT_COMPONENT_STATUS_OK
) {
465 text
->options
.field_default
= TEXT_DEFAULT_UNSET
;
466 } else if (!strcmp(str
, "show")) {
467 text
->options
.field_default
= TEXT_DEFAULT_SHOW
;
468 } else if (!strcmp(str
, "hide")) {
469 text
->options
.field_default
= TEXT_DEFAULT_HIDE
;
471 ret
= BT_COMPONENT_STATUS_ERROR
;
477 switch (text
->options
.field_default
) {
478 case TEXT_DEFAULT_UNSET
:
479 text
->options
.print_trace_field
= false;
480 text
->options
.print_trace_hostname_field
= true;
481 text
->options
.print_trace_domain_field
= false;
482 text
->options
.print_trace_procname_field
= true;
483 text
->options
.print_trace_vpid_field
= true;
484 text
->options
.print_loglevel_field
= false;
485 text
->options
.print_emf_field
= false;
486 text
->options
.print_emf_field
= false;
488 case TEXT_DEFAULT_SHOW
:
489 text
->options
.print_trace_field
= true;
490 text
->options
.print_trace_hostname_field
= true;
491 text
->options
.print_trace_domain_field
= true;
492 text
->options
.print_trace_procname_field
= true;
493 text
->options
.print_trace_vpid_field
= true;
494 text
->options
.print_loglevel_field
= true;
495 text
->options
.print_emf_field
= true;
496 text
->options
.print_emf_field
= true;
498 case TEXT_DEFAULT_HIDE
:
499 text
->options
.print_trace_field
= false;
500 text
->options
.print_trace_hostname_field
= false;
501 text
->options
.print_trace_domain_field
= false;
502 text
->options
.print_trace_procname_field
= false;
503 text
->options
.print_trace_vpid_field
= false;
504 text
->options
.print_loglevel_field
= false;
505 text
->options
.print_emf_field
= false;
506 text
->options
.print_emf_field
= false;
509 ret
= BT_COMPONENT_STATUS_ERROR
;
515 ret
= apply_one_bool("field-trace", params
, &value
, &found
);
516 if (ret
!= BT_COMPONENT_STATUS_OK
) {
520 text
->options
.print_trace_field
= value
;
525 ret
= apply_one_bool("field-trace:hostname", params
, &value
, &found
);
526 if (ret
!= BT_COMPONENT_STATUS_OK
) {
530 text
->options
.print_trace_hostname_field
= value
;
535 ret
= apply_one_bool("field-trace:domain", params
, &value
, &found
);
536 if (ret
!= BT_COMPONENT_STATUS_OK
) {
540 text
->options
.print_trace_domain_field
= value
;
545 ret
= apply_one_bool("field-trace:procname", params
, &value
, &found
);
546 if (ret
!= BT_COMPONENT_STATUS_OK
) {
550 text
->options
.print_trace_procname_field
= value
;
555 ret
= apply_one_bool("field-trace:vpid", params
, &value
, &found
);
556 if (ret
!= BT_COMPONENT_STATUS_OK
) {
560 text
->options
.print_trace_vpid_field
= value
;
565 ret
= apply_one_bool("field-loglevel", params
, &value
, &found
);
566 if (ret
!= BT_COMPONENT_STATUS_OK
) {
570 text
->options
.print_loglevel_field
= value
;
575 ret
= apply_one_bool("field-emf", params
, &value
, &found
);
576 if (ret
!= BT_COMPONENT_STATUS_OK
) {
580 text
->options
.print_emf_field
= value
;
585 ret
= apply_one_bool("field-emf", params
, &value
, &found
);
586 if (ret
!= BT_COMPONENT_STATUS_OK
) {
590 text
->options
.print_emf_field
= value
;
594 bt_put(text
->plugin_opt_map
);
595 text
->plugin_opt_map
= NULL
;
601 enum bt_component_status
text_component_init(
602 struct bt_component
*component
, struct bt_value
*params
)
604 enum bt_component_status ret
;
605 struct text_component
*text
= create_text();
608 ret
= BT_COMPONENT_STATUS_NOMEM
;
615 ret
= apply_params(text
, params
);
616 if (ret
!= BT_COMPONENT_STATUS_OK
) {
620 ret
= bt_component_set_destroy_cb(component
,
622 if (ret
!= BT_COMPONENT_STATUS_OK
) {
626 ret
= bt_component_set_private_data(component
, text
);
627 if (ret
!= BT_COMPONENT_STATUS_OK
) {
631 ret
= bt_component_sink_set_consume_cb(component
,
633 if (ret
!= BT_COMPONENT_STATUS_OK
) {
639 destroy_text_data(text
);
643 /* Initialize plug-in entry points. */
644 BT_PLUGIN_NAME("text");
645 BT_PLUGIN_DESCRIPTION("Babeltrace text output plug-in.");
646 BT_PLUGIN_AUTHOR("Jérémie Galarneau");
647 BT_PLUGIN_LICENSE("MIT");
649 BT_PLUGIN_COMPONENT_CLASSES_BEGIN
650 BT_PLUGIN_SINK_COMPONENT_CLASS_ENTRY(PLUGIN_NAME
,
651 "Formats CTF-IR to text. Formerly known as ctf-text.",
653 BT_PLUGIN_COMPONENT_CLASSES_END