2 * Copyright 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com>
3 * Copyright 2016 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
5 * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 #include <babeltrace2/babeltrace.h>
27 #include "compat/bitfield.h"
28 #include "common/common.h"
29 #include "common/uuid.h"
30 #include "compat/time.h"
31 #include "common/assert.h"
38 #define NSEC_PER_SEC 1000000000LL
40 static char color_name
[32];
41 static char color_field_name
[32];
42 static char color_rst
[32];
43 static char color_string_value
[32];
44 static char color_number_value
[32];
45 static char color_enum_mapping_name
[32];
46 static char color_unknown
[32];
47 static char color_event_name
[32];
48 static char color_timestamp
[32];
51 int64_t real_timestamp
; /* Relative to UNIX epoch. */
52 uint64_t clock_snapshot
; /* In cycles. */
56 int print_field(struct pretty_component
*pretty
,
57 const bt_field
*field
, bool print_names
);
60 void print_name_equal(struct pretty_component
*pretty
, const char *name
)
62 if (pretty
->use_colors
) {
63 bt_common_g_string_append(pretty
->string
, color_name
);
64 bt_common_g_string_append(pretty
->string
, name
);
65 bt_common_g_string_append(pretty
->string
, color_rst
);
67 bt_common_g_string_append(pretty
->string
, name
);
69 bt_common_g_string_append(pretty
->string
, " = ");
73 void print_field_name_equal(struct pretty_component
*pretty
, const char *name
)
75 if (pretty
->use_colors
) {
76 bt_common_g_string_append(pretty
->string
, color_field_name
);
77 bt_common_g_string_append(pretty
->string
, name
);
78 bt_common_g_string_append(pretty
->string
, color_rst
);
80 bt_common_g_string_append(pretty
->string
, name
);
82 bt_common_g_string_append(pretty
->string
, " = ");
86 void print_timestamp_cycles(struct pretty_component
*pretty
,
87 const bt_clock_snapshot
*clock_snapshot
, bool update_last
)
91 cycles
= bt_clock_snapshot_get_value(clock_snapshot
);
92 bt_common_g_string_append_printf(pretty
->string
, "%020" PRIu64
, cycles
);
95 if (pretty
->last_cycles_timestamp
!= -1ULL) {
96 pretty
->delta_cycles
= cycles
- pretty
->last_cycles_timestamp
;
99 pretty
->last_cycles_timestamp
= cycles
;
104 void print_timestamp_wall(struct pretty_component
*pretty
,
105 const bt_clock_snapshot
*clock_snapshot
, bool update_last
)
108 int64_t ts_nsec
= 0; /* add configurable offset */
109 int64_t ts_sec
= 0; /* add configurable offset */
110 uint64_t ts_sec_abs
, ts_nsec_abs
;
113 if (!clock_snapshot
) {
114 bt_common_g_string_append(pretty
->string
, "??:??:??.?????????");
118 ret
= bt_clock_snapshot_get_ns_from_origin(clock_snapshot
, &ts_nsec
);
120 // TODO: log, this is unexpected
121 bt_common_g_string_append(pretty
->string
, "Error");
126 if (pretty
->last_real_timestamp
!= -1ULL) {
127 pretty
->delta_real_timestamp
= ts_nsec
- pretty
->last_real_timestamp
;
130 pretty
->last_real_timestamp
= ts_nsec
;
133 ts_sec
+= ts_nsec
/ NSEC_PER_SEC
;
134 ts_nsec
= ts_nsec
% NSEC_PER_SEC
;
136 if (ts_sec
>= 0 && ts_nsec
>= 0) {
139 ts_nsec_abs
= ts_nsec
;
140 } else if (ts_sec
> 0 && ts_nsec
< 0) {
142 ts_sec_abs
= ts_sec
- 1;
143 ts_nsec_abs
= NSEC_PER_SEC
+ ts_nsec
;
144 } else if (ts_sec
== 0 && ts_nsec
< 0) {
147 ts_nsec_abs
= -ts_nsec
;
148 } else if (ts_sec
< 0 && ts_nsec
> 0) {
150 ts_sec_abs
= -(ts_sec
+ 1);
151 ts_nsec_abs
= NSEC_PER_SEC
- ts_nsec
;
152 } else if (ts_sec
< 0 && ts_nsec
== 0) {
154 ts_sec_abs
= -ts_sec
;
155 ts_nsec_abs
= ts_nsec
;
156 } else { /* (ts_sec < 0 && ts_nsec < 0) */
158 ts_sec_abs
= -ts_sec
;
159 ts_nsec_abs
= -ts_nsec
;
162 if (!pretty
->options
.clock_seconds
) {
164 time_t time_s
= (time_t) ts_sec_abs
;
166 if (is_negative
&& !pretty
->negative_timestamp_warning_done
) {
168 fprintf(stderr
, "[warning] Fallback to [sec.ns] to print negative time value. Use --clock-seconds.\n");
169 pretty
->negative_timestamp_warning_done
= true;
173 if (!pretty
->options
.clock_gmt
) {
176 res
= bt_localtime_r(&time_s
, &tm
);
179 fprintf(stderr
, "[warning] Unable to get localtime.\n");
185 res
= bt_gmtime_r(&time_s
, &tm
);
188 fprintf(stderr
, "[warning] Unable to get gmtime.\n");
192 if (pretty
->options
.clock_date
) {
196 /* Print date and time */
197 res
= strftime(timestr
, sizeof(timestr
),
201 fprintf(stderr
, "[warning] Unable to print ascii time.\n");
205 bt_common_g_string_append(pretty
->string
, timestr
);
208 /* Print time in HH:MM:SS.ns */
209 bt_common_g_string_append_printf(pretty
->string
,
210 "%02d:%02d:%02d.%09" PRIu64
, tm
.tm_hour
, tm
.tm_min
,
211 tm
.tm_sec
, ts_nsec_abs
);
215 bt_common_g_string_append_printf(pretty
->string
, "%s%" PRId64
".%09" PRIu64
,
216 is_negative
? "-" : "", ts_sec_abs
, ts_nsec_abs
);
222 int print_event_timestamp(struct pretty_component
*pretty
,
223 const bt_message
*event_msg
, bool *start_line
)
225 bool print_names
= pretty
->options
.print_header_field_names
;
227 const bt_clock_snapshot
*clock_snapshot
= NULL
;
229 if (!bt_message_event_borrow_stream_class_default_clock_class_const(
231 /* No default clock class: skip the timestamp without an error */
235 clock_snapshot
= bt_message_event_borrow_default_clock_snapshot_const(event_msg
);
238 print_name_equal(pretty
, "timestamp");
240 bt_common_g_string_append(pretty
->string
, "[");
242 if (pretty
->use_colors
) {
243 bt_common_g_string_append(pretty
->string
, color_timestamp
);
245 if (pretty
->options
.print_timestamp_cycles
) {
246 print_timestamp_cycles(pretty
, clock_snapshot
, true);
248 print_timestamp_wall(pretty
, clock_snapshot
, true);
250 if (pretty
->use_colors
) {
251 bt_common_g_string_append(pretty
->string
, color_rst
);
255 bt_common_g_string_append(pretty
->string
, "] ");
257 if (pretty
->options
.print_delta_field
) {
259 bt_common_g_string_append(pretty
->string
, ", ");
260 print_name_equal(pretty
, "delta");
262 bt_common_g_string_append(pretty
->string
, "(");
264 if (pretty
->options
.print_timestamp_cycles
) {
265 if (pretty
->delta_cycles
== -1ULL) {
266 bt_common_g_string_append(pretty
->string
,
267 "+??????????\?\?"); /* Not a trigraph. */
269 bt_common_g_string_append_printf(pretty
->string
,
270 "+%012" PRIu64
, pretty
->delta_cycles
);
273 if (pretty
->delta_real_timestamp
!= -1ULL) {
274 uint64_t delta_sec
, delta_nsec
, delta
;
276 delta
= pretty
->delta_real_timestamp
;
277 delta_sec
= delta
/ NSEC_PER_SEC
;
278 delta_nsec
= delta
% NSEC_PER_SEC
;
279 bt_common_g_string_append_printf(pretty
->string
,
280 "+%" PRIu64
".%09" PRIu64
,
281 delta_sec
, delta_nsec
);
283 bt_common_g_string_append(pretty
->string
, "+?.?????????");
287 bt_common_g_string_append(pretty
->string
, ") ");
290 *start_line
= !print_names
;
297 int print_event_header(struct pretty_component
*pretty
,
298 const bt_message
*event_msg
)
300 bool print_names
= pretty
->options
.print_header_field_names
;
302 const bt_event_class
*event_class
= NULL
;
303 const bt_stream
*stream
= NULL
;
304 const bt_trace
*trace
= NULL
;
305 const bt_event
*event
= bt_message_event_borrow_event_const(event_msg
);
308 bt_property_availability prop_avail
;
310 event_class
= bt_event_borrow_class_const(event
);
311 stream
= bt_event_borrow_stream_const(event
);
312 trace
= bt_stream_borrow_trace_const(stream
);
313 ret
= print_event_timestamp(pretty
, event_msg
, &pretty
->start_line
);
317 if (pretty
->options
.print_trace_field
) {
320 name
= bt_trace_get_name(trace
);
322 if (!pretty
->start_line
) {
323 bt_common_g_string_append(pretty
->string
, ", ");
326 print_name_equal(pretty
, "trace");
329 bt_common_g_string_append(pretty
->string
, name
);
332 bt_common_g_string_append(pretty
->string
, ", ");
336 if (pretty
->options
.print_trace_hostname_field
) {
337 const bt_value
*hostname_str
;
339 hostname_str
= bt_trace_borrow_environment_entry_value_by_name_const(
344 if (!pretty
->start_line
) {
345 bt_common_g_string_append(pretty
->string
, ", ");
348 print_name_equal(pretty
, "trace:hostname");
350 str
= bt_value_string_get(hostname_str
);
351 bt_common_g_string_append(pretty
->string
, str
);
355 if (pretty
->options
.print_trace_domain_field
) {
356 const bt_value
*domain_str
;
358 domain_str
= bt_trace_borrow_environment_entry_value_by_name_const(
363 if (!pretty
->start_line
) {
364 bt_common_g_string_append(pretty
->string
, ", ");
367 print_name_equal(pretty
, "trace:domain");
368 } else if (dom_print
) {
369 bt_common_g_string_append(pretty
->string
, ":");
371 str
= bt_value_string_get(domain_str
);
372 bt_common_g_string_append(pretty
->string
, str
);
376 if (pretty
->options
.print_trace_procname_field
) {
377 const bt_value
*procname_str
;
379 procname_str
= bt_trace_borrow_environment_entry_value_by_name_const(
384 if (!pretty
->start_line
) {
385 bt_common_g_string_append(pretty
->string
, ", ");
388 print_name_equal(pretty
, "trace:procname");
389 } else if (dom_print
) {
390 bt_common_g_string_append(pretty
->string
, ":");
392 str
= bt_value_string_get(procname_str
);
393 bt_common_g_string_append(pretty
->string
, str
);
397 if (pretty
->options
.print_trace_vpid_field
) {
398 const bt_value
*vpid_value
;
400 vpid_value
= bt_trace_borrow_environment_entry_value_by_name_const(
405 if (!pretty
->start_line
) {
406 bt_common_g_string_append(pretty
->string
, ", ");
409 print_name_equal(pretty
, "trace:vpid");
410 } else if (dom_print
) {
411 bt_common_g_string_append(pretty
->string
, ":");
413 value
= bt_value_integer_signed_get(vpid_value
);
414 bt_common_g_string_append_printf(pretty
->string
,
415 "(%" PRId64
")", value
);
419 if (pretty
->options
.print_loglevel_field
) {
420 static const char *log_level_names
[] = {
421 [ BT_EVENT_CLASS_LOG_LEVEL_EMERGENCY
] = "TRACE_EMERG",
422 [ BT_EVENT_CLASS_LOG_LEVEL_ALERT
] = "TRACE_ALERT",
423 [ BT_EVENT_CLASS_LOG_LEVEL_CRITICAL
] = "TRACE_CRIT",
424 [ BT_EVENT_CLASS_LOG_LEVEL_ERROR
] = "TRACE_ERR",
425 [ BT_EVENT_CLASS_LOG_LEVEL_WARNING
] = "TRACE_WARNING",
426 [ BT_EVENT_CLASS_LOG_LEVEL_NOTICE
] = "TRACE_NOTICE",
427 [ BT_EVENT_CLASS_LOG_LEVEL_INFO
] = "TRACE_INFO",
428 [ BT_EVENT_CLASS_LOG_LEVEL_DEBUG_SYSTEM
] = "TRACE_DEBUG_SYSTEM",
429 [ BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROGRAM
] = "TRACE_DEBUG_PROGRAM",
430 [ BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROCESS
] = "TRACE_DEBUG_PROCESS",
431 [ BT_EVENT_CLASS_LOG_LEVEL_DEBUG_MODULE
] = "TRACE_DEBUG_MODULE",
432 [ BT_EVENT_CLASS_LOG_LEVEL_DEBUG_UNIT
] = "TRACE_DEBUG_UNIT",
433 [ BT_EVENT_CLASS_LOG_LEVEL_DEBUG_FUNCTION
] = "TRACE_DEBUG_FUNCTION",
434 [ BT_EVENT_CLASS_LOG_LEVEL_DEBUG_LINE
] = "TRACE_DEBUG_LINE",
435 [ BT_EVENT_CLASS_LOG_LEVEL_DEBUG
] = "TRACE_DEBUG",
437 bt_event_class_log_level log_level
;
438 const char *log_level_str
= NULL
;
440 prop_avail
= bt_event_class_get_log_level(event_class
,
442 if (prop_avail
== BT_PROPERTY_AVAILABILITY_AVAILABLE
) {
443 log_level_str
= log_level_names
[log_level
];
444 BT_ASSERT_DBG(log_level_str
);
446 if (!pretty
->start_line
) {
447 bt_common_g_string_append(pretty
->string
, ", ");
450 print_name_equal(pretty
, "loglevel");
451 } else if (dom_print
) {
452 bt_common_g_string_append(pretty
->string
, ":");
455 bt_common_g_string_append(pretty
->string
, log_level_str
);
456 bt_common_g_string_append_printf(
457 pretty
->string
, " (%d)", (int) log_level
);
461 if (pretty
->options
.print_emf_field
) {
464 uri_str
= bt_event_class_get_emf_uri(event_class
);
466 if (!pretty
->start_line
) {
467 bt_common_g_string_append(pretty
->string
, ", ");
470 print_name_equal(pretty
, "model.emf.uri");
471 } else if (dom_print
) {
472 bt_common_g_string_append(pretty
->string
, ":");
475 bt_common_g_string_append(pretty
->string
, uri_str
);
479 if (dom_print
&& !print_names
) {
480 bt_common_g_string_append(pretty
->string
, " ");
482 if (!pretty
->start_line
) {
483 bt_common_g_string_append(pretty
->string
, ", ");
485 pretty
->start_line
= true;
487 print_name_equal(pretty
, "name");
489 ev_name
= bt_event_class_get_name(event_class
);
490 if (pretty
->use_colors
) {
492 bt_common_g_string_append(pretty
->string
,
495 bt_common_g_string_append(pretty
->string
,
500 bt_common_g_string_append(pretty
->string
, ev_name
);
502 bt_common_g_string_append(pretty
->string
, "<unknown>");
504 if (pretty
->use_colors
) {
505 bt_common_g_string_append(pretty
->string
, color_rst
);
508 bt_common_g_string_append(pretty
->string
, ": ");
510 bt_common_g_string_append(pretty
->string
, ", ");
518 int print_integer(struct pretty_component
*pretty
,
519 const bt_field
*field
)
522 bt_field_class_integer_preferred_display_base base
;
523 const bt_field_class
*int_fc
;
528 bool rst_color
= false;
529 bt_field_class_type ft_type
;
531 int_fc
= bt_field_borrow_class_const(field
);
532 BT_ASSERT_DBG(int_fc
);
533 ft_type
= bt_field_get_class_type(field
);
534 if (bt_field_class_type_is(ft_type
,
535 BT_FIELD_CLASS_TYPE_UNSIGNED_INTEGER
)) {
536 v
.u
= bt_field_integer_unsigned_get_value(field
);
538 v
.s
= bt_field_integer_signed_get_value(field
);
541 if (pretty
->use_colors
) {
542 bt_common_g_string_append(pretty
->string
, color_number_value
);
546 base
= bt_field_class_integer_get_preferred_display_base(int_fc
);
548 case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_BINARY
:
552 len
= bt_field_class_integer_get_field_value_range(int_fc
);
553 bt_common_g_string_append(pretty
->string
, "0b");
554 _bt_safe_lshift(v
.u
, 64 - len
);
555 for (bitnr
= 0; bitnr
< len
; bitnr
++) {
556 bt_common_g_string_append_c(pretty
->string
,
557 (v
.u
& (1ULL << 63)) ? '1' : '0');
558 _bt_safe_lshift(v
.u
, 1);
562 case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_OCTAL
:
564 if (bt_field_class_type_is(ft_type
,
565 BT_FIELD_CLASS_TYPE_SIGNED_INTEGER
)) {
568 len
= bt_field_class_integer_get_field_value_range(
573 BT_ASSERT_DBG(len
!= 0);
574 /* Round length to the nearest 3-bit */
575 rounded_len
= (((len
- 1) / 3) + 1) * 3;
576 v
.u
&= ((uint64_t) 1 << rounded_len
) - 1;
580 bt_common_g_string_append_printf(pretty
->string
, "0%" PRIo64
, v
.u
);
583 case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
:
584 if (bt_field_class_type_is(ft_type
,
585 BT_FIELD_CLASS_TYPE_UNSIGNED_INTEGER
)) {
586 bt_common_g_string_append_printf(pretty
->string
, "%" PRIu64
, v
.u
);
588 bt_common_g_string_append_printf(pretty
->string
, "%" PRId64
, v
.s
);
591 case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL
:
595 len
= bt_field_class_integer_get_field_value_range(int_fc
);
597 /* Round length to the nearest nibble */
598 uint8_t rounded_len
= ((len
+ 3) & ~0x3);
600 v
.u
&= ((uint64_t) 1 << rounded_len
) - 1;
603 bt_common_g_string_append_printf(pretty
->string
, "0x%" PRIX64
, v
.u
);
612 bt_common_g_string_append(pretty
->string
, color_rst
);
618 void print_escape_string(struct pretty_component
*pretty
, const char *str
)
622 bt_common_g_string_append_c(pretty
->string
, '"');
624 for (i
= 0; i
< strlen(str
); i
++) {
625 /* Escape sequences not recognized by iscntrl(). */
628 bt_common_g_string_append(pretty
->string
, "\\\\");
631 bt_common_g_string_append(pretty
->string
, "\\\'");
634 bt_common_g_string_append(pretty
->string
, "\\\"");
637 bt_common_g_string_append(pretty
->string
, "\\\?");
641 /* Standard characters. */
642 if (!iscntrl(str
[i
])) {
643 bt_common_g_string_append_c(pretty
->string
, str
[i
]);
649 bt_common_g_string_append(pretty
->string
, "\\0");
652 bt_common_g_string_append(pretty
->string
, "\\a");
655 bt_common_g_string_append(pretty
->string
, "\\b");
658 bt_common_g_string_append(pretty
->string
, "\\e");
661 bt_common_g_string_append(pretty
->string
, "\\f");
664 bt_common_g_string_append(pretty
->string
, "\\n");
667 bt_common_g_string_append(pretty
->string
, "\\r");
670 bt_common_g_string_append(pretty
->string
, "\\t");
673 bt_common_g_string_append(pretty
->string
, "\\v");
676 /* Unhandled control-sequence, print as hex. */
677 bt_common_g_string_append_printf(pretty
->string
, "\\x%02x", str
[i
]);
682 bt_common_g_string_append_c(pretty
->string
, '"');
686 int print_enum(struct pretty_component
*pretty
,
687 const bt_field
*field
)
690 const bt_field_class
*enumeration_field_class
= NULL
;
691 bt_field_class_enumeration_mapping_label_array label_array
;
692 uint64_t label_count
;
695 enumeration_field_class
= bt_field_borrow_class_const(field
);
696 if (!enumeration_field_class
) {
701 switch (bt_field_get_class_type(field
)) {
702 case BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION
:
703 ret
= bt_field_enumeration_unsigned_get_mapping_labels(field
,
704 &label_array
, &label_count
);
706 case BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION
:
707 ret
= bt_field_enumeration_signed_get_mapping_labels(field
,
708 &label_array
, &label_count
);
719 bt_common_g_string_append(pretty
->string
, "( ");
720 if (label_count
== 0) {
721 if (pretty
->use_colors
) {
722 bt_common_g_string_append(pretty
->string
, color_unknown
);
724 bt_common_g_string_append(pretty
->string
, "<unknown>");
725 if (pretty
->use_colors
) {
726 bt_common_g_string_append(pretty
->string
, color_rst
);
730 for (i
= 0; i
< label_count
; i
++) {
731 const char *mapping_name
= label_array
[i
];
734 bt_common_g_string_append(pretty
->string
, ", ");
736 if (pretty
->use_colors
) {
737 bt_common_g_string_append(pretty
->string
, color_enum_mapping_name
);
739 print_escape_string(pretty
, mapping_name
);
740 if (pretty
->use_colors
) {
741 bt_common_g_string_append(pretty
->string
, color_rst
);
745 bt_common_g_string_append(pretty
->string
, " : container = ");
746 ret
= print_integer(pretty
, field
);
750 bt_common_g_string_append(pretty
->string
, " )");
756 int print_struct_field(struct pretty_component
*pretty
,
757 const bt_field
*_struct
,
758 const bt_field_class
*struct_class
,
759 uint64_t i
, bool print_names
, uint64_t *nr_printed_fields
)
762 const char *field_name
;
763 const bt_field
*field
= NULL
;
764 const bt_field_class_structure_member
*member
;
766 field
= bt_field_structure_borrow_member_field_by_index_const(_struct
, i
);
772 member
= bt_field_class_structure_borrow_member_by_index_const(
774 field_name
= bt_field_class_structure_member_get_name(member
);
776 if (*nr_printed_fields
> 0) {
777 bt_common_g_string_append(pretty
->string
, ", ");
779 bt_common_g_string_append(pretty
->string
, " ");
782 print_field_name_equal(pretty
, field_name
);
784 ret
= print_field(pretty
, field
, print_names
);
785 *nr_printed_fields
+= 1;
792 int print_struct(struct pretty_component
*pretty
,
793 const bt_field
*_struct
, bool print_names
)
796 const bt_field_class
*struct_class
= NULL
;
797 uint64_t nr_fields
, i
, nr_printed_fields
;
799 struct_class
= bt_field_borrow_class_const(_struct
);
805 nr_fields
= bt_field_class_structure_get_member_count(struct_class
);
807 bt_common_g_string_append(pretty
->string
, "{");
809 nr_printed_fields
= 0;
810 for (i
= 0; i
< nr_fields
; i
++) {
811 ret
= print_struct_field(pretty
, _struct
, struct_class
, i
,
812 print_names
, &nr_printed_fields
);
818 bt_common_g_string_append(pretty
->string
, " }");
825 int print_array_field(struct pretty_component
*pretty
,
826 const bt_field
*array
, uint64_t i
, bool print_names
)
828 const bt_field
*field
= NULL
;
831 bt_common_g_string_append(pretty
->string
, ", ");
833 bt_common_g_string_append(pretty
->string
, " ");
836 bt_common_g_string_append_printf(pretty
->string
, "[%" PRIu64
"] = ", i
);
839 field
= bt_field_array_borrow_element_field_by_index_const(array
, i
);
840 BT_ASSERT_DBG(field
);
841 return print_field(pretty
, field
, print_names
);
845 int print_array(struct pretty_component
*pretty
,
846 const bt_field
*array
, bool print_names
)
849 const bt_field_class
*array_class
= NULL
;
853 array_class
= bt_field_borrow_class_const(array
);
858 len
= bt_field_array_get_length(array
);
859 bt_common_g_string_append(pretty
->string
, "[");
861 for (i
= 0; i
< len
; i
++) {
862 ret
= print_array_field(pretty
, array
, i
, print_names
);
868 bt_common_g_string_append(pretty
->string
, " ]");
875 int print_sequence_field(struct pretty_component
*pretty
,
876 const bt_field
*seq
, uint64_t i
, bool print_names
)
878 const bt_field
*field
= NULL
;
881 bt_common_g_string_append(pretty
->string
, ", ");
883 bt_common_g_string_append(pretty
->string
, " ");
886 bt_common_g_string_append_printf(pretty
->string
, "[%" PRIu64
"] = ", i
);
889 field
= bt_field_array_borrow_element_field_by_index_const(seq
, i
);
890 BT_ASSERT_DBG(field
);
891 return print_field(pretty
, field
, print_names
);
895 int print_sequence(struct pretty_component
*pretty
,
896 const bt_field
*seq
, bool print_names
)
902 len
= bt_field_array_get_length(seq
);
903 bt_common_g_string_append(pretty
->string
, "[");
906 for (i
= 0; i
< len
; i
++) {
907 ret
= print_sequence_field(pretty
, seq
, i
, print_names
);
913 bt_common_g_string_append(pretty
->string
, " ]");
920 int print_option(struct pretty_component
*pretty
,
921 const bt_field
*option
, bool print_names
)
924 const bt_field
*field
= NULL
;
926 field
= bt_field_option_borrow_field_const(option
);
928 bt_common_g_string_append(pretty
->string
, "{ ");
931 // TODO: find tag's name using field path
932 // print_field_name_equal(pretty, tag_choice);
934 ret
= print_field(pretty
, field
, print_names
);
939 bt_common_g_string_append(pretty
->string
, " }");
941 bt_common_g_string_append(pretty
->string
, "<none>");
949 int print_variant(struct pretty_component
*pretty
,
950 const bt_field
*variant
, bool print_names
)
953 const bt_field
*field
= NULL
;
955 field
= bt_field_variant_borrow_selected_option_field_const(variant
);
956 BT_ASSERT_DBG(field
);
957 bt_common_g_string_append(pretty
->string
, "{ ");
960 // TODO: find tag's name using field path
961 // print_field_name_equal(pretty, tag_choice);
963 ret
= print_field(pretty
, field
, print_names
);
968 bt_common_g_string_append(pretty
->string
, " }");
975 int print_field(struct pretty_component
*pretty
,
976 const bt_field
*field
, bool print_names
)
978 bt_field_class_type class_id
;
980 class_id
= bt_field_get_class_type(field
);
981 if (class_id
== BT_FIELD_CLASS_TYPE_BOOL
) {
985 v
= bt_field_bool_get_value(field
);
986 if (pretty
->use_colors
) {
987 bt_common_g_string_append(pretty
->string
, color_number_value
);
994 bt_common_g_string_append(pretty
->string
, text
);
995 if (pretty
->use_colors
) {
996 bt_common_g_string_append(pretty
->string
, color_rst
);
999 } else if (class_id
== BT_FIELD_CLASS_TYPE_BIT_ARRAY
) {
1000 uint64_t v
= bt_field_bit_array_get_value_as_integer(field
);
1002 if (pretty
->use_colors
) {
1003 bt_common_g_string_append(pretty
->string
,
1004 color_number_value
);
1006 bt_common_g_string_append_printf(pretty
->string
, "0x%" PRIX64
,
1008 if (pretty
->use_colors
) {
1009 bt_common_g_string_append(pretty
->string
, color_rst
);
1012 } else if (bt_field_class_type_is(class_id
,
1013 BT_FIELD_CLASS_TYPE_ENUMERATION
)) {
1014 return print_enum(pretty
, field
);
1015 } else if (bt_field_class_type_is(class_id
,
1016 BT_FIELD_CLASS_TYPE_INTEGER
)) {
1017 return print_integer(pretty
, field
);
1018 } else if (bt_field_class_type_is(class_id
,
1019 BT_FIELD_CLASS_TYPE_REAL
)) {
1022 if (class_id
== BT_FIELD_CLASS_TYPE_SINGLE_PRECISION_REAL
) {
1023 v
= bt_field_real_single_precision_get_value(field
);
1025 v
= bt_field_real_double_precision_get_value(field
);
1028 if (pretty
->use_colors
) {
1029 bt_common_g_string_append(pretty
->string
, color_number_value
);
1031 bt_common_g_string_append_printf(pretty
->string
, "%g", v
);
1032 if (pretty
->use_colors
) {
1033 bt_common_g_string_append(pretty
->string
, color_rst
);
1036 } else if (class_id
== BT_FIELD_CLASS_TYPE_STRING
) {
1039 str
= bt_field_string_get_value(field
);
1044 if (pretty
->use_colors
) {
1045 bt_common_g_string_append(pretty
->string
, color_string_value
);
1047 print_escape_string(pretty
, str
);
1048 if (pretty
->use_colors
) {
1049 bt_common_g_string_append(pretty
->string
, color_rst
);
1052 } else if (class_id
== BT_FIELD_CLASS_TYPE_STRUCTURE
) {
1053 return print_struct(pretty
, field
, print_names
);
1054 } else if (bt_field_class_type_is(class_id
,
1055 BT_FIELD_CLASS_TYPE_OPTION
)) {
1056 return print_option(pretty
, field
, print_names
);
1057 } else if (bt_field_class_type_is(class_id
,
1058 BT_FIELD_CLASS_TYPE_VARIANT
)) {
1059 return print_variant(pretty
, field
, print_names
);
1060 } else if (class_id
== BT_FIELD_CLASS_TYPE_STATIC_ARRAY
) {
1061 return print_array(pretty
, field
, print_names
);
1062 } else if (bt_field_class_type_is(class_id
,
1063 BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY
)) {
1064 return print_sequence(pretty
, field
, print_names
);
1066 // TODO: log instead
1067 fprintf(pretty
->err
, "[error] Unknown type id: %d\n", (int) class_id
);
1073 int print_stream_packet_context(struct pretty_component
*pretty
,
1074 const bt_event
*event
)
1077 const bt_packet
*packet
= NULL
;
1078 const bt_field
*main_field
= NULL
;
1080 packet
= bt_event_borrow_packet_const(event
);
1084 main_field
= bt_packet_borrow_context_field_const(packet
);
1088 if (!pretty
->start_line
) {
1089 bt_common_g_string_append(pretty
->string
, ", ");
1091 pretty
->start_line
= false;
1092 if (pretty
->options
.print_scope_field_names
) {
1093 print_name_equal(pretty
, "stream.packet.context");
1095 ret
= print_field(pretty
, main_field
,
1096 pretty
->options
.print_context_field_names
);
1103 int print_stream_event_context(struct pretty_component
*pretty
,
1104 const bt_event
*event
)
1107 const bt_field
*main_field
= NULL
;
1109 main_field
= bt_event_borrow_common_context_field_const(event
);
1113 if (!pretty
->start_line
) {
1114 bt_common_g_string_append(pretty
->string
, ", ");
1116 pretty
->start_line
= false;
1117 if (pretty
->options
.print_scope_field_names
) {
1118 print_name_equal(pretty
, "stream.event.context");
1120 ret
= print_field(pretty
, main_field
,
1121 pretty
->options
.print_context_field_names
);
1128 int print_event_context(struct pretty_component
*pretty
,
1129 const bt_event
*event
)
1132 const bt_field
*main_field
= NULL
;
1134 main_field
= bt_event_borrow_specific_context_field_const(event
);
1138 if (!pretty
->start_line
) {
1139 bt_common_g_string_append(pretty
->string
, ", ");
1141 pretty
->start_line
= false;
1142 if (pretty
->options
.print_scope_field_names
) {
1143 print_name_equal(pretty
, "event.context");
1145 ret
= print_field(pretty
, main_field
,
1146 pretty
->options
.print_context_field_names
);
1153 int print_event_payload(struct pretty_component
*pretty
,
1154 const bt_event
*event
)
1157 const bt_field
*main_field
= NULL
;
1159 main_field
= bt_event_borrow_payload_field_const(event
);
1163 if (!pretty
->start_line
) {
1164 bt_common_g_string_append(pretty
->string
, ", ");
1166 pretty
->start_line
= false;
1167 if (pretty
->options
.print_scope_field_names
) {
1168 print_name_equal(pretty
, "event.fields");
1170 ret
= print_field(pretty
, main_field
,
1171 pretty
->options
.print_payload_field_names
);
1178 int flush_buf(FILE *stream
, struct pretty_component
*pretty
)
1182 if (pretty
->string
->len
== 0) {
1186 if (fwrite(pretty
->string
->str
, pretty
->string
->len
, 1, stream
) != 1) {
1195 int pretty_print_event(struct pretty_component
*pretty
,
1196 const bt_message
*event_msg
)
1199 const bt_event
*event
=
1200 bt_message_event_borrow_event_const(event_msg
);
1202 BT_ASSERT_DBG(event
);
1203 pretty
->start_line
= true;
1204 g_string_assign(pretty
->string
, "");
1205 ret
= print_event_header(pretty
, event_msg
);
1210 ret
= print_stream_packet_context(pretty
, event
);
1215 ret
= print_stream_event_context(pretty
, event
);
1220 ret
= print_event_context(pretty
, event
);
1225 ret
= print_event_payload(pretty
, event
);
1230 bt_common_g_string_append_c(pretty
->string
, '\n');
1231 if (flush_buf(pretty
->out
, pretty
)) {
1241 int print_discarded_elements_msg(struct pretty_component
*pretty
,
1242 const bt_stream
*stream
,
1243 const bt_clock_snapshot
*begin_clock_snapshot
,
1244 const bt_clock_snapshot
*end_clock_snapshot
,
1245 uint64_t count
, const char *elem_type
)
1248 const bt_stream_class
*stream_class
= NULL
;
1249 const bt_trace
*trace
= NULL
;
1250 const char *stream_name
;
1251 const char *trace_name
;
1253 int64_t stream_class_id
;
1255 const char *init_msg
;
1258 stream_name
= bt_stream_get_name(stream
);
1260 stream_name
= "(unknown)";
1263 /* Stream class ID */
1264 stream_class
= bt_stream_borrow_class_const(stream
);
1265 BT_ASSERT(stream_class
);
1266 stream_class_id
= bt_stream_class_get_id(stream_class
);
1269 stream_id
= bt_stream_get_id(stream
);
1272 trace
= bt_stream_borrow_trace_const(stream
);
1274 trace_name
= bt_trace_get_name(trace
);
1276 trace_name
= "(unknown)";
1280 trace_uuid
= bt_trace_get_uuid(trace
);
1282 /* Format message */
1283 g_string_assign(pretty
->string
, "");
1285 if (count
== UINT64_C(-1)) {
1286 init_msg
= "Tracer may have discarded";
1288 init_msg
= "Tracer discarded";
1291 bt_common_g_string_append_printf(pretty
->string
,
1292 "%s%sWARNING%s%s: %s ",
1293 bt_common_color_fg_yellow(),
1294 bt_common_color_bold(),
1295 bt_common_color_reset(),
1296 bt_common_color_fg_yellow(), init_msg
);
1298 if (count
== UINT64_C(-1)) {
1299 bt_common_g_string_append_printf(pretty
->string
, "%ss", elem_type
);
1301 bt_common_g_string_append_printf(pretty
->string
,
1302 "%" PRIu64
" %s%s", count
, elem_type
,
1303 count
== 1 ? "" : "s");
1306 bt_common_g_string_append_c(pretty
->string
, ' ');
1308 if (begin_clock_snapshot
&& end_clock_snapshot
) {
1309 bt_common_g_string_append(pretty
->string
, "between [");
1310 print_timestamp_wall(pretty
, begin_clock_snapshot
, false);
1311 bt_common_g_string_append(pretty
->string
, "] and [");
1312 print_timestamp_wall(pretty
, end_clock_snapshot
, false);
1313 bt_common_g_string_append(pretty
->string
, "]");
1315 bt_common_g_string_append(pretty
->string
, "(unknown time range)");
1318 bt_common_g_string_append_printf(pretty
->string
, " in trace \"%s\" ", trace_name
);
1321 bt_common_g_string_append_printf(pretty
->string
,
1322 "(UUID: " BT_UUID_FMT
") ",
1323 BT_UUID_FMT_VALUES(trace_uuid
));
1325 bt_common_g_string_append(pretty
->string
, "(no UUID) ");
1328 bt_common_g_string_append_printf(pretty
->string
,
1329 "within stream \"%s\" (stream class ID: %" PRIu64
", ",
1330 stream_name
, stream_class_id
);
1332 if (stream_id
>= 0) {
1333 bt_common_g_string_append_printf(pretty
->string
,
1334 "stream ID: %" PRIu64
, stream_id
);
1336 bt_common_g_string_append(pretty
->string
, "no stream ID");
1339 bt_common_g_string_append_printf(pretty
->string
, ").%s\n",
1340 bt_common_color_reset());
1343 * Print to standard error stream to remain backward compatible
1344 * with Babeltrace 1.
1346 if (flush_buf(stderr
, pretty
)) {
1354 int pretty_print_discarded_items(struct pretty_component
*pretty
,
1355 const bt_message
*msg
)
1357 const bt_clock_snapshot
*begin
= NULL
;
1358 const bt_clock_snapshot
*end
= NULL
;
1359 const bt_stream
*stream
;
1360 const bt_stream_class
*stream_class
;
1361 uint64_t count
= UINT64_C(-1);
1362 const char *elem_type
;
1364 switch (bt_message_get_type(msg
)) {
1365 case BT_MESSAGE_TYPE_DISCARDED_EVENTS
:
1366 stream
= bt_message_discarded_events_borrow_stream_const(msg
);
1368 if (bt_message_discarded_events_get_count(msg
, &count
) ==
1369 BT_PROPERTY_AVAILABILITY_NOT_AVAILABLE
) {
1370 count
= UINT64_C(-1);
1373 elem_type
= "event";
1375 case BT_MESSAGE_TYPE_DISCARDED_PACKETS
:
1376 stream
= bt_message_discarded_packets_borrow_stream_const(msg
);
1378 if (bt_message_discarded_packets_get_count(msg
, &count
) ==
1379 BT_PROPERTY_AVAILABILITY_NOT_AVAILABLE
) {
1380 count
= UINT64_C(-1);
1383 elem_type
= "packet";
1390 stream_class
= bt_stream_borrow_class_const(stream
);
1392 switch (bt_message_get_type(msg
)) {
1393 case BT_MESSAGE_TYPE_DISCARDED_EVENTS
:
1394 if (bt_stream_class_discarded_events_have_default_clock_snapshots(
1396 begin
= bt_message_discarded_events_borrow_beginning_default_clock_snapshot_const(
1398 end
= bt_message_discarded_events_borrow_end_default_clock_snapshot_const(
1403 case BT_MESSAGE_TYPE_DISCARDED_PACKETS
:
1404 if (bt_stream_class_discarded_packets_have_default_clock_snapshots(
1406 begin
= bt_message_discarded_packets_borrow_beginning_default_clock_snapshot_const(
1408 end
= bt_message_discarded_packets_borrow_end_default_clock_snapshot_const(
1417 print_discarded_elements_msg(pretty
, stream
, begin
, end
,
1423 void pretty_print_init(void)
1425 strcpy(color_name
, bt_common_color_bold());
1426 strcpy(color_field_name
, bt_common_color_fg_cyan());
1427 strcpy(color_rst
, bt_common_color_reset());
1428 strcpy(color_string_value
, bt_common_color_bold());
1429 strcpy(color_number_value
, bt_common_color_bold());
1430 strcpy(color_enum_mapping_name
, bt_common_color_bold());
1431 strcpy(color_unknown
, bt_common_color_bold());
1432 strcat(color_unknown
, bt_common_color_fg_bright_red());
1433 strcpy(color_event_name
, bt_common_color_bold());
1434 strcat(color_event_name
, bt_common_color_fg_bright_magenta());
1435 strcpy(color_timestamp
, bt_common_color_bold());
1436 strcat(color_timestamp
, bt_common_color_fg_bright_yellow());