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"
37 #define NSEC_PER_SEC 1000000000LL
39 #define COLOR_NAME BT_COMMON_COLOR_BOLD
40 #define COLOR_FIELD_NAME BT_COMMON_COLOR_FG_CYAN
41 #define COLOR_RST BT_COMMON_COLOR_RESET
42 #define COLOR_STRING_VALUE BT_COMMON_COLOR_BOLD
43 #define COLOR_NUMBER_VALUE BT_COMMON_COLOR_BOLD
44 #define COLOR_ENUM_MAPPING_NAME BT_COMMON_COLOR_BOLD
45 #define COLOR_UNKNOWN BT_COMMON_COLOR_BOLD BT_COMMON_COLOR_FG_RED
46 #define COLOR_EVENT_NAME BT_COMMON_COLOR_BOLD BT_COMMON_COLOR_FG_MAGENTA
47 #define COLOR_TIMESTAMP BT_COMMON_COLOR_BOLD BT_COMMON_COLOR_FG_YELLOW
50 int64_t real_timestamp
; /* Relative to UNIX epoch. */
51 uint64_t clock_snapshot
; /* In cycles. */
55 int print_field(struct pretty_component
*pretty
,
56 const bt_field
*field
, bool print_names
);
59 void print_name_equal(struct pretty_component
*pretty
, const char *name
)
61 if (pretty
->use_colors
) {
62 bt_common_g_string_append(pretty
->string
, COLOR_NAME
);
63 bt_common_g_string_append(pretty
->string
, name
);
64 bt_common_g_string_append(pretty
->string
, COLOR_RST
);
66 bt_common_g_string_append(pretty
->string
, name
);
68 bt_common_g_string_append(pretty
->string
, " = ");
72 void print_field_name_equal(struct pretty_component
*pretty
, const char *name
)
74 if (pretty
->use_colors
) {
75 bt_common_g_string_append(pretty
->string
, COLOR_FIELD_NAME
);
76 bt_common_g_string_append(pretty
->string
, name
);
77 bt_common_g_string_append(pretty
->string
, COLOR_RST
);
79 bt_common_g_string_append(pretty
->string
, name
);
81 bt_common_g_string_append(pretty
->string
, " = ");
85 void print_timestamp_cycles(struct pretty_component
*pretty
,
86 const bt_clock_snapshot
*clock_snapshot
, bool update_last
)
90 cycles
= bt_clock_snapshot_get_value(clock_snapshot
);
91 bt_common_g_string_append_printf(pretty
->string
, "%020" PRIu64
, cycles
);
94 if (pretty
->last_cycles_timestamp
!= -1ULL) {
95 pretty
->delta_cycles
= cycles
- pretty
->last_cycles_timestamp
;
98 pretty
->last_cycles_timestamp
= cycles
;
103 void print_timestamp_wall(struct pretty_component
*pretty
,
104 const bt_clock_snapshot
*clock_snapshot
, bool update_last
)
107 int64_t ts_nsec
= 0; /* add configurable offset */
108 int64_t ts_sec
= 0; /* add configurable offset */
109 uint64_t ts_sec_abs
, ts_nsec_abs
;
112 if (!clock_snapshot
) {
113 bt_common_g_string_append(pretty
->string
, "??:??:??.?????????");
117 ret
= bt_clock_snapshot_get_ns_from_origin(clock_snapshot
, &ts_nsec
);
119 // TODO: log, this is unexpected
120 bt_common_g_string_append(pretty
->string
, "Error");
125 if (pretty
->last_real_timestamp
!= -1ULL) {
126 pretty
->delta_real_timestamp
= ts_nsec
- pretty
->last_real_timestamp
;
129 pretty
->last_real_timestamp
= ts_nsec
;
132 ts_sec
+= ts_nsec
/ NSEC_PER_SEC
;
133 ts_nsec
= ts_nsec
% NSEC_PER_SEC
;
135 if (ts_sec
>= 0 && ts_nsec
>= 0) {
138 ts_nsec_abs
= ts_nsec
;
139 } else if (ts_sec
> 0 && ts_nsec
< 0) {
141 ts_sec_abs
= ts_sec
- 1;
142 ts_nsec_abs
= NSEC_PER_SEC
+ ts_nsec
;
143 } else if (ts_sec
== 0 && ts_nsec
< 0) {
146 ts_nsec_abs
= -ts_nsec
;
147 } else if (ts_sec
< 0 && ts_nsec
> 0) {
149 ts_sec_abs
= -(ts_sec
+ 1);
150 ts_nsec_abs
= NSEC_PER_SEC
- ts_nsec
;
151 } else if (ts_sec
< 0 && ts_nsec
== 0) {
153 ts_sec_abs
= -ts_sec
;
154 ts_nsec_abs
= ts_nsec
;
155 } else { /* (ts_sec < 0 && ts_nsec < 0) */
157 ts_sec_abs
= -ts_sec
;
158 ts_nsec_abs
= -ts_nsec
;
161 if (!pretty
->options
.clock_seconds
) {
163 time_t time_s
= (time_t) ts_sec_abs
;
165 if (is_negative
&& !pretty
->negative_timestamp_warning_done
) {
167 fprintf(stderr
, "[warning] Fallback to [sec.ns] to print negative time value. Use --clock-seconds.\n");
168 pretty
->negative_timestamp_warning_done
= true;
172 if (!pretty
->options
.clock_gmt
) {
175 res
= bt_localtime_r(&time_s
, &tm
);
178 fprintf(stderr
, "[warning] Unable to get localtime.\n");
184 res
= bt_gmtime_r(&time_s
, &tm
);
187 fprintf(stderr
, "[warning] Unable to get gmtime.\n");
191 if (pretty
->options
.clock_date
) {
195 /* Print date and time */
196 res
= strftime(timestr
, sizeof(timestr
),
200 fprintf(stderr
, "[warning] Unable to print ascii time.\n");
204 bt_common_g_string_append(pretty
->string
, timestr
);
207 /* Print time in HH:MM:SS.ns */
208 bt_common_g_string_append_printf(pretty
->string
,
209 "%02d:%02d:%02d.%09" PRIu64
, tm
.tm_hour
, tm
.tm_min
,
210 tm
.tm_sec
, ts_nsec_abs
);
214 bt_common_g_string_append_printf(pretty
->string
, "%s%" PRId64
".%09" PRIu64
,
215 is_negative
? "-" : "", ts_sec_abs
, ts_nsec_abs
);
221 int print_event_timestamp(struct pretty_component
*pretty
,
222 const bt_message
*event_msg
, bool *start_line
)
224 bool print_names
= pretty
->options
.print_header_field_names
;
226 const bt_clock_snapshot
*clock_snapshot
= NULL
;
228 if (!bt_message_event_borrow_stream_class_default_clock_class_const(
230 /* No default clock class: skip the timestamp without an error */
234 clock_snapshot
= bt_message_event_borrow_default_clock_snapshot_const(event_msg
);
237 print_name_equal(pretty
, "timestamp");
239 bt_common_g_string_append(pretty
->string
, "[");
241 if (pretty
->use_colors
) {
242 bt_common_g_string_append(pretty
->string
, COLOR_TIMESTAMP
);
244 if (pretty
->options
.print_timestamp_cycles
) {
245 print_timestamp_cycles(pretty
, clock_snapshot
, true);
247 print_timestamp_wall(pretty
, clock_snapshot
, true);
249 if (pretty
->use_colors
) {
250 bt_common_g_string_append(pretty
->string
, COLOR_RST
);
254 bt_common_g_string_append(pretty
->string
, "] ");
256 if (pretty
->options
.print_delta_field
) {
258 bt_common_g_string_append(pretty
->string
, ", ");
259 print_name_equal(pretty
, "delta");
261 bt_common_g_string_append(pretty
->string
, "(");
263 if (pretty
->options
.print_timestamp_cycles
) {
264 if (pretty
->delta_cycles
== -1ULL) {
265 bt_common_g_string_append(pretty
->string
,
266 "+??????????\?\?"); /* Not a trigraph. */
268 bt_common_g_string_append_printf(pretty
->string
,
269 "+%012" PRIu64
, pretty
->delta_cycles
);
272 if (pretty
->delta_real_timestamp
!= -1ULL) {
273 uint64_t delta_sec
, delta_nsec
, delta
;
275 delta
= pretty
->delta_real_timestamp
;
276 delta_sec
= delta
/ NSEC_PER_SEC
;
277 delta_nsec
= delta
% NSEC_PER_SEC
;
278 bt_common_g_string_append_printf(pretty
->string
,
279 "+%" PRIu64
".%09" PRIu64
,
280 delta_sec
, delta_nsec
);
282 bt_common_g_string_append(pretty
->string
, "+?.?????????");
286 bt_common_g_string_append(pretty
->string
, ") ");
289 *start_line
= !print_names
;
296 int print_event_header(struct pretty_component
*pretty
,
297 const bt_message
*event_msg
)
299 bool print_names
= pretty
->options
.print_header_field_names
;
301 const bt_event_class
*event_class
= NULL
;
302 const bt_stream
*stream
= NULL
;
303 const bt_trace
*trace
= NULL
;
304 const bt_event
*event
= bt_message_event_borrow_event_const(event_msg
);
307 bt_property_availability prop_avail
;
309 event_class
= bt_event_borrow_class_const(event
);
310 stream
= bt_event_borrow_stream_const(event
);
311 trace
= bt_stream_borrow_trace_const(stream
);
312 ret
= print_event_timestamp(pretty
, event_msg
, &pretty
->start_line
);
316 if (pretty
->options
.print_trace_field
) {
319 name
= bt_trace_get_name(trace
);
321 if (!pretty
->start_line
) {
322 bt_common_g_string_append(pretty
->string
, ", ");
325 print_name_equal(pretty
, "trace");
328 bt_common_g_string_append(pretty
->string
, name
);
331 bt_common_g_string_append(pretty
->string
, ", ");
335 if (pretty
->options
.print_trace_hostname_field
) {
336 const bt_value
*hostname_str
;
338 hostname_str
= bt_trace_borrow_environment_entry_value_by_name_const(
343 if (!pretty
->start_line
) {
344 bt_common_g_string_append(pretty
->string
, ", ");
347 print_name_equal(pretty
, "trace:hostname");
349 str
= bt_value_string_get(hostname_str
);
350 bt_common_g_string_append(pretty
->string
, str
);
354 if (pretty
->options
.print_trace_domain_field
) {
355 const bt_value
*domain_str
;
357 domain_str
= bt_trace_borrow_environment_entry_value_by_name_const(
362 if (!pretty
->start_line
) {
363 bt_common_g_string_append(pretty
->string
, ", ");
366 print_name_equal(pretty
, "trace:domain");
367 } else if (dom_print
) {
368 bt_common_g_string_append(pretty
->string
, ":");
370 str
= bt_value_string_get(domain_str
);
371 bt_common_g_string_append(pretty
->string
, str
);
375 if (pretty
->options
.print_trace_procname_field
) {
376 const bt_value
*procname_str
;
378 procname_str
= bt_trace_borrow_environment_entry_value_by_name_const(
383 if (!pretty
->start_line
) {
384 bt_common_g_string_append(pretty
->string
, ", ");
387 print_name_equal(pretty
, "trace:procname");
388 } else if (dom_print
) {
389 bt_common_g_string_append(pretty
->string
, ":");
391 str
= bt_value_string_get(procname_str
);
392 bt_common_g_string_append(pretty
->string
, str
);
396 if (pretty
->options
.print_trace_vpid_field
) {
397 const bt_value
*vpid_value
;
399 vpid_value
= bt_trace_borrow_environment_entry_value_by_name_const(
404 if (!pretty
->start_line
) {
405 bt_common_g_string_append(pretty
->string
, ", ");
408 print_name_equal(pretty
, "trace:vpid");
409 } else if (dom_print
) {
410 bt_common_g_string_append(pretty
->string
, ":");
412 value
= bt_value_integer_signed_get(vpid_value
);
413 bt_common_g_string_append_printf(pretty
->string
,
414 "(%" PRId64
")", value
);
418 if (pretty
->options
.print_loglevel_field
) {
419 static const char *log_level_names
[] = {
420 [ BT_EVENT_CLASS_LOG_LEVEL_EMERGENCY
] = "TRACE_EMERG",
421 [ BT_EVENT_CLASS_LOG_LEVEL_ALERT
] = "TRACE_ALERT",
422 [ BT_EVENT_CLASS_LOG_LEVEL_CRITICAL
] = "TRACE_CRIT",
423 [ BT_EVENT_CLASS_LOG_LEVEL_ERROR
] = "TRACE_ERR",
424 [ BT_EVENT_CLASS_LOG_LEVEL_WARNING
] = "TRACE_WARNING",
425 [ BT_EVENT_CLASS_LOG_LEVEL_NOTICE
] = "TRACE_NOTICE",
426 [ BT_EVENT_CLASS_LOG_LEVEL_INFO
] = "TRACE_INFO",
427 [ BT_EVENT_CLASS_LOG_LEVEL_DEBUG_SYSTEM
] = "TRACE_DEBUG_SYSTEM",
428 [ BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROGRAM
] = "TRACE_DEBUG_PROGRAM",
429 [ BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROCESS
] = "TRACE_DEBUG_PROCESS",
430 [ BT_EVENT_CLASS_LOG_LEVEL_DEBUG_MODULE
] = "TRACE_DEBUG_MODULE",
431 [ BT_EVENT_CLASS_LOG_LEVEL_DEBUG_UNIT
] = "TRACE_DEBUG_UNIT",
432 [ BT_EVENT_CLASS_LOG_LEVEL_DEBUG_FUNCTION
] = "TRACE_DEBUG_FUNCTION",
433 [ BT_EVENT_CLASS_LOG_LEVEL_DEBUG_LINE
] = "TRACE_DEBUG_LINE",
434 [ BT_EVENT_CLASS_LOG_LEVEL_DEBUG
] = "TRACE_DEBUG",
436 bt_event_class_log_level log_level
;
437 const char *log_level_str
= NULL
;
439 prop_avail
= bt_event_class_get_log_level(event_class
,
441 if (prop_avail
== BT_PROPERTY_AVAILABILITY_AVAILABLE
) {
442 log_level_str
= log_level_names
[log_level
];
443 BT_ASSERT(log_level_str
);
445 if (!pretty
->start_line
) {
446 bt_common_g_string_append(pretty
->string
, ", ");
449 print_name_equal(pretty
, "loglevel");
450 } else if (dom_print
) {
451 bt_common_g_string_append(pretty
->string
, ":");
454 bt_common_g_string_append(pretty
->string
, log_level_str
);
455 bt_common_g_string_append_printf(
456 pretty
->string
, " (%d)", (int) log_level
);
460 if (pretty
->options
.print_emf_field
) {
463 uri_str
= bt_event_class_get_emf_uri(event_class
);
465 if (!pretty
->start_line
) {
466 bt_common_g_string_append(pretty
->string
, ", ");
469 print_name_equal(pretty
, "model.emf.uri");
470 } else if (dom_print
) {
471 bt_common_g_string_append(pretty
->string
, ":");
474 bt_common_g_string_append(pretty
->string
, uri_str
);
478 if (dom_print
&& !print_names
) {
479 bt_common_g_string_append(pretty
->string
, " ");
481 if (!pretty
->start_line
) {
482 bt_common_g_string_append(pretty
->string
, ", ");
484 pretty
->start_line
= true;
486 print_name_equal(pretty
, "name");
488 ev_name
= bt_event_class_get_name(event_class
);
489 if (pretty
->use_colors
) {
491 bt_common_g_string_append(pretty
->string
,
494 bt_common_g_string_append(pretty
->string
,
499 bt_common_g_string_append(pretty
->string
, ev_name
);
501 bt_common_g_string_append(pretty
->string
, "<unknown>");
503 if (pretty
->use_colors
) {
504 bt_common_g_string_append(pretty
->string
, COLOR_RST
);
507 bt_common_g_string_append(pretty
->string
, ": ");
509 bt_common_g_string_append(pretty
->string
, ", ");
517 int print_integer(struct pretty_component
*pretty
,
518 const bt_field
*field
)
521 bt_field_class_integer_preferred_display_base base
;
522 const bt_field_class
*int_fc
;
527 bool rst_color
= false;
528 bt_field_class_type ft_type
;
530 int_fc
= bt_field_borrow_class_const(field
);
532 ft_type
= bt_field_get_class_type(field
);
533 if (ft_type
== BT_FIELD_CLASS_TYPE_UNSIGNED_INTEGER
||
534 ft_type
== BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION
) {
535 v
.u
= bt_field_integer_unsigned_get_value(field
);
537 v
.s
= bt_field_integer_signed_get_value(field
);
540 if (pretty
->use_colors
) {
541 bt_common_g_string_append(pretty
->string
, COLOR_NUMBER_VALUE
);
545 base
= bt_field_class_integer_get_preferred_display_base(int_fc
);
547 case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_BINARY
:
551 len
= bt_field_class_integer_get_field_value_range(int_fc
);
552 bt_common_g_string_append(pretty
->string
, "0b");
553 _bt_safe_lshift(v
.u
, 64 - len
);
554 for (bitnr
= 0; bitnr
< len
; bitnr
++) {
555 bt_common_g_string_append_c(pretty
->string
,
556 (v
.u
& (1ULL << 63)) ? '1' : '0');
557 _bt_safe_lshift(v
.u
, 1);
561 case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_OCTAL
:
563 if (ft_type
== BT_FIELD_CLASS_TYPE_SIGNED_INTEGER
||
564 ft_type
== BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION
) {
567 len
= bt_field_class_integer_get_field_value_range(
573 /* Round length to the nearest 3-bit */
574 rounded_len
= (((len
- 1) / 3) + 1) * 3;
575 v
.u
&= ((uint64_t) 1 << rounded_len
) - 1;
579 bt_common_g_string_append_printf(pretty
->string
, "0%" PRIo64
, v
.u
);
582 case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
:
583 if (ft_type
== BT_FIELD_CLASS_TYPE_UNSIGNED_INTEGER
||
584 ft_type
== BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION
) {
585 bt_common_g_string_append_printf(pretty
->string
, "%" PRIu64
, v
.u
);
587 bt_common_g_string_append_printf(pretty
->string
, "%" PRId64
, v
.s
);
590 case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL
:
594 len
= bt_field_class_integer_get_field_value_range(int_fc
);
596 /* Round length to the nearest nibble */
597 uint8_t rounded_len
= ((len
+ 3) & ~0x3);
599 v
.u
&= ((uint64_t) 1 << rounded_len
) - 1;
602 bt_common_g_string_append_printf(pretty
->string
, "0x%" PRIX64
, v
.u
);
611 bt_common_g_string_append(pretty
->string
, COLOR_RST
);
617 void print_escape_string(struct pretty_component
*pretty
, const char *str
)
621 bt_common_g_string_append_c(pretty
->string
, '"');
623 for (i
= 0; i
< strlen(str
); i
++) {
624 /* Escape sequences not recognized by iscntrl(). */
627 bt_common_g_string_append(pretty
->string
, "\\\\");
630 bt_common_g_string_append(pretty
->string
, "\\\'");
633 bt_common_g_string_append(pretty
->string
, "\\\"");
636 bt_common_g_string_append(pretty
->string
, "\\\?");
640 /* Standard characters. */
641 if (!iscntrl(str
[i
])) {
642 bt_common_g_string_append_c(pretty
->string
, str
[i
]);
648 bt_common_g_string_append(pretty
->string
, "\\0");
651 bt_common_g_string_append(pretty
->string
, "\\a");
654 bt_common_g_string_append(pretty
->string
, "\\b");
657 bt_common_g_string_append(pretty
->string
, "\\e");
660 bt_common_g_string_append(pretty
->string
, "\\f");
663 bt_common_g_string_append(pretty
->string
, "\\n");
666 bt_common_g_string_append(pretty
->string
, "\\r");
669 bt_common_g_string_append(pretty
->string
, "\\t");
672 bt_common_g_string_append(pretty
->string
, "\\v");
675 /* Unhandled control-sequence, print as hex. */
676 bt_common_g_string_append_printf(pretty
->string
, "\\x%02x", str
[i
]);
681 bt_common_g_string_append_c(pretty
->string
, '"');
685 int print_enum(struct pretty_component
*pretty
,
686 const bt_field
*field
)
689 const bt_field_class
*enumeration_field_class
= NULL
;
690 bt_field_class_enumeration_mapping_label_array label_array
;
691 uint64_t label_count
;
694 enumeration_field_class
= bt_field_borrow_class_const(field
);
695 if (!enumeration_field_class
) {
700 switch (bt_field_get_class_type(field
)) {
701 case BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION
:
702 ret
= bt_field_enumeration_unsigned_get_mapping_labels(field
,
703 &label_array
, &label_count
);
705 case BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION
:
706 ret
= bt_field_enumeration_signed_get_mapping_labels(field
,
707 &label_array
, &label_count
);
718 bt_common_g_string_append(pretty
->string
, "( ");
719 if (label_count
== 0) {
720 if (pretty
->use_colors
) {
721 bt_common_g_string_append(pretty
->string
, COLOR_UNKNOWN
);
723 bt_common_g_string_append(pretty
->string
, "<unknown>");
724 if (pretty
->use_colors
) {
725 bt_common_g_string_append(pretty
->string
, COLOR_RST
);
729 for (i
= 0; i
< label_count
; i
++) {
730 const char *mapping_name
= label_array
[i
];
733 bt_common_g_string_append(pretty
->string
, ", ");
735 if (pretty
->use_colors
) {
736 bt_common_g_string_append(pretty
->string
, COLOR_ENUM_MAPPING_NAME
);
738 print_escape_string(pretty
, mapping_name
);
739 if (pretty
->use_colors
) {
740 bt_common_g_string_append(pretty
->string
, COLOR_RST
);
744 bt_common_g_string_append(pretty
->string
, " : container = ");
745 ret
= print_integer(pretty
, field
);
749 bt_common_g_string_append(pretty
->string
, " )");
755 int print_struct_field(struct pretty_component
*pretty
,
756 const bt_field
*_struct
,
757 const bt_field_class
*struct_class
,
758 uint64_t i
, bool print_names
, uint64_t *nr_printed_fields
)
761 const char *field_name
;
762 const bt_field
*field
= NULL
;
763 const bt_field_class_structure_member
*member
;
765 field
= bt_field_structure_borrow_member_field_by_index_const(_struct
, i
);
771 member
= bt_field_class_structure_borrow_member_by_index_const(
773 field_name
= bt_field_class_structure_member_get_name(member
);
775 if (*nr_printed_fields
> 0) {
776 bt_common_g_string_append(pretty
->string
, ", ");
778 bt_common_g_string_append(pretty
->string
, " ");
781 print_field_name_equal(pretty
, field_name
);
783 ret
= print_field(pretty
, field
, print_names
);
784 *nr_printed_fields
+= 1;
791 int print_struct(struct pretty_component
*pretty
,
792 const bt_field
*_struct
, bool print_names
)
795 const bt_field_class
*struct_class
= NULL
;
796 uint64_t nr_fields
, i
, nr_printed_fields
;
798 struct_class
= bt_field_borrow_class_const(_struct
);
804 nr_fields
= bt_field_class_structure_get_member_count(struct_class
);
806 bt_common_g_string_append(pretty
->string
, "{");
808 nr_printed_fields
= 0;
809 for (i
= 0; i
< nr_fields
; i
++) {
810 ret
= print_struct_field(pretty
, _struct
, struct_class
, i
,
811 print_names
, &nr_printed_fields
);
817 bt_common_g_string_append(pretty
->string
, " }");
824 int print_array_field(struct pretty_component
*pretty
,
825 const bt_field
*array
, uint64_t i
, bool print_names
)
827 const bt_field
*field
= NULL
;
830 bt_common_g_string_append(pretty
->string
, ", ");
832 bt_common_g_string_append(pretty
->string
, " ");
835 bt_common_g_string_append_printf(pretty
->string
, "[%" PRIu64
"] = ", i
);
838 field
= bt_field_array_borrow_element_field_by_index_const(array
, i
);
840 return print_field(pretty
, field
, print_names
);
844 int print_array(struct pretty_component
*pretty
,
845 const bt_field
*array
, bool print_names
)
848 const bt_field_class
*array_class
= NULL
;
852 array_class
= bt_field_borrow_class_const(array
);
857 len
= bt_field_array_get_length(array
);
858 bt_common_g_string_append(pretty
->string
, "[");
860 for (i
= 0; i
< len
; i
++) {
861 ret
= print_array_field(pretty
, array
, i
, print_names
);
867 bt_common_g_string_append(pretty
->string
, " ]");
874 int print_sequence_field(struct pretty_component
*pretty
,
875 const bt_field
*seq
, uint64_t i
, bool print_names
)
877 const bt_field
*field
= NULL
;
880 bt_common_g_string_append(pretty
->string
, ", ");
882 bt_common_g_string_append(pretty
->string
, " ");
885 bt_common_g_string_append_printf(pretty
->string
, "[%" PRIu64
"] = ", i
);
888 field
= bt_field_array_borrow_element_field_by_index_const(seq
, i
);
890 return print_field(pretty
, field
, print_names
);
894 int print_sequence(struct pretty_component
*pretty
,
895 const bt_field
*seq
, bool print_names
)
901 len
= bt_field_array_get_length(seq
);
902 bt_common_g_string_append(pretty
->string
, "[");
905 for (i
= 0; i
< len
; i
++) {
906 ret
= print_sequence_field(pretty
, seq
, i
, print_names
);
912 bt_common_g_string_append(pretty
->string
, " ]");
919 int print_option(struct pretty_component
*pretty
,
920 const bt_field
*option
, bool print_names
)
923 const bt_field
*field
= NULL
;
925 field
= bt_field_option_borrow_field_const(option
);
927 bt_common_g_string_append(pretty
->string
, "{ ");
930 // TODO: find tag's name using field path
931 // print_field_name_equal(pretty, tag_choice);
933 ret
= print_field(pretty
, field
, print_names
);
938 bt_common_g_string_append(pretty
->string
, " }");
940 bt_common_g_string_append(pretty
->string
, "<none>");
948 int print_variant(struct pretty_component
*pretty
,
949 const bt_field
*variant
, bool print_names
)
952 const bt_field
*field
= NULL
;
954 field
= bt_field_variant_borrow_selected_option_field_const(variant
);
956 bt_common_g_string_append(pretty
->string
, "{ ");
959 // TODO: find tag's name using field path
960 // print_field_name_equal(pretty, tag_choice);
962 ret
= print_field(pretty
, field
, print_names
);
967 bt_common_g_string_append(pretty
->string
, " }");
974 int print_field(struct pretty_component
*pretty
,
975 const bt_field
*field
, bool print_names
)
977 bt_field_class_type class_id
;
979 class_id
= bt_field_get_class_type(field
);
981 case BT_FIELD_CLASS_TYPE_BOOL
:
986 v
= bt_field_bool_get_value(field
);
987 if (pretty
->use_colors
) {
988 bt_common_g_string_append(pretty
->string
, COLOR_NUMBER_VALUE
);
995 bt_common_g_string_append(pretty
->string
, text
);
996 if (pretty
->use_colors
) {
997 bt_common_g_string_append(pretty
->string
, COLOR_RST
);
1001 case BT_FIELD_CLASS_TYPE_BIT_ARRAY
:
1003 uint64_t v
= bt_field_bit_array_get_value_as_integer(field
);
1005 if (pretty
->use_colors
) {
1006 bt_common_g_string_append(pretty
->string
,
1007 COLOR_NUMBER_VALUE
);
1009 bt_common_g_string_append_printf(pretty
->string
, "0x%" PRIX64
,
1011 if (pretty
->use_colors
) {
1012 bt_common_g_string_append(pretty
->string
, COLOR_RST
);
1016 case BT_FIELD_CLASS_TYPE_UNSIGNED_INTEGER
:
1017 case BT_FIELD_CLASS_TYPE_SIGNED_INTEGER
:
1018 return print_integer(pretty
, field
);
1019 case BT_FIELD_CLASS_TYPE_SINGLE_PRECISION_REAL
:
1020 case BT_FIELD_CLASS_TYPE_DOUBLE_PRECISION_REAL
:
1024 if (class_id
== BT_FIELD_CLASS_TYPE_SINGLE_PRECISION_REAL
) {
1025 v
= (float) bt_field_real_single_precision_get_value(field
);
1027 v
= bt_field_real_double_precision_get_value(field
);
1030 if (pretty
->use_colors
) {
1031 bt_common_g_string_append(pretty
->string
, COLOR_NUMBER_VALUE
);
1033 bt_common_g_string_append_printf(pretty
->string
, "%g", v
);
1034 if (pretty
->use_colors
) {
1035 bt_common_g_string_append(pretty
->string
, COLOR_RST
);
1039 case BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION
:
1040 case BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION
:
1041 return print_enum(pretty
, field
);
1042 case BT_FIELD_CLASS_TYPE_STRING
:
1046 str
= bt_field_string_get_value(field
);
1051 if (pretty
->use_colors
) {
1052 bt_common_g_string_append(pretty
->string
, COLOR_STRING_VALUE
);
1054 print_escape_string(pretty
, str
);
1055 if (pretty
->use_colors
) {
1056 bt_common_g_string_append(pretty
->string
, COLOR_RST
);
1060 case BT_FIELD_CLASS_TYPE_STRUCTURE
:
1061 return print_struct(pretty
, field
, print_names
);
1062 case BT_FIELD_CLASS_TYPE_OPTION_WITHOUT_SELECTOR_FIELD
:
1063 case BT_FIELD_CLASS_TYPE_OPTION_WITH_BOOL_SELECTOR_FIELD
:
1064 case BT_FIELD_CLASS_TYPE_OPTION_WITH_UNSIGNED_INTEGER_SELECTOR_FIELD
:
1065 case BT_FIELD_CLASS_TYPE_OPTION_WITH_SIGNED_INTEGER_SELECTOR_FIELD
:
1066 return print_option(pretty
, field
, print_names
);
1067 case BT_FIELD_CLASS_TYPE_VARIANT_WITHOUT_SELECTOR_FIELD
:
1068 case BT_FIELD_CLASS_TYPE_VARIANT_WITH_UNSIGNED_INTEGER_SELECTOR_FIELD
:
1069 case BT_FIELD_CLASS_TYPE_VARIANT_WITH_SIGNED_INTEGER_SELECTOR_FIELD
:
1070 return print_variant(pretty
, field
, print_names
);
1071 case BT_FIELD_CLASS_TYPE_STATIC_ARRAY
:
1072 return print_array(pretty
, field
, print_names
);
1073 case BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY_WITHOUT_LENGTH_FIELD
:
1074 case BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY_WITH_LENGTH_FIELD
:
1075 return print_sequence(pretty
, field
, print_names
);
1077 // TODO: log instead
1078 fprintf(pretty
->err
, "[error] Unknown type id: %d\n", (int) class_id
);
1084 int print_stream_packet_context(struct pretty_component
*pretty
,
1085 const bt_event
*event
)
1088 const bt_packet
*packet
= NULL
;
1089 const bt_field
*main_field
= NULL
;
1091 packet
= bt_event_borrow_packet_const(event
);
1095 main_field
= bt_packet_borrow_context_field_const(packet
);
1099 if (!pretty
->start_line
) {
1100 bt_common_g_string_append(pretty
->string
, ", ");
1102 pretty
->start_line
= false;
1103 if (pretty
->options
.print_scope_field_names
) {
1104 print_name_equal(pretty
, "stream.packet.context");
1106 ret
= print_field(pretty
, main_field
,
1107 pretty
->options
.print_context_field_names
);
1114 int print_stream_event_context(struct pretty_component
*pretty
,
1115 const bt_event
*event
)
1118 const bt_field
*main_field
= NULL
;
1120 main_field
= bt_event_borrow_common_context_field_const(event
);
1124 if (!pretty
->start_line
) {
1125 bt_common_g_string_append(pretty
->string
, ", ");
1127 pretty
->start_line
= false;
1128 if (pretty
->options
.print_scope_field_names
) {
1129 print_name_equal(pretty
, "stream.event.context");
1131 ret
= print_field(pretty
, main_field
,
1132 pretty
->options
.print_context_field_names
);
1139 int print_event_context(struct pretty_component
*pretty
,
1140 const bt_event
*event
)
1143 const bt_field
*main_field
= NULL
;
1145 main_field
= bt_event_borrow_specific_context_field_const(event
);
1149 if (!pretty
->start_line
) {
1150 bt_common_g_string_append(pretty
->string
, ", ");
1152 pretty
->start_line
= false;
1153 if (pretty
->options
.print_scope_field_names
) {
1154 print_name_equal(pretty
, "event.context");
1156 ret
= print_field(pretty
, main_field
,
1157 pretty
->options
.print_context_field_names
);
1164 int print_event_payload(struct pretty_component
*pretty
,
1165 const bt_event
*event
)
1168 const bt_field
*main_field
= NULL
;
1170 main_field
= bt_event_borrow_payload_field_const(event
);
1174 if (!pretty
->start_line
) {
1175 bt_common_g_string_append(pretty
->string
, ", ");
1177 pretty
->start_line
= false;
1178 if (pretty
->options
.print_scope_field_names
) {
1179 print_name_equal(pretty
, "event.fields");
1181 ret
= print_field(pretty
, main_field
,
1182 pretty
->options
.print_payload_field_names
);
1189 int flush_buf(FILE *stream
, struct pretty_component
*pretty
)
1193 if (pretty
->string
->len
== 0) {
1197 if (fwrite(pretty
->string
->str
, pretty
->string
->len
, 1, stream
) != 1) {
1206 int pretty_print_event(struct pretty_component
*pretty
,
1207 const bt_message
*event_msg
)
1210 const bt_event
*event
=
1211 bt_message_event_borrow_event_const(event_msg
);
1214 pretty
->start_line
= true;
1215 g_string_assign(pretty
->string
, "");
1216 ret
= print_event_header(pretty
, event_msg
);
1221 ret
= print_stream_packet_context(pretty
, event
);
1226 ret
= print_stream_event_context(pretty
, event
);
1231 ret
= print_event_context(pretty
, event
);
1236 ret
= print_event_payload(pretty
, event
);
1241 bt_common_g_string_append_c(pretty
->string
, '\n');
1242 if (flush_buf(pretty
->out
, pretty
)) {
1252 int print_discarded_elements_msg(struct pretty_component
*pretty
,
1253 const bt_stream
*stream
,
1254 const bt_clock_snapshot
*begin_clock_snapshot
,
1255 const bt_clock_snapshot
*end_clock_snapshot
,
1256 uint64_t count
, const char *elem_type
)
1259 const bt_stream_class
*stream_class
= NULL
;
1260 const bt_trace
*trace
= NULL
;
1261 const char *stream_name
;
1262 const char *trace_name
;
1264 int64_t stream_class_id
;
1266 const char *init_msg
;
1269 stream_name
= bt_stream_get_name(stream
);
1271 stream_name
= "(unknown)";
1274 /* Stream class ID */
1275 stream_class
= bt_stream_borrow_class_const(stream
);
1276 BT_ASSERT(stream_class
);
1277 stream_class_id
= bt_stream_class_get_id(stream_class
);
1280 stream_id
= bt_stream_get_id(stream
);
1283 trace
= bt_stream_borrow_trace_const(stream
);
1285 trace_name
= bt_trace_get_name(trace
);
1287 trace_name
= "(unknown)";
1291 trace_uuid
= bt_trace_get_uuid(trace
);
1293 /* Format message */
1294 g_string_assign(pretty
->string
, "");
1296 if (count
== UINT64_C(-1)) {
1297 init_msg
= "Tracer may have discarded";
1299 init_msg
= "Tracer discarded";
1302 bt_common_g_string_append_printf(pretty
->string
,
1303 "%s%sWARNING%s%s: %s ",
1304 bt_common_color_fg_yellow(),
1305 bt_common_color_bold(),
1306 bt_common_color_reset(),
1307 bt_common_color_fg_yellow(), init_msg
);
1309 if (count
== UINT64_C(-1)) {
1310 bt_common_g_string_append_printf(pretty
->string
, "%ss", elem_type
);
1312 bt_common_g_string_append_printf(pretty
->string
,
1313 "%" PRIu64
" %s%s", count
, elem_type
,
1314 count
== 1 ? "" : "s");
1317 bt_common_g_string_append_c(pretty
->string
, ' ');
1319 if (begin_clock_snapshot
&& end_clock_snapshot
) {
1320 bt_common_g_string_append(pretty
->string
, "between [");
1321 print_timestamp_wall(pretty
, begin_clock_snapshot
, false);
1322 bt_common_g_string_append(pretty
->string
, "] and [");
1323 print_timestamp_wall(pretty
, end_clock_snapshot
, false);
1324 bt_common_g_string_append(pretty
->string
, "]");
1326 bt_common_g_string_append(pretty
->string
, "(unknown time range)");
1329 bt_common_g_string_append_printf(pretty
->string
, " in trace \"%s\" ", trace_name
);
1332 bt_common_g_string_append_printf(pretty
->string
,
1333 "(UUID: " BT_UUID_FMT
") ",
1334 BT_UUID_FMT_VALUES(trace_uuid
));
1336 bt_common_g_string_append(pretty
->string
, "(no UUID) ");
1339 bt_common_g_string_append_printf(pretty
->string
,
1340 "within stream \"%s\" (stream class ID: %" PRIu64
", ",
1341 stream_name
, stream_class_id
);
1343 if (stream_id
>= 0) {
1344 bt_common_g_string_append_printf(pretty
->string
,
1345 "stream ID: %" PRIu64
, stream_id
);
1347 bt_common_g_string_append(pretty
->string
, "no stream ID");
1350 bt_common_g_string_append_printf(pretty
->string
, ").%s\n",
1351 bt_common_color_reset());
1354 * Print to standard error stream to remain backward compatible
1355 * with Babeltrace 1.
1357 if (flush_buf(stderr
, pretty
)) {
1365 int pretty_print_discarded_items(struct pretty_component
*pretty
,
1366 const bt_message
*msg
)
1368 const bt_clock_snapshot
*begin
= NULL
;
1369 const bt_clock_snapshot
*end
= NULL
;
1370 const bt_stream
*stream
;
1371 const bt_stream_class
*stream_class
;
1372 uint64_t count
= UINT64_C(-1);
1373 const char *elem_type
;
1375 switch (bt_message_get_type(msg
)) {
1376 case BT_MESSAGE_TYPE_DISCARDED_EVENTS
:
1377 stream
= bt_message_discarded_events_borrow_stream_const(msg
);
1379 if (bt_message_discarded_events_get_count(msg
, &count
) ==
1380 BT_PROPERTY_AVAILABILITY_NOT_AVAILABLE
) {
1381 count
= UINT64_C(-1);
1384 elem_type
= "event";
1386 case BT_MESSAGE_TYPE_DISCARDED_PACKETS
:
1387 stream
= bt_message_discarded_packets_borrow_stream_const(msg
);
1389 if (bt_message_discarded_packets_get_count(msg
, &count
) ==
1390 BT_PROPERTY_AVAILABILITY_NOT_AVAILABLE
) {
1391 count
= UINT64_C(-1);
1394 elem_type
= "packet";
1401 stream_class
= bt_stream_borrow_class_const(stream
);
1403 switch (bt_message_get_type(msg
)) {
1404 case BT_MESSAGE_TYPE_DISCARDED_EVENTS
:
1405 if (bt_stream_class_discarded_events_have_default_clock_snapshots(
1407 begin
= bt_message_discarded_events_borrow_beginning_default_clock_snapshot_const(
1409 end
= bt_message_discarded_events_borrow_end_default_clock_snapshot_const(
1414 case BT_MESSAGE_TYPE_DISCARDED_PACKETS
:
1415 if (bt_stream_class_discarded_packets_have_default_clock_snapshots(
1417 begin
= bt_message_discarded_packets_borrow_beginning_default_clock_snapshot_const(
1419 end
= bt_message_discarded_packets_borrow_end_default_clock_snapshot_const(
1428 print_discarded_elements_msg(pretty
, stream
, begin
, end
,