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
,
57 GQuark
*filters_fields
, int filter_array_len
);
60 void print_name_equal(struct pretty_component
*pretty
, const char *name
)
62 if (pretty
->use_colors
) {
63 g_string_append_printf(pretty
->string
, "%s%s%s = ", COLOR_NAME
,
66 g_string_append_printf(pretty
->string
, "%s = ", name
);
71 void print_field_name_equal(struct pretty_component
*pretty
, const char *name
)
73 if (pretty
->use_colors
) {
74 g_string_append_printf(pretty
->string
, "%s%s%s = ",
75 COLOR_FIELD_NAME
, name
, COLOR_RST
);
77 g_string_append_printf(pretty
->string
, "%s = ", name
);
82 void print_timestamp_cycles(struct pretty_component
*pretty
,
83 const bt_clock_snapshot
*clock_snapshot
, bool update_last
)
87 cycles
= bt_clock_snapshot_get_value(clock_snapshot
);
88 g_string_append_printf(pretty
->string
, "%020" PRIu64
, cycles
);
91 if (pretty
->last_cycles_timestamp
!= -1ULL) {
92 pretty
->delta_cycles
= cycles
- pretty
->last_cycles_timestamp
;
95 pretty
->last_cycles_timestamp
= cycles
;
100 void print_timestamp_wall(struct pretty_component
*pretty
,
101 const bt_clock_snapshot
*clock_snapshot
, bool update_last
)
104 int64_t ts_nsec
= 0; /* add configurable offset */
105 int64_t ts_sec
= 0; /* add configurable offset */
106 uint64_t ts_sec_abs
, ts_nsec_abs
;
109 if (!clock_snapshot
) {
110 g_string_append(pretty
->string
, "??:??:??.?????????");
114 ret
= bt_clock_snapshot_get_ns_from_origin(clock_snapshot
, &ts_nsec
);
116 // TODO: log, this is unexpected
117 g_string_append(pretty
->string
, "Error");
122 if (pretty
->last_real_timestamp
!= -1ULL) {
123 pretty
->delta_real_timestamp
= ts_nsec
- pretty
->last_real_timestamp
;
126 pretty
->last_real_timestamp
= ts_nsec
;
129 ts_sec
+= ts_nsec
/ NSEC_PER_SEC
;
130 ts_nsec
= ts_nsec
% NSEC_PER_SEC
;
132 if (ts_sec
>= 0 && ts_nsec
>= 0) {
135 ts_nsec_abs
= ts_nsec
;
136 } else if (ts_sec
> 0 && ts_nsec
< 0) {
138 ts_sec_abs
= ts_sec
- 1;
139 ts_nsec_abs
= NSEC_PER_SEC
+ ts_nsec
;
140 } else if (ts_sec
== 0 && ts_nsec
< 0) {
143 ts_nsec_abs
= -ts_nsec
;
144 } else if (ts_sec
< 0 && ts_nsec
> 0) {
146 ts_sec_abs
= -(ts_sec
+ 1);
147 ts_nsec_abs
= NSEC_PER_SEC
- ts_nsec
;
148 } else if (ts_sec
< 0 && ts_nsec
== 0) {
150 ts_sec_abs
= -ts_sec
;
151 ts_nsec_abs
= ts_nsec
;
152 } else { /* (ts_sec < 0 && ts_nsec < 0) */
154 ts_sec_abs
= -ts_sec
;
155 ts_nsec_abs
= -ts_nsec
;
158 if (!pretty
->options
.clock_seconds
) {
160 time_t time_s
= (time_t) ts_sec_abs
;
162 if (is_negative
&& !pretty
->negative_timestamp_warning_done
) {
164 fprintf(stderr
, "[warning] Fallback to [sec.ns] to print negative time value. Use --clock-seconds.\n");
165 pretty
->negative_timestamp_warning_done
= true;
169 if (!pretty
->options
.clock_gmt
) {
172 res
= bt_localtime_r(&time_s
, &tm
);
175 fprintf(stderr
, "[warning] Unable to get localtime.\n");
181 res
= bt_gmtime_r(&time_s
, &tm
);
184 fprintf(stderr
, "[warning] Unable to get gmtime.\n");
188 if (pretty
->options
.clock_date
) {
192 /* Print date and time */
193 res
= strftime(timestr
, sizeof(timestr
),
197 fprintf(stderr
, "[warning] Unable to print ascii time.\n");
201 g_string_append(pretty
->string
, timestr
);
204 /* Print time in HH:MM:SS.ns */
205 g_string_append_printf(pretty
->string
,
206 "%02d:%02d:%02d.%09" PRIu64
, tm
.tm_hour
, tm
.tm_min
,
207 tm
.tm_sec
, ts_nsec_abs
);
211 g_string_append_printf(pretty
->string
, "%s%" PRId64
".%09" PRIu64
,
212 is_negative
? "-" : "", ts_sec_abs
, ts_nsec_abs
);
218 int print_event_timestamp(struct pretty_component
*pretty
,
219 const bt_message
*event_msg
, bool *start_line
)
221 bool print_names
= pretty
->options
.print_header_field_names
;
223 const bt_clock_snapshot
*clock_snapshot
= NULL
;
225 if (!bt_message_event_borrow_stream_class_default_clock_class_const(
227 /* No default clock class: skip the timestamp without an error */
231 clock_snapshot
= bt_message_event_borrow_default_clock_snapshot_const(event_msg
);
234 print_name_equal(pretty
, "timestamp");
236 g_string_append(pretty
->string
, "[");
238 if (pretty
->use_colors
) {
239 g_string_append(pretty
->string
, COLOR_TIMESTAMP
);
241 if (pretty
->options
.print_timestamp_cycles
) {
242 print_timestamp_cycles(pretty
, clock_snapshot
, true);
244 print_timestamp_wall(pretty
, clock_snapshot
, true);
246 if (pretty
->use_colors
) {
247 g_string_append(pretty
->string
, COLOR_RST
);
251 g_string_append(pretty
->string
, "] ");
253 if (pretty
->options
.print_delta_field
) {
255 g_string_append(pretty
->string
, ", ");
256 print_name_equal(pretty
, "delta");
258 g_string_append(pretty
->string
, "(");
260 if (pretty
->options
.print_timestamp_cycles
) {
261 if (pretty
->delta_cycles
== -1ULL) {
262 g_string_append(pretty
->string
,
263 "+??????????\?\?"); /* Not a trigraph. */
265 g_string_append_printf(pretty
->string
,
266 "+%012" PRIu64
, pretty
->delta_cycles
);
269 if (pretty
->delta_real_timestamp
!= -1ULL) {
270 uint64_t delta_sec
, delta_nsec
, delta
;
272 delta
= pretty
->delta_real_timestamp
;
273 delta_sec
= delta
/ NSEC_PER_SEC
;
274 delta_nsec
= delta
% NSEC_PER_SEC
;
275 g_string_append_printf(pretty
->string
,
276 "+%" PRIu64
".%09" PRIu64
,
277 delta_sec
, delta_nsec
);
279 g_string_append(pretty
->string
, "+?.?????????");
283 g_string_append(pretty
->string
, ") ");
286 *start_line
= !print_names
;
293 int print_event_header(struct pretty_component
*pretty
,
294 const bt_message
*event_msg
)
296 bool print_names
= pretty
->options
.print_header_field_names
;
298 const bt_event_class
*event_class
= NULL
;
299 const bt_packet
*packet
= NULL
;
300 const bt_stream
*stream
= NULL
;
301 const bt_trace
*trace
= NULL
;
302 const bt_event
*event
= bt_message_event_borrow_event_const(event_msg
);
305 bt_property_availability prop_avail
;
307 event_class
= bt_event_borrow_class_const(event
);
308 packet
= bt_event_borrow_packet_const(event
);
309 stream
= bt_packet_borrow_stream_const(packet
);
310 trace
= bt_stream_borrow_trace_const(stream
);
311 ret
= print_event_timestamp(pretty
, event_msg
, &pretty
->start_line
);
315 if (pretty
->options
.print_trace_field
) {
318 name
= bt_trace_get_name(trace
);
320 if (!pretty
->start_line
) {
321 g_string_append(pretty
->string
, ", ");
324 print_name_equal(pretty
, "trace");
327 g_string_append(pretty
->string
, name
);
330 g_string_append(pretty
->string
, ", ");
334 if (pretty
->options
.print_trace_hostname_field
) {
335 const bt_value
*hostname_str
;
337 hostname_str
= bt_trace_borrow_environment_entry_value_by_name_const(
342 if (!pretty
->start_line
) {
343 g_string_append(pretty
->string
, ", ");
346 print_name_equal(pretty
, "trace:hostname");
348 str
= bt_value_string_get(hostname_str
);
349 g_string_append(pretty
->string
, str
);
353 if (pretty
->options
.print_trace_domain_field
) {
354 const bt_value
*domain_str
;
356 domain_str
= bt_trace_borrow_environment_entry_value_by_name_const(
361 if (!pretty
->start_line
) {
362 g_string_append(pretty
->string
, ", ");
365 print_name_equal(pretty
, "trace:domain");
366 } else if (dom_print
) {
367 g_string_append(pretty
->string
, ":");
369 str
= bt_value_string_get(domain_str
);
370 g_string_append(pretty
->string
, str
);
374 if (pretty
->options
.print_trace_procname_field
) {
375 const bt_value
*procname_str
;
377 procname_str
= bt_trace_borrow_environment_entry_value_by_name_const(
382 if (!pretty
->start_line
) {
383 g_string_append(pretty
->string
, ", ");
386 print_name_equal(pretty
, "trace:procname");
387 } else if (dom_print
) {
388 g_string_append(pretty
->string
, ":");
390 str
= bt_value_string_get(procname_str
);
391 g_string_append(pretty
->string
, str
);
395 if (pretty
->options
.print_trace_vpid_field
) {
396 const bt_value
*vpid_value
;
398 vpid_value
= bt_trace_borrow_environment_entry_value_by_name_const(
403 if (!pretty
->start_line
) {
404 g_string_append(pretty
->string
, ", ");
407 print_name_equal(pretty
, "trace:vpid");
408 } else if (dom_print
) {
409 g_string_append(pretty
->string
, ":");
411 value
= bt_value_signed_integer_get(vpid_value
);
412 g_string_append_printf(pretty
->string
,
413 "(%" PRId64
")", value
);
417 if (pretty
->options
.print_loglevel_field
) {
418 static const char *log_level_names
[] = {
419 [ BT_EVENT_CLASS_LOG_LEVEL_EMERGENCY
] = "TRACE_EMERG",
420 [ BT_EVENT_CLASS_LOG_LEVEL_ALERT
] = "TRACE_ALERT",
421 [ BT_EVENT_CLASS_LOG_LEVEL_CRITICAL
] = "TRACE_CRIT",
422 [ BT_EVENT_CLASS_LOG_LEVEL_ERROR
] = "TRACE_ERR",
423 [ BT_EVENT_CLASS_LOG_LEVEL_WARNING
] = "TRACE_WARNING",
424 [ BT_EVENT_CLASS_LOG_LEVEL_NOTICE
] = "TRACE_NOTICE",
425 [ BT_EVENT_CLASS_LOG_LEVEL_INFO
] = "TRACE_INFO",
426 [ BT_EVENT_CLASS_LOG_LEVEL_DEBUG_SYSTEM
] = "TRACE_DEBUG_SYSTEM",
427 [ BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROGRAM
] = "TRACE_DEBUG_PROGRAM",
428 [ BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROCESS
] = "TRACE_DEBUG_PROCESS",
429 [ BT_EVENT_CLASS_LOG_LEVEL_DEBUG_MODULE
] = "TRACE_DEBUG_MODULE",
430 [ BT_EVENT_CLASS_LOG_LEVEL_DEBUG_UNIT
] = "TRACE_DEBUG_UNIT",
431 [ BT_EVENT_CLASS_LOG_LEVEL_DEBUG_FUNCTION
] = "TRACE_DEBUG_FUNCTION",
432 [ BT_EVENT_CLASS_LOG_LEVEL_DEBUG_LINE
] = "TRACE_DEBUG_LINE",
433 [ BT_EVENT_CLASS_LOG_LEVEL_DEBUG
] = "TRACE_DEBUG",
435 bt_event_class_log_level log_level
;
436 const char *log_level_str
= NULL
;
438 prop_avail
= bt_event_class_get_log_level(event_class
,
440 if (prop_avail
== BT_PROPERTY_AVAILABILITY_AVAILABLE
) {
441 log_level_str
= log_level_names
[log_level
];
442 BT_ASSERT(log_level_str
);
444 if (!pretty
->start_line
) {
445 g_string_append(pretty
->string
, ", ");
448 print_name_equal(pretty
, "loglevel");
449 } else if (dom_print
) {
450 g_string_append(pretty
->string
, ":");
453 g_string_append(pretty
->string
, log_level_str
);
454 g_string_append_printf(
455 pretty
->string
, " (%d)", (int) log_level
);
459 if (pretty
->options
.print_emf_field
) {
462 uri_str
= bt_event_class_get_emf_uri(event_class
);
464 if (!pretty
->start_line
) {
465 g_string_append(pretty
->string
, ", ");
468 print_name_equal(pretty
, "model.emf.uri");
469 } else if (dom_print
) {
470 g_string_append(pretty
->string
, ":");
473 g_string_append(pretty
->string
, uri_str
);
477 if (dom_print
&& !print_names
) {
478 g_string_append(pretty
->string
, " ");
480 if (!pretty
->start_line
) {
481 g_string_append(pretty
->string
, ", ");
483 pretty
->start_line
= true;
485 print_name_equal(pretty
, "name");
487 ev_name
= bt_event_class_get_name(event_class
);
488 if (pretty
->use_colors
) {
490 g_string_append(pretty
->string
, COLOR_EVENT_NAME
);
492 g_string_append(pretty
->string
, COLOR_UNKNOWN
);
496 g_string_append(pretty
->string
, ev_name
);
498 g_string_append(pretty
->string
, "<unknown>");
500 if (pretty
->use_colors
) {
501 g_string_append(pretty
->string
, COLOR_RST
);
504 g_string_append(pretty
->string
, ": ");
506 g_string_append(pretty
->string
, ", ");
514 int print_integer(struct pretty_component
*pretty
,
515 const bt_field
*field
)
518 bt_field_class_integer_preferred_display_base base
;
519 const bt_field_class
*int_fc
;
524 bool rst_color
= false;
525 bt_field_class_type ft_type
;
527 int_fc
= bt_field_borrow_class_const(field
);
529 ft_type
= bt_field_get_class_type(field
);
530 if (ft_type
== BT_FIELD_CLASS_TYPE_UNSIGNED_INTEGER
||
531 ft_type
== BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION
) {
532 v
.u
= bt_field_unsigned_integer_get_value(field
);
534 v
.s
= bt_field_signed_integer_get_value(field
);
537 if (pretty
->use_colors
) {
538 g_string_append(pretty
->string
, COLOR_NUMBER_VALUE
);
542 base
= bt_field_class_integer_get_preferred_display_base(int_fc
);
544 case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_BINARY
:
548 len
= bt_field_class_integer_get_field_value_range(int_fc
);
549 g_string_append(pretty
->string
, "0b");
550 _bt_safe_lshift(v
.u
, 64 - len
);
551 for (bitnr
= 0; bitnr
< len
; bitnr
++) {
552 g_string_append_printf(pretty
->string
, "%u", (v
.u
& (1ULL << 63)) ? 1 : 0);
553 _bt_safe_lshift(v
.u
, 1);
557 case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_OCTAL
:
559 if (ft_type
== BT_FIELD_CLASS_TYPE_SIGNED_INTEGER
||
560 ft_type
== BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION
) {
563 len
= bt_field_class_integer_get_field_value_range(
569 /* Round length to the nearest 3-bit */
570 rounded_len
= (((len
- 1) / 3) + 1) * 3;
571 v
.u
&= ((uint64_t) 1 << rounded_len
) - 1;
575 g_string_append_printf(pretty
->string
, "0%" PRIo64
, v
.u
);
578 case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
:
579 if (ft_type
== BT_FIELD_CLASS_TYPE_UNSIGNED_INTEGER
||
580 ft_type
== BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION
) {
581 g_string_append_printf(pretty
->string
, "%" PRIu64
, v
.u
);
583 g_string_append_printf(pretty
->string
, "%" PRId64
, v
.s
);
586 case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL
:
590 len
= bt_field_class_integer_get_field_value_range(int_fc
);
592 /* Round length to the nearest nibble */
593 uint8_t rounded_len
= ((len
+ 3) & ~0x3);
595 v
.u
&= ((uint64_t) 1 << rounded_len
) - 1;
598 g_string_append_printf(pretty
->string
, "0x%" PRIX64
, v
.u
);
607 g_string_append(pretty
->string
, COLOR_RST
);
613 void print_escape_string(struct pretty_component
*pretty
, const char *str
)
617 g_string_append_c(pretty
->string
, '"');
619 for (i
= 0; i
< strlen(str
); i
++) {
620 /* Escape sequences not recognized by iscntrl(). */
623 g_string_append(pretty
->string
, "\\\\");
626 g_string_append(pretty
->string
, "\\\'");
629 g_string_append(pretty
->string
, "\\\"");
632 g_string_append(pretty
->string
, "\\\?");
636 /* Standard characters. */
637 if (!iscntrl(str
[i
])) {
638 g_string_append_c(pretty
->string
, str
[i
]);
644 g_string_append(pretty
->string
, "\\0");
647 g_string_append(pretty
->string
, "\\a");
650 g_string_append(pretty
->string
, "\\b");
653 g_string_append(pretty
->string
, "\\e");
656 g_string_append(pretty
->string
, "\\f");
659 g_string_append(pretty
->string
, "\\n");
662 g_string_append(pretty
->string
, "\\r");
665 g_string_append(pretty
->string
, "\\t");
668 g_string_append(pretty
->string
, "\\v");
671 /* Unhandled control-sequence, print as hex. */
672 g_string_append_printf(pretty
->string
, "\\x%02x", str
[i
]);
677 g_string_append_c(pretty
->string
, '"');
681 int print_enum(struct pretty_component
*pretty
,
682 const bt_field
*field
)
685 const bt_field_class
*enumeration_field_class
= NULL
;
686 bt_field_class_enumeration_mapping_label_array label_array
;
687 uint64_t label_count
;
690 enumeration_field_class
= bt_field_borrow_class_const(field
);
691 if (!enumeration_field_class
) {
696 switch (bt_field_get_class_type(field
)) {
697 case BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION
:
698 ret
= bt_field_unsigned_enumeration_get_mapping_labels(field
,
699 &label_array
, &label_count
);
701 case BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION
:
702 ret
= bt_field_signed_enumeration_get_mapping_labels(field
,
703 &label_array
, &label_count
);
714 g_string_append(pretty
->string
, "( ");
715 if (label_count
== 0) {
716 if (pretty
->use_colors
) {
717 g_string_append(pretty
->string
, COLOR_UNKNOWN
);
719 g_string_append(pretty
->string
, "<unknown>");
720 if (pretty
->use_colors
) {
721 g_string_append(pretty
->string
, COLOR_RST
);
725 for (i
= 0; i
< label_count
; i
++) {
726 const char *mapping_name
= label_array
[i
];
729 g_string_append(pretty
->string
, ", ");
731 if (pretty
->use_colors
) {
732 g_string_append(pretty
->string
, COLOR_ENUM_MAPPING_NAME
);
734 print_escape_string(pretty
, mapping_name
);
735 if (pretty
->use_colors
) {
736 g_string_append(pretty
->string
, COLOR_RST
);
740 g_string_append(pretty
->string
, " : container = ");
741 ret
= print_integer(pretty
, field
);
745 g_string_append(pretty
->string
, " )");
751 int filter_field_name(struct pretty_component
*pretty
, const char *field_name
,
752 GQuark
*filter_fields
, int filter_array_len
)
755 GQuark field_quark
= g_quark_try_string(field_name
);
757 if (!field_quark
|| pretty
->options
.verbose
) {
761 for (i
= 0; i
< filter_array_len
; i
++) {
762 if (field_quark
== filter_fields
[i
]) {
770 int print_struct_field(struct pretty_component
*pretty
,
771 const bt_field
*_struct
,
772 const bt_field_class
*struct_class
,
773 uint64_t i
, bool print_names
, uint64_t *nr_printed_fields
,
774 GQuark
*filter_fields
, int filter_array_len
)
777 const char *field_name
;
778 const bt_field
*field
= NULL
;
779 const bt_field_class_structure_member
*member
;
781 field
= bt_field_structure_borrow_member_field_by_index_const(_struct
, i
);
787 member
= bt_field_class_structure_borrow_member_by_index_const(
789 field_name
= bt_field_class_structure_member_get_name(member
);
791 if (filter_fields
&& !filter_field_name(pretty
, field_name
,
792 filter_fields
, filter_array_len
)) {
797 if (*nr_printed_fields
> 0) {
798 g_string_append(pretty
->string
, ", ");
800 g_string_append(pretty
->string
, " ");
803 print_field_name_equal(pretty
, field_name
);
805 ret
= print_field(pretty
, field
, print_names
, NULL
, 0);
806 *nr_printed_fields
+= 1;
813 int print_struct(struct pretty_component
*pretty
,
814 const bt_field
*_struct
, bool print_names
,
815 GQuark
*filter_fields
, int filter_array_len
)
818 const bt_field_class
*struct_class
= NULL
;
819 uint64_t nr_fields
, i
, nr_printed_fields
;
821 struct_class
= bt_field_borrow_class_const(_struct
);
827 nr_fields
= bt_field_class_structure_get_member_count(struct_class
);
829 g_string_append(pretty
->string
, "{");
831 nr_printed_fields
= 0;
832 for (i
= 0; i
< nr_fields
; i
++) {
833 ret
= print_struct_field(pretty
, _struct
, struct_class
, i
,
834 print_names
, &nr_printed_fields
, filter_fields
,
841 g_string_append(pretty
->string
, " }");
848 int print_array_field(struct pretty_component
*pretty
,
849 const bt_field
*array
, uint64_t i
, bool print_names
)
851 const bt_field
*field
= NULL
;
854 g_string_append(pretty
->string
, ", ");
856 g_string_append(pretty
->string
, " ");
859 g_string_append_printf(pretty
->string
, "[%" PRIu64
"] = ", i
);
862 field
= bt_field_array_borrow_element_field_by_index_const(array
, i
);
864 return print_field(pretty
, field
, print_names
, NULL
, 0);
868 int print_array(struct pretty_component
*pretty
,
869 const bt_field
*array
, bool print_names
)
872 const bt_field_class
*array_class
= NULL
;
876 array_class
= bt_field_borrow_class_const(array
);
881 len
= bt_field_array_get_length(array
);
882 g_string_append(pretty
->string
, "[");
884 for (i
= 0; i
< len
; i
++) {
885 ret
= print_array_field(pretty
, array
, i
, print_names
);
891 g_string_append(pretty
->string
, " ]");
898 int print_sequence_field(struct pretty_component
*pretty
,
899 const bt_field
*seq
, uint64_t i
, bool print_names
)
901 const bt_field
*field
= NULL
;
904 g_string_append(pretty
->string
, ", ");
906 g_string_append(pretty
->string
, " ");
909 g_string_append_printf(pretty
->string
, "[%" PRIu64
"] = ", i
);
912 field
= bt_field_array_borrow_element_field_by_index_const(seq
, i
);
914 return print_field(pretty
, field
, print_names
, NULL
, 0);
918 int print_sequence(struct pretty_component
*pretty
,
919 const bt_field
*seq
, bool print_names
)
925 len
= bt_field_array_get_length(seq
);
926 g_string_append(pretty
->string
, "[");
929 for (i
= 0; i
< len
; i
++) {
930 ret
= print_sequence_field(pretty
, seq
, i
, print_names
);
936 g_string_append(pretty
->string
, " ]");
943 int print_variant(struct pretty_component
*pretty
,
944 const bt_field
*variant
, bool print_names
)
947 const bt_field
*field
= NULL
;
949 field
= bt_field_variant_borrow_selected_option_field_const(variant
);
951 g_string_append(pretty
->string
, "{ ");
954 // TODO: find tag's name using field path
955 // print_field_name_equal(pretty, tag_choice);
957 ret
= print_field(pretty
, field
, print_names
, NULL
, 0);
962 g_string_append(pretty
->string
, " }");
969 int print_field(struct pretty_component
*pretty
,
970 const bt_field
*field
, bool print_names
,
971 GQuark
*filter_fields
, int filter_array_len
)
973 bt_field_class_type class_id
;
975 class_id
= bt_field_get_class_type(field
);
977 case BT_FIELD_CLASS_TYPE_UNSIGNED_INTEGER
:
978 case BT_FIELD_CLASS_TYPE_SIGNED_INTEGER
:
979 return print_integer(pretty
, field
);
980 case BT_FIELD_CLASS_TYPE_REAL
:
984 v
= bt_field_real_get_value(field
);
985 if (pretty
->use_colors
) {
986 g_string_append(pretty
->string
, COLOR_NUMBER_VALUE
);
988 g_string_append_printf(pretty
->string
, "%g", v
);
989 if (pretty
->use_colors
) {
990 g_string_append(pretty
->string
, COLOR_RST
);
994 case BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION
:
995 case BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION
:
996 return print_enum(pretty
, field
);
997 case BT_FIELD_CLASS_TYPE_STRING
:
1001 str
= bt_field_string_get_value(field
);
1006 if (pretty
->use_colors
) {
1007 g_string_append(pretty
->string
, COLOR_STRING_VALUE
);
1009 print_escape_string(pretty
, str
);
1010 if (pretty
->use_colors
) {
1011 g_string_append(pretty
->string
, COLOR_RST
);
1015 case BT_FIELD_CLASS_TYPE_STRUCTURE
:
1016 return print_struct(pretty
, field
, print_names
, filter_fields
,
1018 case BT_FIELD_CLASS_TYPE_VARIANT
:
1019 return print_variant(pretty
, field
, print_names
);
1020 case BT_FIELD_CLASS_TYPE_STATIC_ARRAY
:
1021 return print_array(pretty
, field
, print_names
);
1022 case BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY
:
1023 return print_sequence(pretty
, field
, print_names
);
1025 // TODO: log instead
1026 fprintf(pretty
->err
, "[error] Unknown type id: %d\n", (int) class_id
);
1032 int print_stream_packet_context(struct pretty_component
*pretty
,
1033 const bt_event
*event
)
1036 const bt_packet
*packet
= NULL
;
1037 const bt_field
*main_field
= NULL
;
1039 packet
= bt_event_borrow_packet_const(event
);
1044 main_field
= bt_packet_borrow_context_field_const(packet
);
1048 if (!pretty
->start_line
) {
1049 g_string_append(pretty
->string
, ", ");
1051 pretty
->start_line
= false;
1052 if (pretty
->options
.print_scope_field_names
) {
1053 print_name_equal(pretty
, "stream.packet.context");
1055 ret
= print_field(pretty
, main_field
,
1056 pretty
->options
.print_context_field_names
,
1057 stream_packet_context_quarks
,
1058 STREAM_PACKET_CONTEXT_QUARKS_LEN
);
1065 int print_stream_event_context(struct pretty_component
*pretty
,
1066 const bt_event
*event
)
1069 const bt_field
*main_field
= NULL
;
1071 main_field
= bt_event_borrow_common_context_field_const(event
);
1075 if (!pretty
->start_line
) {
1076 g_string_append(pretty
->string
, ", ");
1078 pretty
->start_line
= false;
1079 if (pretty
->options
.print_scope_field_names
) {
1080 print_name_equal(pretty
, "stream.event.context");
1082 ret
= print_field(pretty
, main_field
,
1083 pretty
->options
.print_context_field_names
, NULL
, 0);
1090 int print_event_context(struct pretty_component
*pretty
,
1091 const bt_event
*event
)
1094 const bt_field
*main_field
= NULL
;
1096 main_field
= bt_event_borrow_specific_context_field_const(event
);
1100 if (!pretty
->start_line
) {
1101 g_string_append(pretty
->string
, ", ");
1103 pretty
->start_line
= false;
1104 if (pretty
->options
.print_scope_field_names
) {
1105 print_name_equal(pretty
, "event.context");
1107 ret
= print_field(pretty
, main_field
,
1108 pretty
->options
.print_context_field_names
, NULL
, 0);
1115 int print_event_payload(struct pretty_component
*pretty
,
1116 const bt_event
*event
)
1119 const bt_field
*main_field
= NULL
;
1121 main_field
= bt_event_borrow_payload_field_const(event
);
1125 if (!pretty
->start_line
) {
1126 g_string_append(pretty
->string
, ", ");
1128 pretty
->start_line
= false;
1129 if (pretty
->options
.print_scope_field_names
) {
1130 print_name_equal(pretty
, "event.fields");
1132 ret
= print_field(pretty
, main_field
,
1133 pretty
->options
.print_payload_field_names
, NULL
, 0);
1140 int flush_buf(FILE *stream
, struct pretty_component
*pretty
)
1144 if (pretty
->string
->len
== 0) {
1148 if (fwrite(pretty
->string
->str
, pretty
->string
->len
, 1, stream
) != 1) {
1157 int pretty_print_event(struct pretty_component
*pretty
,
1158 const bt_message
*event_msg
)
1161 const bt_event
*event
=
1162 bt_message_event_borrow_event_const(event_msg
);
1165 pretty
->start_line
= true;
1166 g_string_assign(pretty
->string
, "");
1167 ret
= print_event_header(pretty
, event_msg
);
1172 ret
= print_stream_packet_context(pretty
, event
);
1177 ret
= print_stream_event_context(pretty
, event
);
1182 ret
= print_event_context(pretty
, event
);
1187 ret
= print_event_payload(pretty
, event
);
1192 g_string_append_c(pretty
->string
, '\n');
1193 if (flush_buf(pretty
->out
, pretty
)) {
1203 int print_discarded_elements_msg(struct pretty_component
*pretty
,
1204 const bt_stream
*stream
,
1205 const bt_clock_snapshot
*begin_clock_snapshot
,
1206 const bt_clock_snapshot
*end_clock_snapshot
,
1207 uint64_t count
, const char *elem_type
)
1210 const bt_stream_class
*stream_class
= NULL
;
1211 const bt_trace
*trace
= NULL
;
1212 const char *stream_name
;
1213 const char *trace_name
;
1215 int64_t stream_class_id
;
1217 const char *init_msg
;
1220 stream_name
= bt_stream_get_name(stream
);
1222 stream_name
= "(unknown)";
1225 /* Stream class ID */
1226 stream_class
= bt_stream_borrow_class_const(stream
);
1227 BT_ASSERT(stream_class
);
1228 stream_class_id
= bt_stream_class_get_id(stream_class
);
1231 stream_id
= bt_stream_get_id(stream
);
1234 trace
= bt_stream_borrow_trace_const(stream
);
1236 trace_name
= bt_trace_get_name(trace
);
1238 trace_name
= "(unknown)";
1242 trace_uuid
= bt_trace_get_uuid(trace
);
1244 /* Format message */
1245 g_string_assign(pretty
->string
, "");
1247 if (count
== UINT64_C(-1)) {
1248 init_msg
= "Tracer may have discarded";
1250 init_msg
= "Tracer discarded";
1253 g_string_append_printf(pretty
->string
,
1254 "%s%sWARNING%s%s: %s ",
1255 bt_common_color_fg_yellow(),
1256 bt_common_color_bold(),
1257 bt_common_color_reset(),
1258 bt_common_color_fg_yellow(), init_msg
);
1260 if (count
== UINT64_C(-1)) {
1261 g_string_append_printf(pretty
->string
, "%ss", elem_type
);
1263 g_string_append_printf(pretty
->string
,
1264 "%" PRIu64
" %s%s", count
, elem_type
,
1265 count
== 1 ? "" : "s");
1268 g_string_append_c(pretty
->string
, ' ');
1270 if (begin_clock_snapshot
&& end_clock_snapshot
) {
1271 g_string_append(pretty
->string
, "between [");
1272 print_timestamp_wall(pretty
, begin_clock_snapshot
, false);
1273 g_string_append(pretty
->string
, "] and [");
1274 print_timestamp_wall(pretty
, end_clock_snapshot
, false);
1275 g_string_append(pretty
->string
, "]");
1277 g_string_append(pretty
->string
, "(unknown time range)");
1280 g_string_append_printf(pretty
->string
, " in trace \"%s\" ", trace_name
);
1283 g_string_append_printf(pretty
->string
,
1284 "(UUID: " BT_UUID_FMT
") ",
1285 BT_UUID_FMT_VALUES(trace_uuid
));
1287 g_string_append(pretty
->string
, "(no UUID) ");
1290 g_string_append_printf(pretty
->string
,
1291 "within stream \"%s\" (stream class ID: %" PRIu64
", ",
1292 stream_name
, stream_class_id
);
1294 if (stream_id
>= 0) {
1295 g_string_append_printf(pretty
->string
,
1296 "stream ID: %" PRIu64
, stream_id
);
1298 g_string_append(pretty
->string
, "no stream ID");
1301 g_string_append_printf(pretty
->string
, ").%s\n",
1302 bt_common_color_reset());
1305 * Print to standard error stream to remain backward compatible
1306 * with Babeltrace 1.
1308 if (flush_buf(stderr
, pretty
)) {
1316 int pretty_print_discarded_items(struct pretty_component
*pretty
,
1317 const bt_message
*msg
)
1319 const bt_clock_snapshot
*begin
= NULL
;
1320 const bt_clock_snapshot
*end
= NULL
;
1321 const bt_stream
*stream
;
1322 const bt_stream_class
*stream_class
;
1323 uint64_t count
= UINT64_C(-1);
1324 const char *elem_type
;
1326 switch (bt_message_get_type(msg
)) {
1327 case BT_MESSAGE_TYPE_DISCARDED_EVENTS
:
1328 stream
= bt_message_discarded_events_borrow_stream_const(msg
);
1330 if (bt_message_discarded_events_get_count(msg
, &count
) ==
1331 BT_PROPERTY_AVAILABILITY_NOT_AVAILABLE
) {
1332 count
= UINT64_C(-1);
1335 elem_type
= "event";
1337 case BT_MESSAGE_TYPE_DISCARDED_PACKETS
:
1338 stream
= bt_message_discarded_packets_borrow_stream_const(msg
);
1340 if (bt_message_discarded_packets_get_count(msg
, &count
) ==
1341 BT_PROPERTY_AVAILABILITY_NOT_AVAILABLE
) {
1342 count
= UINT64_C(-1);
1345 elem_type
= "packet";
1352 stream_class
= bt_stream_borrow_class_const(stream
);
1354 switch (bt_message_get_type(msg
)) {
1355 case BT_MESSAGE_TYPE_DISCARDED_EVENTS
:
1356 if (bt_stream_class_discarded_events_have_default_clock_snapshots(
1358 begin
= bt_message_discarded_events_borrow_beginning_default_clock_snapshot_const(
1360 end
= bt_message_discarded_events_borrow_end_default_clock_snapshot_const(
1365 case BT_MESSAGE_TYPE_DISCARDED_PACKETS
:
1366 if (bt_stream_class_discarded_packets_have_default_clock_snapshots(
1368 begin
= bt_message_discarded_packets_borrow_beginning_default_clock_snapshot_const(
1370 end
= bt_message_discarded_packets_borrow_end_default_clock_snapshot_const(
1379 print_discarded_elements_msg(pretty
, stream
, begin
, end
,