4 * Babeltrace CTF Text Output Plugin Event Printing
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/babeltrace.h>
31 #include <babeltrace/bitfield-internal.h>
32 #include <babeltrace/common-internal.h>
33 #include <babeltrace/compat/time-internal.h>
34 #include <babeltrace/assert-internal.h>
39 #define NSEC_PER_SEC 1000000000LL
41 #define COLOR_NAME BT_COMMON_COLOR_BOLD
42 #define COLOR_FIELD_NAME BT_COMMON_COLOR_FG_CYAN
43 #define COLOR_RST BT_COMMON_COLOR_RESET
44 #define COLOR_STRING_VALUE BT_COMMON_COLOR_BOLD
45 #define COLOR_NUMBER_VALUE BT_COMMON_COLOR_BOLD
46 #define COLOR_ENUM_MAPPING_NAME BT_COMMON_COLOR_BOLD
47 #define COLOR_UNKNOWN BT_COMMON_COLOR_BOLD BT_COMMON_COLOR_FG_RED
48 #define COLOR_EVENT_NAME BT_COMMON_COLOR_BOLD BT_COMMON_COLOR_FG_MAGENTA
49 #define COLOR_TIMESTAMP BT_COMMON_COLOR_BOLD BT_COMMON_COLOR_FG_YELLOW
52 int64_t real_timestamp
; /* Relative to UNIX epoch. */
53 uint64_t clock_value
; /* In cycles. */
57 enum bt_component_status
print_field(struct pretty_component
*pretty
,
58 struct bt_field
*field
, bool print_names
,
59 GQuark
*filters_fields
, int filter_array_len
);
62 void print_name_equal(struct pretty_component
*pretty
, const char *name
)
64 if (pretty
->use_colors
) {
65 g_string_append_printf(pretty
->string
, "%s%s%s = ", COLOR_NAME
,
68 g_string_append_printf(pretty
->string
, "%s = ", name
);
73 void print_field_name_equal(struct pretty_component
*pretty
, const char *name
)
75 if (pretty
->use_colors
) {
76 g_string_append_printf(pretty
->string
, "%s%s%s = ",
77 COLOR_FIELD_NAME
, name
, COLOR_RST
);
79 g_string_append_printf(pretty
->string
, "%s = ", name
);
84 void print_timestamp_cycles(struct pretty_component
*pretty
,
85 struct bt_event
*event
)
88 struct bt_clock_value
*clock_value
;
91 clock_value
= bt_event_borrow_default_clock_value(event
);
93 g_string_append(pretty
->string
, "????????????????????");
97 ret
= bt_clock_value_get_value(clock_value
, &cycles
);
99 // TODO: log, this is unexpected
100 g_string_append(pretty
->string
, "Error");
104 g_string_append_printf(pretty
->string
, "%020" PRIu64
, cycles
);
106 if (pretty
->last_cycles_timestamp
!= -1ULL) {
107 pretty
->delta_cycles
= cycles
- pretty
->last_cycles_timestamp
;
109 pretty
->last_cycles_timestamp
= cycles
;
113 void print_timestamp_wall(struct pretty_component
*pretty
,
114 struct bt_clock_value
*clock_value
)
117 int64_t ts_nsec
= 0; /* add configurable offset */
118 int64_t ts_sec
= 0; /* add configurable offset */
119 uint64_t ts_sec_abs
, ts_nsec_abs
;
123 g_string_append(pretty
->string
, "??:??:??.?????????");
127 ret
= bt_clock_value_get_value_ns_from_epoch(clock_value
, &ts_nsec
);
129 // TODO: log, this is unexpected
130 g_string_append(pretty
->string
, "Error");
134 if (pretty
->last_real_timestamp
!= -1ULL) {
135 pretty
->delta_real_timestamp
= ts_nsec
- pretty
->last_real_timestamp
;
138 pretty
->last_real_timestamp
= ts_nsec
;
139 ts_sec
+= ts_nsec
/ NSEC_PER_SEC
;
140 ts_nsec
= ts_nsec
% NSEC_PER_SEC
;
142 if (ts_sec
>= 0 && ts_nsec
>= 0) {
145 ts_nsec_abs
= ts_nsec
;
146 } else if (ts_sec
> 0 && ts_nsec
< 0) {
148 ts_sec_abs
= ts_sec
- 1;
149 ts_nsec_abs
= NSEC_PER_SEC
+ ts_nsec
;
150 } else if (ts_sec
== 0 && ts_nsec
< 0) {
153 ts_nsec_abs
= -ts_nsec
;
154 } else if (ts_sec
< 0 && ts_nsec
> 0) {
156 ts_sec_abs
= -(ts_sec
+ 1);
157 ts_nsec_abs
= NSEC_PER_SEC
- ts_nsec
;
158 } else if (ts_sec
< 0 && ts_nsec
== 0) {
160 ts_sec_abs
= -ts_sec
;
161 ts_nsec_abs
= ts_nsec
;
162 } else { /* (ts_sec < 0 && ts_nsec < 0) */
164 ts_sec_abs
= -ts_sec
;
165 ts_nsec_abs
= -ts_nsec
;
168 if (!pretty
->options
.clock_seconds
) {
170 time_t time_s
= (time_t) ts_sec_abs
;
172 if (is_negative
&& !pretty
->negative_timestamp_warning_done
) {
174 fprintf(stderr
, "[warning] Fallback to [sec.ns] to print negative time value. Use --clock-seconds.\n");
175 pretty
->negative_timestamp_warning_done
= true;
179 if (!pretty
->options
.clock_gmt
) {
182 res
= bt_localtime_r(&time_s
, &tm
);
185 fprintf(stderr
, "[warning] Unable to get localtime.\n");
191 res
= bt_gmtime_r(&time_s
, &tm
);
194 fprintf(stderr
, "[warning] Unable to get gmtime.\n");
198 if (pretty
->options
.clock_date
) {
202 /* Print date and time */
203 res
= strftime(timestr
, sizeof(timestr
),
207 fprintf(stderr
, "[warning] Unable to print ascii time.\n");
211 g_string_append(pretty
->string
, timestr
);
214 /* Print time in HH:MM:SS.ns */
215 g_string_append_printf(pretty
->string
,
216 "%02d:%02d:%02d.%09" PRIu64
, tm
.tm_hour
, tm
.tm_min
,
217 tm
.tm_sec
, ts_nsec_abs
);
221 g_string_append_printf(pretty
->string
, "%s%" PRId64
".%09" PRIu64
,
222 is_negative
? "-" : "", ts_sec_abs
, ts_nsec_abs
);
228 enum bt_component_status
print_event_timestamp(struct pretty_component
*pretty
,
229 struct bt_event
*event
, bool *start_line
)
231 bool print_names
= pretty
->options
.print_header_field_names
;
232 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
233 struct bt_stream
*stream
= NULL
;
234 struct bt_stream_class
*stream_class
= NULL
;
235 struct bt_trace
*trace
= NULL
;
236 struct bt_clock_value
*clock_value
= NULL
;
238 stream
= bt_event_borrow_stream(event
);
240 ret
= BT_COMPONENT_STATUS_ERROR
;
244 stream_class
= bt_stream_borrow_class(stream
);
246 ret
= BT_COMPONENT_STATUS_ERROR
;
249 trace
= bt_stream_class_borrow_trace(stream_class
);
251 ret
= BT_COMPONENT_STATUS_ERROR
;
255 clock_value
= bt_event_borrow_default_clock_value(event
);
257 /* No default clock value: skip the timestamp without an error */
262 print_name_equal(pretty
, "timestamp");
264 g_string_append(pretty
->string
, "[");
266 if (pretty
->use_colors
) {
267 g_string_append(pretty
->string
, COLOR_TIMESTAMP
);
269 if (pretty
->options
.print_timestamp_cycles
) {
270 print_timestamp_cycles(pretty
, event
);
272 struct bt_clock_value
*clock_value
=
273 bt_event_borrow_default_clock_value(event
);
275 print_timestamp_wall(pretty
, clock_value
);
277 if (pretty
->use_colors
) {
278 g_string_append(pretty
->string
, COLOR_RST
);
282 g_string_append(pretty
->string
, "] ");
284 if (pretty
->options
.print_delta_field
) {
286 g_string_append(pretty
->string
, ", ");
287 print_name_equal(pretty
, "delta");
289 g_string_append(pretty
->string
, "(");
291 if (pretty
->options
.print_timestamp_cycles
) {
292 if (pretty
->delta_cycles
== -1ULL) {
293 g_string_append(pretty
->string
,
294 "+??????????\?\?) "); /* Not a trigraph. */
296 g_string_append_printf(pretty
->string
,
297 "+%012" PRIu64
, pretty
->delta_cycles
);
300 if (pretty
->delta_real_timestamp
!= -1ULL) {
301 uint64_t delta_sec
, delta_nsec
, delta
;
303 delta
= pretty
->delta_real_timestamp
;
304 delta_sec
= delta
/ NSEC_PER_SEC
;
305 delta_nsec
= delta
% NSEC_PER_SEC
;
306 g_string_append_printf(pretty
->string
,
307 "+%" PRIu64
".%09" PRIu64
,
308 delta_sec
, delta_nsec
);
310 g_string_append(pretty
->string
, "+?.?????????");
314 g_string_append(pretty
->string
, ") ");
317 *start_line
= !print_names
;
324 enum bt_component_status
print_event_header(struct pretty_component
*pretty
,
325 struct bt_event
*event
)
327 bool print_names
= pretty
->options
.print_header_field_names
;
328 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
329 struct bt_event_class
*event_class
= NULL
;
330 struct bt_stream_class
*stream_class
= NULL
;
331 struct bt_trace
*trace_class
= NULL
;
334 event_class
= bt_event_borrow_class(event
);
336 ret
= BT_COMPONENT_STATUS_ERROR
;
339 stream_class
= bt_event_class_borrow_stream_class(event_class
);
341 ret
= BT_COMPONENT_STATUS_ERROR
;
344 trace_class
= bt_stream_class_borrow_trace(stream_class
);
346 ret
= BT_COMPONENT_STATUS_ERROR
;
349 ret
= print_event_timestamp(pretty
, event
, &pretty
->start_line
);
350 if (ret
!= BT_COMPONENT_STATUS_OK
) {
353 if (pretty
->options
.print_trace_field
) {
356 name
= bt_trace_get_name(trace_class
);
358 if (!pretty
->start_line
) {
359 g_string_append(pretty
->string
, ", ");
362 print_name_equal(pretty
, "trace");
365 g_string_append(pretty
->string
, name
);
368 g_string_append(pretty
->string
, " ");
372 if (pretty
->options
.print_trace_hostname_field
) {
373 struct bt_value
*hostname_str
;
375 hostname_str
= bt_trace_borrow_environment_field_value_by_name(
376 trace_class
, "hostname");
380 if (!pretty
->start_line
) {
381 g_string_append(pretty
->string
, ", ");
384 print_name_equal(pretty
, "trace:hostname");
386 if (bt_value_string_get(hostname_str
, &str
)
387 == BT_VALUE_STATUS_OK
) {
388 g_string_append(pretty
->string
, str
);
393 if (pretty
->options
.print_trace_domain_field
) {
394 struct bt_value
*domain_str
;
396 domain_str
= bt_trace_borrow_environment_field_value_by_name(
397 trace_class
, "domain");
401 if (!pretty
->start_line
) {
402 g_string_append(pretty
->string
, ", ");
405 print_name_equal(pretty
, "trace:domain");
406 } else if (dom_print
) {
407 g_string_append(pretty
->string
, ":");
409 if (bt_value_string_get(domain_str
, &str
)
410 == BT_VALUE_STATUS_OK
) {
411 g_string_append(pretty
->string
, str
);
416 if (pretty
->options
.print_trace_procname_field
) {
417 struct bt_value
*procname_str
;
419 procname_str
= bt_trace_borrow_environment_field_value_by_name(
420 trace_class
, "procname");
424 if (!pretty
->start_line
) {
425 g_string_append(pretty
->string
, ", ");
428 print_name_equal(pretty
, "trace:procname");
429 } else if (dom_print
) {
430 g_string_append(pretty
->string
, ":");
432 if (bt_value_string_get(procname_str
, &str
)
433 == BT_VALUE_STATUS_OK
) {
434 g_string_append(pretty
->string
, str
);
440 if (pretty
->options
.print_trace_vpid_field
) {
441 struct bt_value
*vpid_value
;
443 vpid_value
= bt_trace_borrow_environment_field_value_by_name(
444 trace_class
, "vpid");
448 if (!pretty
->start_line
) {
449 g_string_append(pretty
->string
, ", ");
452 print_name_equal(pretty
, "trace:vpid");
453 } else if (dom_print
) {
454 g_string_append(pretty
->string
, ":");
456 if (bt_value_integer_get(vpid_value
, &value
)
457 == BT_VALUE_STATUS_OK
) {
458 g_string_append_printf(pretty
->string
, "(%" PRId64
")", value
);
464 if (pretty
->options
.print_loglevel_field
) {
465 static const char *log_level_names
[] = {
466 [ BT_EVENT_CLASS_LOG_LEVEL_EMERGENCY
] = "TRACE_EMERG",
467 [ BT_EVENT_CLASS_LOG_LEVEL_ALERT
] = "TRACE_ALERT",
468 [ BT_EVENT_CLASS_LOG_LEVEL_CRITICAL
] = "TRACE_CRIT",
469 [ BT_EVENT_CLASS_LOG_LEVEL_ERROR
] = "TRACE_ERR",
470 [ BT_EVENT_CLASS_LOG_LEVEL_WARNING
] = "TRACE_WARNING",
471 [ BT_EVENT_CLASS_LOG_LEVEL_NOTICE
] = "TRACE_NOTICE",
472 [ BT_EVENT_CLASS_LOG_LEVEL_INFO
] = "TRACE_INFO",
473 [ BT_EVENT_CLASS_LOG_LEVEL_DEBUG_SYSTEM
] = "TRACE_DEBUG_SYSTEM",
474 [ BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROGRAM
] = "TRACE_DEBUG_PROGRAM",
475 [ BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROCESS
] = "TRACE_DEBUG_PROCESS",
476 [ BT_EVENT_CLASS_LOG_LEVEL_DEBUG_MODULE
] = "TRACE_DEBUG_MODULE",
477 [ BT_EVENT_CLASS_LOG_LEVEL_DEBUG_UNIT
] = "TRACE_DEBUG_UNIT",
478 [ BT_EVENT_CLASS_LOG_LEVEL_DEBUG_FUNCTION
] = "TRACE_DEBUG_FUNCTION",
479 [ BT_EVENT_CLASS_LOG_LEVEL_DEBUG_LINE
] = "TRACE_DEBUG_LINE",
480 [ BT_EVENT_CLASS_LOG_LEVEL_DEBUG
] = "TRACE_DEBUG",
482 enum bt_event_class_log_level log_level
;
483 const char *log_level_str
= NULL
;
485 log_level
= bt_event_class_get_log_level(event_class
);
486 BT_ASSERT(log_level
!= BT_EVENT_CLASS_LOG_LEVEL_UNKNOWN
);
487 if (log_level
!= BT_EVENT_CLASS_LOG_LEVEL_UNSPECIFIED
) {
488 log_level_str
= log_level_names
[log_level
];
492 if (!pretty
->start_line
) {
493 g_string_append(pretty
->string
, ", ");
496 print_name_equal(pretty
, "loglevel");
497 } else if (dom_print
) {
498 g_string_append(pretty
->string
, ":");
501 g_string_append(pretty
->string
, log_level_str
);
502 g_string_append_printf(
503 pretty
->string
, " (%d)", (int) log_level
);
507 if (pretty
->options
.print_emf_field
) {
510 uri_str
= bt_event_class_get_emf_uri(event_class
);
512 if (!pretty
->start_line
) {
513 g_string_append(pretty
->string
, ", ");
516 print_name_equal(pretty
, "model.emf.uri");
517 } else if (dom_print
) {
518 g_string_append(pretty
->string
, ":");
521 g_string_append(pretty
->string
, uri_str
);
525 if (dom_print
&& !print_names
) {
526 g_string_append(pretty
->string
, " ");
528 if (!pretty
->start_line
) {
529 g_string_append(pretty
->string
, ", ");
531 pretty
->start_line
= true;
533 print_name_equal(pretty
, "name");
535 if (pretty
->use_colors
) {
536 g_string_append(pretty
->string
, COLOR_EVENT_NAME
);
538 g_string_append(pretty
->string
, bt_event_class_get_name(event_class
));
539 if (pretty
->use_colors
) {
540 g_string_append(pretty
->string
, COLOR_RST
);
543 g_string_append(pretty
->string
, ": ");
545 g_string_append(pretty
->string
, ", ");
553 enum bt_component_status
print_integer(struct pretty_component
*pretty
,
554 struct bt_field
*field
)
556 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
557 struct bt_field_type
*field_type
= NULL
;
558 enum bt_integer_base base
;
559 enum bt_string_encoding encoding
;
561 struct bt_field_type
*int_ft
;
566 bool rst_color
= false;
567 enum bt_field_type_id ft_id
;
569 field_type
= bt_field_borrow_type(field
);
571 ret
= BT_COMPONENT_STATUS_ERROR
;
575 ft_id
= bt_field_get_type_id(field
);
578 case BT_FIELD_TYPE_ID_INTEGER
:
581 case BT_FIELD_TYPE_ID_ENUM
:
582 int_ft
= bt_field_type_enumeration_borrow_container_field_type(
589 signedness
= bt_field_type_integer_is_signed(int_ft
);
590 if (signedness
< 0) {
591 ret
= BT_COMPONENT_STATUS_ERROR
;
595 ret
= bt_field_integer_unsigned_get_value(field
, &v
.u
);
597 ret
= bt_field_integer_signed_get_value(field
, &v
.s
);
601 ret
= BT_COMPONENT_STATUS_ERROR
;
605 encoding
= bt_field_type_integer_get_encoding(int_ft
);
607 case BT_STRING_ENCODING_UTF8
:
608 case BT_STRING_ENCODING_ASCII
:
609 g_string_append_c(pretty
->tmp_string
, (int) v
.u
);
611 case BT_STRING_ENCODING_NONE
:
612 case BT_STRING_ENCODING_UNKNOWN
:
615 ret
= BT_COMPONENT_STATUS_ERROR
;
619 if (pretty
->use_colors
) {
620 g_string_append(pretty
->string
, COLOR_NUMBER_VALUE
);
624 base
= bt_field_type_integer_get_base(int_ft
);
626 case BT_INTEGER_BASE_BINARY
:
630 len
= bt_field_type_integer_get_size(int_ft
);
632 ret
= BT_COMPONENT_STATUS_ERROR
;
635 g_string_append(pretty
->string
, "0b");
636 v
.u
= _bt_piecewise_lshift(v
.u
, 64 - len
);
637 for (bitnr
= 0; bitnr
< len
; bitnr
++) {
638 g_string_append_printf(pretty
->string
, "%u", (v
.u
& (1ULL << 63)) ? 1 : 0);
639 v
.u
= _bt_piecewise_lshift(v
.u
, 1);
643 case BT_INTEGER_BASE_OCTAL
:
648 len
= bt_field_type_integer_get_size(int_ft
);
650 ret
= BT_COMPONENT_STATUS_ERROR
;
657 /* Round length to the nearest 3-bit */
658 rounded_len
= (((len
- 1) / 3) + 1) * 3;
659 v
.u
&= ((uint64_t) 1 << rounded_len
) - 1;
663 g_string_append_printf(pretty
->string
, "0%" PRIo64
, v
.u
);
666 case BT_INTEGER_BASE_DECIMAL
:
667 case BT_INTEGER_BASE_UNSPECIFIED
:
669 g_string_append_printf(pretty
->string
, "%" PRIu64
, v
.u
);
671 g_string_append_printf(pretty
->string
, "%" PRId64
, v
.s
);
674 case BT_INTEGER_BASE_HEXADECIMAL
:
678 len
= bt_field_type_integer_get_size(int_ft
);
680 ret
= BT_COMPONENT_STATUS_ERROR
;
684 /* Round length to the nearest nibble */
685 uint8_t rounded_len
= ((len
+ 3) & ~0x3);
687 v
.u
&= ((uint64_t) 1 << rounded_len
) - 1;
690 g_string_append_printf(pretty
->string
, "0x%" PRIX64
, v
.u
);
694 ret
= BT_COMPONENT_STATUS_ERROR
;
699 g_string_append(pretty
->string
, COLOR_RST
);
705 void print_escape_string(struct pretty_component
*pretty
, const char *str
)
709 g_string_append_c(pretty
->string
, '"');
711 for (i
= 0; i
< strlen(str
); i
++) {
712 /* Escape sequences not recognized by iscntrl(). */
715 g_string_append(pretty
->string
, "\\\\");
718 g_string_append(pretty
->string
, "\\\'");
721 g_string_append(pretty
->string
, "\\\"");
724 g_string_append(pretty
->string
, "\\\?");
728 /* Standard characters. */
729 if (!iscntrl(str
[i
])) {
730 g_string_append_c(pretty
->string
, str
[i
]);
736 g_string_append(pretty
->string
, "\\0");
739 g_string_append(pretty
->string
, "\\a");
742 g_string_append(pretty
->string
, "\\b");
745 g_string_append(pretty
->string
, "\\e");
748 g_string_append(pretty
->string
, "\\f");
751 g_string_append(pretty
->string
, "\\n");
754 g_string_append(pretty
->string
, "\\r");
757 g_string_append(pretty
->string
, "\\t");
760 g_string_append(pretty
->string
, "\\v");
763 /* Unhandled control-sequence, print as hex. */
764 g_string_append_printf(pretty
->string
, "\\x%02x", str
[i
]);
769 g_string_append_c(pretty
->string
, '"');
773 enum bt_component_status
print_enum(struct pretty_component
*pretty
,
774 struct bt_field
*field
)
776 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
777 struct bt_field_type
*enumeration_field_type
= NULL
;
778 struct bt_field_type
*container_field_type
= NULL
;
779 struct bt_field_type_enumeration_mapping_iterator
*iter
= NULL
;
782 enumeration_field_type
= bt_field_borrow_type(field
);
783 if (!enumeration_field_type
) {
784 ret
= BT_COMPONENT_STATUS_ERROR
;
787 container_field_type
=
788 bt_field_type_enumeration_borrow_container_field_type(
789 enumeration_field_type
);
790 if (!container_field_type
) {
791 ret
= BT_COMPONENT_STATUS_ERROR
;
794 iter
= bt_field_enumeration_get_mappings(field
);
796 ret
= BT_COMPONENT_STATUS_ERROR
;
799 g_string_append(pretty
->string
, "( ");
800 ret
= bt_field_type_enumeration_mapping_iterator_next(iter
);
802 if (pretty
->use_colors
) {
803 g_string_append(pretty
->string
, COLOR_UNKNOWN
);
805 g_string_append(pretty
->string
, "<unknown>");
806 if (pretty
->use_colors
) {
807 g_string_append(pretty
->string
, COLOR_RST
);
812 const char *mapping_name
;
814 if (bt_field_type_enumeration_mapping_iterator_signed_get(
815 iter
, &mapping_name
, NULL
, NULL
) < 0) {
816 ret
= BT_COMPONENT_STATUS_ERROR
;
820 g_string_append(pretty
->string
, ", ");
821 if (pretty
->use_colors
) {
822 g_string_append(pretty
->string
, COLOR_ENUM_MAPPING_NAME
);
824 print_escape_string(pretty
, mapping_name
);
825 if (pretty
->use_colors
) {
826 g_string_append(pretty
->string
, COLOR_RST
);
828 if (bt_field_type_enumeration_mapping_iterator_next(iter
) < 0) {
833 g_string_append(pretty
->string
, " : container = ");
834 ret
= print_integer(pretty
, field
);
835 if (ret
!= BT_COMPONENT_STATUS_OK
) {
838 g_string_append(pretty
->string
, " )");
845 int filter_field_name(struct pretty_component
*pretty
, const char *field_name
,
846 GQuark
*filter_fields
, int filter_array_len
)
849 GQuark field_quark
= g_quark_try_string(field_name
);
851 if (!field_quark
|| pretty
->options
.verbose
) {
855 for (i
= 0; i
< filter_array_len
; i
++) {
856 if (field_quark
== filter_fields
[i
]) {
864 enum bt_component_status
print_struct_field(struct pretty_component
*pretty
,
865 struct bt_field
*_struct
,
866 struct bt_field_type
*struct_type
,
867 int i
, bool print_names
, int *nr_printed_fields
,
868 GQuark
*filter_fields
, int filter_array_len
)
870 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
871 const char *field_name
;
872 struct bt_field
*field
= NULL
;
873 struct bt_field_type
*field_type
= NULL
;;
875 field
= bt_field_structure_borrow_field_by_index(_struct
, i
);
877 ret
= BT_COMPONENT_STATUS_ERROR
;
880 if (bt_field_type_structure_borrow_field_by_index(struct_type
,
881 &field_name
, &field_type
, i
) < 0) {
882 ret
= BT_COMPONENT_STATUS_ERROR
;
886 if (filter_fields
&& !filter_field_name(pretty
, field_name
,
887 filter_fields
, filter_array_len
)) {
888 ret
= BT_COMPONENT_STATUS_OK
;
892 if (*nr_printed_fields
> 0) {
893 g_string_append(pretty
->string
, ", ");
895 g_string_append(pretty
->string
, " ");
898 print_field_name_equal(pretty
, field_name
);
900 ret
= print_field(pretty
, field
, print_names
, NULL
, 0);
901 *nr_printed_fields
+= 1;
908 enum bt_component_status
print_struct(struct pretty_component
*pretty
,
909 struct bt_field
*_struct
, bool print_names
,
910 GQuark
*filter_fields
, int filter_array_len
)
912 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
913 struct bt_field_type
*struct_type
= NULL
;
914 int nr_fields
, i
, nr_printed_fields
;
916 struct_type
= bt_field_borrow_type(_struct
);
918 ret
= BT_COMPONENT_STATUS_ERROR
;
921 nr_fields
= bt_field_type_structure_get_field_count(struct_type
);
923 ret
= BT_COMPONENT_STATUS_ERROR
;
926 g_string_append(pretty
->string
, "{");
928 nr_printed_fields
= 0;
929 for (i
= 0; i
< nr_fields
; i
++) {
930 ret
= print_struct_field(pretty
, _struct
, struct_type
, i
,
931 print_names
, &nr_printed_fields
, filter_fields
,
933 if (ret
!= BT_COMPONENT_STATUS_OK
) {
938 g_string_append(pretty
->string
, " }");
945 enum bt_component_status
print_array_field(struct pretty_component
*pretty
,
946 struct bt_field
*array
, uint64_t i
,
947 bool is_string
, bool print_names
)
949 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
950 struct bt_field
*field
= NULL
;
954 g_string_append(pretty
->string
, ", ");
956 g_string_append(pretty
->string
, " ");
959 g_string_append_printf(pretty
->string
, "[%" PRIu64
"] = ", i
);
962 field
= bt_field_array_borrow_field(array
, i
);
964 ret
= BT_COMPONENT_STATUS_ERROR
;
967 ret
= print_field(pretty
, field
, print_names
, NULL
, 0);
974 enum bt_component_status
print_array(struct pretty_component
*pretty
,
975 struct bt_field
*array
, bool print_names
)
977 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
978 struct bt_field_type
*array_type
= NULL
, *field_type
= NULL
;
979 enum bt_field_type_id type_id
;
982 bool is_string
= false;
984 array_type
= bt_field_borrow_type(array
);
986 ret
= BT_COMPONENT_STATUS_ERROR
;
989 field_type
= bt_field_type_array_borrow_element_field_type(array_type
);
991 ret
= BT_COMPONENT_STATUS_ERROR
;
994 len
= bt_field_type_array_get_length(array_type
);
996 ret
= BT_COMPONENT_STATUS_ERROR
;
999 type_id
= bt_field_type_get_type_id(field_type
);
1000 if (type_id
== BT_FIELD_TYPE_ID_INTEGER
) {
1001 enum bt_string_encoding encoding
;
1003 encoding
= bt_field_type_integer_get_encoding(field_type
);
1004 if (encoding
== BT_STRING_ENCODING_UTF8
1005 || encoding
== BT_STRING_ENCODING_ASCII
) {
1006 int integer_len
, integer_alignment
;
1008 integer_len
= bt_field_type_integer_get_size(field_type
);
1009 if (integer_len
< 0) {
1010 return BT_COMPONENT_STATUS_ERROR
;
1012 integer_alignment
= bt_field_type_get_alignment(field_type
);
1013 if (integer_alignment
< 0) {
1014 return BT_COMPONENT_STATUS_ERROR
;
1016 if (integer_len
== CHAR_BIT
1017 && integer_alignment
== CHAR_BIT
) {
1024 g_string_assign(pretty
->tmp_string
, "");
1026 g_string_append(pretty
->string
, "[");
1030 for (i
= 0; i
< len
; i
++) {
1031 ret
= print_array_field(pretty
, array
, i
, is_string
, print_names
);
1032 if (ret
!= BT_COMPONENT_STATUS_OK
) {
1039 if (pretty
->use_colors
) {
1040 g_string_append(pretty
->string
, COLOR_STRING_VALUE
);
1042 print_escape_string(pretty
, pretty
->tmp_string
->str
);
1043 if (pretty
->use_colors
) {
1044 g_string_append(pretty
->string
, COLOR_RST
);
1047 g_string_append(pretty
->string
, " ]");
1055 enum bt_component_status
print_sequence_field(struct pretty_component
*pretty
,
1056 struct bt_field
*seq
, uint64_t i
,
1057 bool is_string
, bool print_names
)
1059 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
1060 struct bt_field
*field
= NULL
;
1064 g_string_append(pretty
->string
, ", ");
1066 g_string_append(pretty
->string
, " ");
1069 g_string_append_printf(pretty
->string
, "[%" PRIu64
"] = ", i
);
1072 field
= bt_field_sequence_borrow_field(seq
, i
);
1074 ret
= BT_COMPONENT_STATUS_ERROR
;
1077 ret
= print_field(pretty
, field
, print_names
, NULL
, 0);
1084 enum bt_component_status
print_sequence(struct pretty_component
*pretty
,
1085 struct bt_field
*seq
, bool print_names
)
1087 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
1088 struct bt_field_type
*seq_type
= NULL
, *field_type
= NULL
;
1089 enum bt_field_type_id type_id
;
1092 bool is_string
= false;
1094 seq_type
= bt_field_borrow_type(seq
);
1096 ret
= BT_COMPONENT_STATUS_ERROR
;
1099 len
= bt_field_sequence_get_length(seq
);
1101 ret
= BT_COMPONENT_STATUS_ERROR
;
1104 field_type
= bt_field_type_sequence_borrow_element_field_type(seq_type
);
1106 ret
= BT_COMPONENT_STATUS_ERROR
;
1109 type_id
= bt_field_type_get_type_id(field_type
);
1110 if (type_id
== BT_FIELD_TYPE_ID_INTEGER
) {
1111 enum bt_string_encoding encoding
;
1113 encoding
= bt_field_type_integer_get_encoding(field_type
);
1114 if (encoding
== BT_STRING_ENCODING_UTF8
1115 || encoding
== BT_STRING_ENCODING_ASCII
) {
1116 int integer_len
, integer_alignment
;
1118 integer_len
= bt_field_type_integer_get_size(field_type
);
1119 if (integer_len
< 0) {
1120 ret
= BT_COMPONENT_STATUS_ERROR
;
1123 integer_alignment
= bt_field_type_get_alignment(field_type
);
1124 if (integer_alignment
< 0) {
1125 ret
= BT_COMPONENT_STATUS_ERROR
;
1128 if (integer_len
== CHAR_BIT
1129 && integer_alignment
== CHAR_BIT
) {
1136 g_string_assign(pretty
->tmp_string
, "");
1138 g_string_append(pretty
->string
, "[");
1142 for (i
= 0; i
< len
; i
++) {
1143 ret
= print_sequence_field(pretty
, seq
, i
,
1144 is_string
, print_names
);
1145 if (ret
!= BT_COMPONENT_STATUS_OK
) {
1152 if (pretty
->use_colors
) {
1153 g_string_append(pretty
->string
, COLOR_STRING_VALUE
);
1155 print_escape_string(pretty
, pretty
->tmp_string
->str
);
1156 if (pretty
->use_colors
) {
1157 g_string_append(pretty
->string
, COLOR_RST
);
1160 g_string_append(pretty
->string
, " ]");
1168 enum bt_component_status
print_variant(struct pretty_component
*pretty
,
1169 struct bt_field
*variant
, bool print_names
)
1171 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
1172 struct bt_field
*field
= NULL
;
1174 field
= bt_field_variant_borrow_current_field(variant
);
1176 ret
= BT_COMPONENT_STATUS_ERROR
;
1179 g_string_append(pretty
->string
, "{ ");
1183 struct bt_field_type
*var_ft
;
1184 struct bt_field_type
*tag_ft
;
1185 struct bt_field_type
*container_ft
;
1186 const char *tag_choice
;
1188 struct bt_field_type_enumeration_mapping_iterator
*iter
;
1190 var_ft
= bt_field_borrow_type(variant
);
1191 tag_ft
= bt_field_type_variant_borrow_tag_field_type(
1194 bt_field_type_enumeration_borrow_container_field_type(
1196 is_signed
= bt_field_type_integer_is_signed(container_ft
);
1201 iret
= bt_field_variant_get_tag_signed(variant
, &tag
);
1203 ret
= BT_COMPONENT_STATUS_ERROR
;
1207 iter
= bt_field_type_enumeration_signed_find_mappings_by_value(
1212 iret
= bt_field_variant_get_tag_unsigned(variant
, &tag
);
1214 ret
= BT_COMPONENT_STATUS_ERROR
;
1218 iter
= bt_field_type_enumeration_unsigned_find_mappings_by_value(
1223 ret
= BT_COMPONENT_STATUS_ERROR
;
1227 iret
= bt_field_type_enumeration_mapping_iterator_next(
1230 ret
= BT_COMPONENT_STATUS_ERROR
;
1235 bt_field_type_enumeration_mapping_iterator_signed_get(
1236 iter
, &tag_choice
, NULL
, NULL
);
1239 ret
= BT_COMPONENT_STATUS_ERROR
;
1242 print_field_name_equal(pretty
, tag_choice
);
1245 ret
= print_field(pretty
, field
, print_names
, NULL
, 0);
1246 if (ret
!= BT_COMPONENT_STATUS_OK
) {
1250 g_string_append(pretty
->string
, " }");
1257 enum bt_component_status
print_field(struct pretty_component
*pretty
,
1258 struct bt_field
*field
, bool print_names
,
1259 GQuark
*filter_fields
, int filter_array_len
)
1261 enum bt_field_type_id type_id
;
1263 type_id
= bt_field_get_type_id(field
);
1265 case BT_FIELD_TYPE_ID_INTEGER
:
1266 return print_integer(pretty
, field
);
1267 case BT_FIELD_TYPE_ID_FLOAT
:
1271 if (bt_field_floating_point_get_value(field
, &v
)) {
1272 return BT_COMPONENT_STATUS_ERROR
;
1274 if (pretty
->use_colors
) {
1275 g_string_append(pretty
->string
, COLOR_NUMBER_VALUE
);
1277 g_string_append_printf(pretty
->string
, "%g", v
);
1278 if (pretty
->use_colors
) {
1279 g_string_append(pretty
->string
, COLOR_RST
);
1281 return BT_COMPONENT_STATUS_OK
;
1283 case BT_FIELD_TYPE_ID_ENUM
:
1284 return print_enum(pretty
, field
);
1285 case BT_FIELD_TYPE_ID_STRING
:
1289 str
= bt_field_string_get_value(field
);
1291 return BT_COMPONENT_STATUS_ERROR
;
1294 if (pretty
->use_colors
) {
1295 g_string_append(pretty
->string
, COLOR_STRING_VALUE
);
1297 print_escape_string(pretty
, str
);
1298 if (pretty
->use_colors
) {
1299 g_string_append(pretty
->string
, COLOR_RST
);
1301 return BT_COMPONENT_STATUS_OK
;
1303 case BT_FIELD_TYPE_ID_STRUCT
:
1304 return print_struct(pretty
, field
, print_names
, filter_fields
,
1306 case BT_FIELD_TYPE_ID_VARIANT
:
1307 return print_variant(pretty
, field
, print_names
);
1308 case BT_FIELD_TYPE_ID_ARRAY
:
1309 return print_array(pretty
, field
, print_names
);
1310 case BT_FIELD_TYPE_ID_SEQUENCE
:
1311 return print_sequence(pretty
, field
, print_names
);
1313 // TODO: log instead
1314 fprintf(pretty
->err
, "[error] Unknown type id: %d\n", (int) type_id
);
1315 return BT_COMPONENT_STATUS_ERROR
;
1320 enum bt_component_status
print_stream_packet_context(struct pretty_component
*pretty
,
1321 struct bt_event
*event
)
1323 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
1324 struct bt_packet
*packet
= NULL
;
1325 struct bt_field
*main_field
= NULL
;
1327 packet
= bt_event_borrow_packet(event
);
1329 ret
= BT_COMPONENT_STATUS_ERROR
;
1332 main_field
= bt_packet_borrow_context(packet
);
1336 if (!pretty
->start_line
) {
1337 g_string_append(pretty
->string
, ", ");
1339 pretty
->start_line
= false;
1340 if (pretty
->options
.print_scope_field_names
) {
1341 print_name_equal(pretty
, "stream.packet.context");
1343 ret
= print_field(pretty
, main_field
,
1344 pretty
->options
.print_context_field_names
,
1345 stream_packet_context_quarks
,
1346 STREAM_PACKET_CONTEXT_QUARKS_LEN
);
1353 enum bt_component_status
print_event_header_raw(struct pretty_component
*pretty
,
1354 struct bt_event
*event
)
1356 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
1357 struct bt_field
*main_field
= NULL
;
1359 main_field
= bt_event_borrow_header(event
);
1363 if (!pretty
->start_line
) {
1364 g_string_append(pretty
->string
, ", ");
1366 pretty
->start_line
= false;
1367 if (pretty
->options
.print_scope_field_names
) {
1368 print_name_equal(pretty
, "stream.event.header");
1370 ret
= print_field(pretty
, main_field
,
1371 pretty
->options
.print_header_field_names
, NULL
, 0);
1378 enum bt_component_status
print_stream_event_context(struct pretty_component
*pretty
,
1379 struct bt_event
*event
)
1381 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
1382 struct bt_field
*main_field
= NULL
;
1384 main_field
= bt_event_borrow_stream_event_context(event
);
1388 if (!pretty
->start_line
) {
1389 g_string_append(pretty
->string
, ", ");
1391 pretty
->start_line
= false;
1392 if (pretty
->options
.print_scope_field_names
) {
1393 print_name_equal(pretty
, "stream.event.context");
1395 ret
= print_field(pretty
, main_field
,
1396 pretty
->options
.print_context_field_names
, NULL
, 0);
1403 enum bt_component_status
print_event_context(struct pretty_component
*pretty
,
1404 struct bt_event
*event
)
1406 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
1407 struct bt_field
*main_field
= NULL
;
1409 main_field
= bt_event_borrow_context(event
);
1413 if (!pretty
->start_line
) {
1414 g_string_append(pretty
->string
, ", ");
1416 pretty
->start_line
= false;
1417 if (pretty
->options
.print_scope_field_names
) {
1418 print_name_equal(pretty
, "event.context");
1420 ret
= print_field(pretty
, main_field
,
1421 pretty
->options
.print_context_field_names
, NULL
, 0);
1428 enum bt_component_status
print_event_payload(struct pretty_component
*pretty
,
1429 struct bt_event
*event
)
1431 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
1432 struct bt_field
*main_field
= NULL
;
1434 main_field
= bt_event_borrow_payload(event
);
1438 if (!pretty
->start_line
) {
1439 g_string_append(pretty
->string
, ", ");
1441 pretty
->start_line
= false;
1442 if (pretty
->options
.print_scope_field_names
) {
1443 print_name_equal(pretty
, "event.fields");
1445 ret
= print_field(pretty
, main_field
,
1446 pretty
->options
.print_payload_field_names
, NULL
, 0);
1453 int flush_buf(FILE *stream
, struct pretty_component
*pretty
)
1457 if (pretty
->string
->len
== 0) {
1461 if (fwrite(pretty
->string
->str
, pretty
->string
->len
, 1, stream
) != 1) {
1470 enum bt_component_status
pretty_print_event(struct pretty_component
*pretty
,
1471 struct bt_notification
*event_notif
)
1473 enum bt_component_status ret
;
1474 struct bt_event
*event
=
1475 bt_notification_event_borrow_event(event_notif
);
1478 pretty
->start_line
= true;
1479 g_string_assign(pretty
->string
, "");
1480 ret
= print_event_header(pretty
, event
);
1481 if (ret
!= BT_COMPONENT_STATUS_OK
) {
1485 ret
= print_stream_packet_context(pretty
, event
);
1486 if (ret
!= BT_COMPONENT_STATUS_OK
) {
1490 if (pretty
->options
.verbose
) {
1491 ret
= print_event_header_raw(pretty
, event
);
1492 if (ret
!= BT_COMPONENT_STATUS_OK
) {
1497 ret
= print_stream_event_context(pretty
, event
);
1498 if (ret
!= BT_COMPONENT_STATUS_OK
) {
1502 ret
= print_event_context(pretty
, event
);
1503 if (ret
!= BT_COMPONENT_STATUS_OK
) {
1507 ret
= print_event_payload(pretty
, event
);
1508 if (ret
!= BT_COMPONENT_STATUS_OK
) {
1512 g_string_append_c(pretty
->string
, '\n');
1513 if (flush_buf(pretty
->out
, pretty
)) {
1514 ret
= BT_COMPONENT_STATUS_ERROR
;
1523 enum bt_component_status
print_discarded_elements_msg(
1524 struct pretty_component
*pretty
, struct bt_packet
*packet
,
1525 uint64_t count
, const char *elem_type
)
1527 enum bt_component_status ret
= BT_COMPONENT_STATUS_OK
;
1528 struct bt_stream
*stream
= NULL
;
1529 struct bt_stream_class
*stream_class
= NULL
;
1530 struct bt_trace
*trace
= NULL
;
1531 const char *stream_name
;
1532 const char *trace_name
;
1533 const unsigned char *trace_uuid
;
1534 int64_t stream_class_id
;
1536 struct bt_clock_value
*begin_clock_value
= NULL
;
1537 struct bt_clock_value
*end_clock_value
= NULL
;
1541 stream
= bt_packet_borrow_stream(packet
);
1543 stream_name
= bt_stream_get_name(stream
);
1545 /* Stream class ID */
1546 stream_class
= bt_stream_borrow_class(stream
);
1547 BT_ASSERT(stream_class
);
1548 stream_class_id
= bt_stream_class_get_id(stream_class
);
1551 stream_id
= bt_stream_get_id(stream
);
1554 trace
= bt_stream_class_borrow_trace(stream_class
);
1556 trace_name
= bt_trace_get_name(trace
);
1558 trace_name
= "(unknown)";
1562 trace_uuid
= bt_trace_get_uuid(trace
);
1564 /* Beginning and end times */
1565 (void) bt_packet_borrow_previous_packet_default_end_clock_value(
1566 packet
, &begin_clock_value
);
1567 (void) bt_packet_borrow_default_end_clock_value(packet
,
1570 /* Format message */
1571 g_string_assign(pretty
->string
, "");
1572 g_string_append_printf(pretty
->string
,
1573 "%s%sWARNING%s%s: Tracer discarded %" PRId64
" %s%s ",
1574 bt_common_color_fg_yellow(),
1575 bt_common_color_bold(),
1576 bt_common_color_reset(),
1577 bt_common_color_fg_yellow(),
1578 count
, elem_type
, count
== 1 ? "" : "s");
1580 if (begin_clock_value
&& end_clock_value
) {
1581 g_string_append(pretty
->string
, "between [");
1582 print_timestamp_wall(pretty
, begin_clock_value
);
1583 g_string_append(pretty
->string
, "] and [");
1584 print_timestamp_wall(pretty
, end_clock_value
);
1585 g_string_append(pretty
->string
, "]");
1587 g_string_append(pretty
->string
, "(unknown time range)");
1590 g_string_append_printf(pretty
->string
, " in trace \"%s\" ", trace_name
);
1593 g_string_append_printf(pretty
->string
,
1594 "(UUID: %02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x) ",
1612 g_string_append(pretty
->string
, "(no UUID) ");
1615 g_string_append_printf(pretty
->string
,
1616 "within stream \"%s\" (stream class ID: %" PRId64
", ",
1617 stream_name
, stream_class_id
);
1619 if (stream_id
>= 0) {
1620 g_string_append_printf(pretty
->string
,
1621 "stream ID: %" PRId64
, stream_id
);
1623 g_string_append(pretty
->string
, "no stream ID");
1626 g_string_append_printf(pretty
->string
, ").%s\n",
1627 bt_common_color_reset());
1630 * Print to standard error stream to remain backward compatible
1631 * with Babeltrace 1.
1633 if (flush_buf(stderr
, pretty
)) {
1634 ret
= BT_COMPONENT_STATUS_ERROR
;
1641 enum bt_component_status
pretty_print_packet(struct pretty_component
*pretty
,
1642 struct bt_notification
*packet_beginning_notif
)
1644 struct bt_packet
*packet
= bt_notification_packet_begin_borrow_packet(
1645 packet_beginning_notif
);
1647 enum bt_component_status status
= BT_COMPONENT_STATUS_OK
;
1649 if (bt_packet_get_discarded_event_count(packet
, &count
) ==
1650 BT_PACKET_PROPERTY_AVAILABILITY_AVAILABLE
&&
1652 status
= print_discarded_elements_msg(pretty
, packet
,
1654 if (status
!= BT_COMPONENT_STATUS_OK
) {
1659 if (bt_packet_get_discarded_packet_count(packet
, &count
) ==
1660 BT_PACKET_PROPERTY_AVAILABILITY_AVAILABLE
&&
1662 status
= print_discarded_elements_msg(pretty
, packet
,
1664 if (status
!= BT_COMPONENT_STATUS_OK
) {