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 <babeltrace/babeltrace.h>
27 #include <babeltrace/bitfield-internal.h>
28 #include <babeltrace/common-internal.h>
29 #include <babeltrace/compat/time-internal.h>
30 #include <babeltrace/assert-internal.h>
35 #define NSEC_PER_SEC 1000000000LL
37 #define COLOR_NAME BT_COMMON_COLOR_BOLD
38 #define COLOR_FIELD_NAME BT_COMMON_COLOR_FG_CYAN
39 #define COLOR_RST BT_COMMON_COLOR_RESET
40 #define COLOR_STRING_VALUE BT_COMMON_COLOR_BOLD
41 #define COLOR_NUMBER_VALUE BT_COMMON_COLOR_BOLD
42 #define COLOR_ENUM_MAPPING_NAME BT_COMMON_COLOR_BOLD
43 #define COLOR_UNKNOWN BT_COMMON_COLOR_BOLD BT_COMMON_COLOR_FG_RED
44 #define COLOR_EVENT_NAME BT_COMMON_COLOR_BOLD BT_COMMON_COLOR_FG_MAGENTA
45 #define COLOR_TIMESTAMP BT_COMMON_COLOR_BOLD BT_COMMON_COLOR_FG_YELLOW
48 int64_t real_timestamp
; /* Relative to UNIX epoch. */
49 uint64_t clock_snapshot
; /* In cycles. */
53 int print_field(struct pretty_component
*pretty
,
54 const bt_field
*field
, bool print_names
,
55 GQuark
*filters_fields
, int filter_array_len
);
58 void print_name_equal(struct pretty_component
*pretty
, const char *name
)
60 if (pretty
->use_colors
) {
61 g_string_append_printf(pretty
->string
, "%s%s%s = ", COLOR_NAME
,
64 g_string_append_printf(pretty
->string
, "%s = ", name
);
69 void print_field_name_equal(struct pretty_component
*pretty
, const char *name
)
71 if (pretty
->use_colors
) {
72 g_string_append_printf(pretty
->string
, "%s%s%s = ",
73 COLOR_FIELD_NAME
, name
, COLOR_RST
);
75 g_string_append_printf(pretty
->string
, "%s = ", name
);
80 void print_timestamp_cycles(struct pretty_component
*pretty
,
81 const bt_clock_snapshot
*clock_snapshot
)
85 cycles
= bt_clock_snapshot_get_value(clock_snapshot
);
86 g_string_append_printf(pretty
->string
, "%020" PRIu64
, cycles
);
88 if (pretty
->last_cycles_timestamp
!= -1ULL) {
89 pretty
->delta_cycles
= cycles
- pretty
->last_cycles_timestamp
;
92 pretty
->last_cycles_timestamp
= cycles
;
96 void print_timestamp_wall(struct pretty_component
*pretty
,
97 const bt_clock_snapshot
*clock_snapshot
)
100 int64_t ts_nsec
= 0; /* add configurable offset */
101 int64_t ts_sec
= 0; /* add configurable offset */
102 uint64_t ts_sec_abs
, ts_nsec_abs
;
105 if (!clock_snapshot
) {
106 g_string_append(pretty
->string
, "??:??:??.?????????");
110 ret
= bt_clock_snapshot_get_ns_from_origin(clock_snapshot
, &ts_nsec
);
112 // TODO: log, this is unexpected
113 g_string_append(pretty
->string
, "Error");
117 if (pretty
->last_real_timestamp
!= -1ULL) {
118 pretty
->delta_real_timestamp
= ts_nsec
- pretty
->last_real_timestamp
;
121 pretty
->last_real_timestamp
= ts_nsec
;
122 ts_sec
+= ts_nsec
/ NSEC_PER_SEC
;
123 ts_nsec
= ts_nsec
% NSEC_PER_SEC
;
125 if (ts_sec
>= 0 && ts_nsec
>= 0) {
128 ts_nsec_abs
= ts_nsec
;
129 } else if (ts_sec
> 0 && ts_nsec
< 0) {
131 ts_sec_abs
= ts_sec
- 1;
132 ts_nsec_abs
= NSEC_PER_SEC
+ ts_nsec
;
133 } else if (ts_sec
== 0 && ts_nsec
< 0) {
136 ts_nsec_abs
= -ts_nsec
;
137 } else if (ts_sec
< 0 && ts_nsec
> 0) {
139 ts_sec_abs
= -(ts_sec
+ 1);
140 ts_nsec_abs
= NSEC_PER_SEC
- ts_nsec
;
141 } else if (ts_sec
< 0 && ts_nsec
== 0) {
143 ts_sec_abs
= -ts_sec
;
144 ts_nsec_abs
= ts_nsec
;
145 } else { /* (ts_sec < 0 && ts_nsec < 0) */
147 ts_sec_abs
= -ts_sec
;
148 ts_nsec_abs
= -ts_nsec
;
151 if (!pretty
->options
.clock_seconds
) {
153 time_t time_s
= (time_t) ts_sec_abs
;
155 if (is_negative
&& !pretty
->negative_timestamp_warning_done
) {
157 fprintf(stderr
, "[warning] Fallback to [sec.ns] to print negative time value. Use --clock-seconds.\n");
158 pretty
->negative_timestamp_warning_done
= true;
162 if (!pretty
->options
.clock_gmt
) {
165 res
= bt_localtime_r(&time_s
, &tm
);
168 fprintf(stderr
, "[warning] Unable to get localtime.\n");
174 res
= bt_gmtime_r(&time_s
, &tm
);
177 fprintf(stderr
, "[warning] Unable to get gmtime.\n");
181 if (pretty
->options
.clock_date
) {
185 /* Print date and time */
186 res
= strftime(timestr
, sizeof(timestr
),
190 fprintf(stderr
, "[warning] Unable to print ascii time.\n");
194 g_string_append(pretty
->string
, timestr
);
197 /* Print time in HH:MM:SS.ns */
198 g_string_append_printf(pretty
->string
,
199 "%02d:%02d:%02d.%09" PRIu64
, tm
.tm_hour
, tm
.tm_min
,
200 tm
.tm_sec
, ts_nsec_abs
);
204 g_string_append_printf(pretty
->string
, "%s%" PRId64
".%09" PRIu64
,
205 is_negative
? "-" : "", ts_sec_abs
, ts_nsec_abs
);
211 int print_event_timestamp(struct pretty_component
*pretty
,
212 const bt_message
*event_msg
, bool *start_line
)
214 bool print_names
= pretty
->options
.print_header_field_names
;
216 const bt_stream
*stream
= NULL
;
217 const bt_stream_class
*stream_class
= NULL
;
218 const bt_clock_snapshot
*clock_snapshot
= NULL
;
219 const bt_event
*event
= bt_message_event_borrow_event_const(event_msg
);
221 stream
= bt_event_borrow_stream_const(event
);
222 stream_class
= bt_stream_borrow_class_const(stream
);
224 if (!bt_stream_class_borrow_default_clock_class_const(stream_class
)) {
225 /* No default clock class: skip the timestamp without an error */
229 if (bt_message_event_borrow_default_clock_snapshot_const(event_msg
,
230 &clock_snapshot
) != BT_CLOCK_SNAPSHOT_STATE_KNOWN
) {
231 /* No default clock value: skip the timestamp without an error */
236 print_name_equal(pretty
, "timestamp");
238 g_string_append(pretty
->string
, "[");
240 if (pretty
->use_colors
) {
241 g_string_append(pretty
->string
, COLOR_TIMESTAMP
);
243 if (pretty
->options
.print_timestamp_cycles
) {
244 print_timestamp_cycles(pretty
, clock_snapshot
);
246 print_timestamp_wall(pretty
, clock_snapshot
);
248 if (pretty
->use_colors
) {
249 g_string_append(pretty
->string
, COLOR_RST
);
253 g_string_append(pretty
->string
, "] ");
255 if (pretty
->options
.print_delta_field
) {
257 g_string_append(pretty
->string
, ", ");
258 print_name_equal(pretty
, "delta");
260 g_string_append(pretty
->string
, "(");
262 if (pretty
->options
.print_timestamp_cycles
) {
263 if (pretty
->delta_cycles
== -1ULL) {
264 g_string_append(pretty
->string
,
265 "+??????????\?\?) "); /* Not a trigraph. */
267 g_string_append_printf(pretty
->string
,
268 "+%012" PRIu64
, pretty
->delta_cycles
);
271 if (pretty
->delta_real_timestamp
!= -1ULL) {
272 uint64_t delta_sec
, delta_nsec
, delta
;
274 delta
= pretty
->delta_real_timestamp
;
275 delta_sec
= delta
/ NSEC_PER_SEC
;
276 delta_nsec
= delta
% NSEC_PER_SEC
;
277 g_string_append_printf(pretty
->string
,
278 "+%" PRIu64
".%09" PRIu64
,
279 delta_sec
, delta_nsec
);
281 g_string_append(pretty
->string
, "+?.?????????");
285 g_string_append(pretty
->string
, ") ");
288 *start_line
= !print_names
;
295 int print_event_header(struct pretty_component
*pretty
,
296 const bt_message
*event_msg
)
298 bool print_names
= pretty
->options
.print_header_field_names
;
300 const bt_event_class
*event_class
= NULL
;
301 const bt_stream_class
*stream_class
= NULL
;
302 const bt_trace_class
*trace_class
= NULL
;
303 const bt_packet
*packet
= NULL
;
304 const bt_stream
*stream
= NULL
;
305 const bt_trace
*trace
= NULL
;
306 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_class
= bt_event_class_borrow_stream_class_const(event_class
);
312 trace_class
= bt_stream_class_borrow_trace_class_const(stream_class
);
313 packet
= bt_event_borrow_packet_const(event
);
314 stream
= bt_packet_borrow_stream_const(packet
);
315 trace
= bt_stream_borrow_trace_const(stream
);
316 ret
= print_event_timestamp(pretty
, event_msg
, &pretty
->start_line
);
320 if (pretty
->options
.print_trace_field
) {
323 name
= bt_trace_get_name(trace
);
325 if (!pretty
->start_line
) {
326 g_string_append(pretty
->string
, ", ");
329 print_name_equal(pretty
, "trace");
332 g_string_append(pretty
->string
, name
);
335 g_string_append(pretty
->string
, " ");
339 if (pretty
->options
.print_trace_hostname_field
) {
340 const bt_value
*hostname_str
;
342 hostname_str
= bt_trace_class_borrow_environment_entry_value_by_name_const(
343 trace_class
, "hostname");
347 if (!pretty
->start_line
) {
348 g_string_append(pretty
->string
, ", ");
351 print_name_equal(pretty
, "trace:hostname");
353 str
= bt_value_string_get(hostname_str
);
354 g_string_append(pretty
->string
, str
);
358 if (pretty
->options
.print_trace_domain_field
) {
359 const bt_value
*domain_str
;
361 domain_str
= bt_trace_class_borrow_environment_entry_value_by_name_const(
362 trace_class
, "domain");
366 if (!pretty
->start_line
) {
367 g_string_append(pretty
->string
, ", ");
370 print_name_equal(pretty
, "trace:domain");
371 } else if (dom_print
) {
372 g_string_append(pretty
->string
, ":");
374 str
= bt_value_string_get(domain_str
);
375 g_string_append(pretty
->string
, str
);
379 if (pretty
->options
.print_trace_procname_field
) {
380 const bt_value
*procname_str
;
382 procname_str
= bt_trace_class_borrow_environment_entry_value_by_name_const(
383 trace_class
, "procname");
387 if (!pretty
->start_line
) {
388 g_string_append(pretty
->string
, ", ");
391 print_name_equal(pretty
, "trace:procname");
392 } else if (dom_print
) {
393 g_string_append(pretty
->string
, ":");
395 str
= bt_value_string_get(procname_str
);
396 g_string_append(pretty
->string
, str
);
400 if (pretty
->options
.print_trace_vpid_field
) {
401 const bt_value
*vpid_value
;
403 vpid_value
= bt_trace_class_borrow_environment_entry_value_by_name_const(
404 trace_class
, "vpid");
408 if (!pretty
->start_line
) {
409 g_string_append(pretty
->string
, ", ");
412 print_name_equal(pretty
, "trace:vpid");
413 } else if (dom_print
) {
414 g_string_append(pretty
->string
, ":");
416 value
= bt_value_integer_get(vpid_value
);
417 g_string_append_printf(pretty
->string
,
418 "(%" PRId64
")", value
);
422 if (pretty
->options
.print_loglevel_field
) {
423 static const char *log_level_names
[] = {
424 [ BT_EVENT_CLASS_LOG_LEVEL_EMERGENCY
] = "TRACE_EMERG",
425 [ BT_EVENT_CLASS_LOG_LEVEL_ALERT
] = "TRACE_ALERT",
426 [ BT_EVENT_CLASS_LOG_LEVEL_CRITICAL
] = "TRACE_CRIT",
427 [ BT_EVENT_CLASS_LOG_LEVEL_ERROR
] = "TRACE_ERR",
428 [ BT_EVENT_CLASS_LOG_LEVEL_WARNING
] = "TRACE_WARNING",
429 [ BT_EVENT_CLASS_LOG_LEVEL_NOTICE
] = "TRACE_NOTICE",
430 [ BT_EVENT_CLASS_LOG_LEVEL_INFO
] = "TRACE_INFO",
431 [ BT_EVENT_CLASS_LOG_LEVEL_DEBUG_SYSTEM
] = "TRACE_DEBUG_SYSTEM",
432 [ BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROGRAM
] = "TRACE_DEBUG_PROGRAM",
433 [ BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROCESS
] = "TRACE_DEBUG_PROCESS",
434 [ BT_EVENT_CLASS_LOG_LEVEL_DEBUG_MODULE
] = "TRACE_DEBUG_MODULE",
435 [ BT_EVENT_CLASS_LOG_LEVEL_DEBUG_UNIT
] = "TRACE_DEBUG_UNIT",
436 [ BT_EVENT_CLASS_LOG_LEVEL_DEBUG_FUNCTION
] = "TRACE_DEBUG_FUNCTION",
437 [ BT_EVENT_CLASS_LOG_LEVEL_DEBUG_LINE
] = "TRACE_DEBUG_LINE",
438 [ BT_EVENT_CLASS_LOG_LEVEL_DEBUG
] = "TRACE_DEBUG",
440 bt_event_class_log_level log_level
;
441 const char *log_level_str
= NULL
;
443 prop_avail
= bt_event_class_get_log_level(event_class
,
445 if (prop_avail
== BT_PROPERTY_AVAILABILITY_AVAILABLE
) {
446 log_level_str
= log_level_names
[log_level
];
447 BT_ASSERT(log_level_str
);
449 if (!pretty
->start_line
) {
450 g_string_append(pretty
->string
, ", ");
453 print_name_equal(pretty
, "loglevel");
454 } else if (dom_print
) {
455 g_string_append(pretty
->string
, ":");
458 g_string_append(pretty
->string
, log_level_str
);
459 g_string_append_printf(
460 pretty
->string
, " (%d)", (int) log_level
);
464 if (pretty
->options
.print_emf_field
) {
467 uri_str
= bt_event_class_get_emf_uri(event_class
);
469 if (!pretty
->start_line
) {
470 g_string_append(pretty
->string
, ", ");
473 print_name_equal(pretty
, "model.emf.uri");
474 } else if (dom_print
) {
475 g_string_append(pretty
->string
, ":");
478 g_string_append(pretty
->string
, uri_str
);
482 if (dom_print
&& !print_names
) {
483 g_string_append(pretty
->string
, " ");
485 if (!pretty
->start_line
) {
486 g_string_append(pretty
->string
, ", ");
488 pretty
->start_line
= true;
490 print_name_equal(pretty
, "name");
492 if (pretty
->use_colors
) {
493 g_string_append(pretty
->string
, COLOR_EVENT_NAME
);
495 g_string_append(pretty
->string
, bt_event_class_get_name(event_class
));
496 if (pretty
->use_colors
) {
497 g_string_append(pretty
->string
, COLOR_RST
);
500 g_string_append(pretty
->string
, ": ");
502 g_string_append(pretty
->string
, ", ");
510 int print_integer(struct pretty_component
*pretty
,
511 const bt_field
*field
)
514 bt_field_class_integer_preferred_display_base base
;
515 const bt_field_class
*int_fc
;
520 bool rst_color
= false;
521 bt_field_class_type ft_type
;
523 int_fc
= bt_field_borrow_class_const(field
);
525 ft_type
= bt_field_get_class_type(field
);
526 if (ft_type
== BT_FIELD_CLASS_TYPE_UNSIGNED_INTEGER
||
527 ft_type
== BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION
) {
528 v
.u
= bt_field_unsigned_integer_get_value(field
);
530 v
.s
= bt_field_signed_integer_get_value(field
);
533 if (pretty
->use_colors
) {
534 g_string_append(pretty
->string
, COLOR_NUMBER_VALUE
);
538 base
= bt_field_class_integer_get_preferred_display_base(int_fc
);
540 case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_BINARY
:
544 len
= bt_field_class_integer_get_field_value_range(int_fc
);
545 g_string_append(pretty
->string
, "0b");
546 v
.u
= _bt_piecewise_lshift(v
.u
, 64 - len
);
547 for (bitnr
= 0; bitnr
< len
; bitnr
++) {
548 g_string_append_printf(pretty
->string
, "%u", (v
.u
& (1ULL << 63)) ? 1 : 0);
549 v
.u
= _bt_piecewise_lshift(v
.u
, 1);
553 case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_OCTAL
:
555 if (ft_type
== BT_FIELD_CLASS_TYPE_SIGNED_INTEGER
||
556 ft_type
== BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION
) {
559 len
= bt_field_class_integer_get_field_value_range(
565 /* Round length to the nearest 3-bit */
566 rounded_len
= (((len
- 1) / 3) + 1) * 3;
567 v
.u
&= ((uint64_t) 1 << rounded_len
) - 1;
571 g_string_append_printf(pretty
->string
, "0%" PRIo64
, v
.u
);
574 case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
:
575 if (ft_type
== BT_FIELD_CLASS_TYPE_UNSIGNED_INTEGER
||
576 ft_type
== BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION
) {
577 g_string_append_printf(pretty
->string
, "%" PRIu64
, v
.u
);
579 g_string_append_printf(pretty
->string
, "%" PRId64
, v
.s
);
582 case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL
:
586 len
= bt_field_class_integer_get_field_value_range(int_fc
);
588 /* Round length to the nearest nibble */
589 uint8_t rounded_len
= ((len
+ 3) & ~0x3);
591 v
.u
&= ((uint64_t) 1 << rounded_len
) - 1;
594 g_string_append_printf(pretty
->string
, "0x%" PRIX64
, v
.u
);
603 g_string_append(pretty
->string
, COLOR_RST
);
609 void print_escape_string(struct pretty_component
*pretty
, const char *str
)
613 g_string_append_c(pretty
->string
, '"');
615 for (i
= 0; i
< strlen(str
); i
++) {
616 /* Escape sequences not recognized by iscntrl(). */
619 g_string_append(pretty
->string
, "\\\\");
622 g_string_append(pretty
->string
, "\\\'");
625 g_string_append(pretty
->string
, "\\\"");
628 g_string_append(pretty
->string
, "\\\?");
632 /* Standard characters. */
633 if (!iscntrl(str
[i
])) {
634 g_string_append_c(pretty
->string
, str
[i
]);
640 g_string_append(pretty
->string
, "\\0");
643 g_string_append(pretty
->string
, "\\a");
646 g_string_append(pretty
->string
, "\\b");
649 g_string_append(pretty
->string
, "\\e");
652 g_string_append(pretty
->string
, "\\f");
655 g_string_append(pretty
->string
, "\\n");
658 g_string_append(pretty
->string
, "\\r");
661 g_string_append(pretty
->string
, "\\t");
664 g_string_append(pretty
->string
, "\\v");
667 /* Unhandled control-sequence, print as hex. */
668 g_string_append_printf(pretty
->string
, "\\x%02x", str
[i
]);
673 g_string_append_c(pretty
->string
, '"');
677 int print_enum(struct pretty_component
*pretty
,
678 const bt_field
*field
)
681 const bt_field_class
*enumeration_field_class
= NULL
;
682 bt_field_class_enumeration_mapping_label_array label_array
;
683 uint64_t label_count
;
686 enumeration_field_class
= bt_field_borrow_class_const(field
);
687 if (!enumeration_field_class
) {
692 switch (bt_field_get_class_type(field
)) {
693 case BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION
:
694 ret
= bt_field_unsigned_enumeration_get_mapping_labels(field
,
695 &label_array
, &label_count
);
697 case BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION
:
698 ret
= bt_field_signed_enumeration_get_mapping_labels(field
,
699 &label_array
, &label_count
);
710 g_string_append(pretty
->string
, "( ");
711 if (label_count
== 0) {
712 if (pretty
->use_colors
) {
713 g_string_append(pretty
->string
, COLOR_UNKNOWN
);
715 g_string_append(pretty
->string
, "<unknown>");
716 if (pretty
->use_colors
) {
717 g_string_append(pretty
->string
, COLOR_RST
);
721 for (i
= 0; i
< label_count
; i
++) {
722 const char *mapping_name
= label_array
[i
];
725 g_string_append(pretty
->string
, ", ");
727 if (pretty
->use_colors
) {
728 g_string_append(pretty
->string
, COLOR_ENUM_MAPPING_NAME
);
730 print_escape_string(pretty
, mapping_name
);
731 if (pretty
->use_colors
) {
732 g_string_append(pretty
->string
, COLOR_RST
);
736 g_string_append(pretty
->string
, " : container = ");
737 ret
= print_integer(pretty
, field
);
741 g_string_append(pretty
->string
, " )");
747 int filter_field_name(struct pretty_component
*pretty
, const char *field_name
,
748 GQuark
*filter_fields
, int filter_array_len
)
751 GQuark field_quark
= g_quark_try_string(field_name
);
753 if (!field_quark
|| pretty
->options
.verbose
) {
757 for (i
= 0; i
< filter_array_len
; i
++) {
758 if (field_quark
== filter_fields
[i
]) {
766 int print_struct_field(struct pretty_component
*pretty
,
767 const bt_field
*_struct
,
768 const bt_field_class
*struct_class
,
769 uint64_t i
, bool print_names
, uint64_t *nr_printed_fields
,
770 GQuark
*filter_fields
, int filter_array_len
)
773 const char *field_name
;
774 const bt_field
*field
= NULL
;
775 const bt_field_class
*field_class
= NULL
;;
777 field
= bt_field_structure_borrow_member_field_by_index_const(_struct
, i
);
783 bt_field_class_structure_borrow_member_by_index_const(struct_class
, i
,
784 &field_name
, &field_class
);
786 if (filter_fields
&& !filter_field_name(pretty
, field_name
,
787 filter_fields
, filter_array_len
)) {
792 if (*nr_printed_fields
> 0) {
793 g_string_append(pretty
->string
, ", ");
795 g_string_append(pretty
->string
, " ");
798 print_field_name_equal(pretty
, field_name
);
800 ret
= print_field(pretty
, field
, print_names
, NULL
, 0);
801 *nr_printed_fields
+= 1;
808 int print_struct(struct pretty_component
*pretty
,
809 const bt_field
*_struct
, bool print_names
,
810 GQuark
*filter_fields
, int filter_array_len
)
813 const bt_field_class
*struct_class
= NULL
;
814 uint64_t nr_fields
, i
, nr_printed_fields
;
816 struct_class
= bt_field_borrow_class_const(_struct
);
821 nr_fields
= bt_field_class_structure_get_member_count(struct_class
);
826 g_string_append(pretty
->string
, "{");
828 nr_printed_fields
= 0;
829 for (i
= 0; i
< nr_fields
; i
++) {
830 ret
= print_struct_field(pretty
, _struct
, struct_class
, i
,
831 print_names
, &nr_printed_fields
, filter_fields
,
838 g_string_append(pretty
->string
, " }");
845 int print_array_field(struct pretty_component
*pretty
,
846 const bt_field
*array
, uint64_t i
, bool print_names
)
848 const bt_field
*field
= NULL
;
851 g_string_append(pretty
->string
, ", ");
853 g_string_append(pretty
->string
, " ");
856 g_string_append_printf(pretty
->string
, "[%" PRIu64
"] = ", i
);
859 field
= bt_field_array_borrow_element_field_by_index_const(array
, i
);
861 return print_field(pretty
, field
, print_names
, NULL
, 0);
865 int print_array(struct pretty_component
*pretty
,
866 const bt_field
*array
, bool print_names
)
869 const bt_field_class
*array_class
= NULL
;
873 array_class
= bt_field_borrow_class_const(array
);
878 len
= bt_field_array_get_length(array
);
879 g_string_append(pretty
->string
, "[");
881 for (i
= 0; i
< len
; i
++) {
882 ret
= print_array_field(pretty
, array
, i
, print_names
);
888 g_string_append(pretty
->string
, " ]");
895 int print_sequence_field(struct pretty_component
*pretty
,
896 const bt_field
*seq
, uint64_t i
, bool print_names
)
898 const bt_field
*field
= NULL
;
901 g_string_append(pretty
->string
, ", ");
903 g_string_append(pretty
->string
, " ");
906 g_string_append_printf(pretty
->string
, "[%" PRIu64
"] = ", i
);
909 field
= bt_field_array_borrow_element_field_by_index_const(seq
, i
);
911 return print_field(pretty
, field
, print_names
, NULL
, 0);
915 int print_sequence(struct pretty_component
*pretty
,
916 const bt_field
*seq
, bool print_names
)
922 len
= bt_field_array_get_length(seq
);
928 g_string_append(pretty
->string
, "[");
931 for (i
= 0; i
< len
; i
++) {
932 ret
= print_sequence_field(pretty
, seq
, i
, print_names
);
938 g_string_append(pretty
->string
, " ]");
945 int print_variant(struct pretty_component
*pretty
,
946 const bt_field
*variant
, bool print_names
)
949 const bt_field
*field
= NULL
;
951 field
= bt_field_variant_borrow_selected_option_field_const(variant
);
953 g_string_append(pretty
->string
, "{ ");
956 // TODO: find tag's name using field path
957 // print_field_name_equal(pretty, tag_choice);
959 ret
= print_field(pretty
, field
, print_names
, NULL
, 0);
964 g_string_append(pretty
->string
, " }");
971 int print_field(struct pretty_component
*pretty
,
972 const bt_field
*field
, bool print_names
,
973 GQuark
*filter_fields
, int filter_array_len
)
975 bt_field_class_type class_id
;
977 class_id
= bt_field_get_class_type(field
);
979 case BT_FIELD_CLASS_TYPE_UNSIGNED_INTEGER
:
980 case BT_FIELD_CLASS_TYPE_SIGNED_INTEGER
:
981 return print_integer(pretty
, field
);
982 case BT_FIELD_CLASS_TYPE_REAL
:
986 v
= bt_field_real_get_value(field
);
987 if (pretty
->use_colors
) {
988 g_string_append(pretty
->string
, COLOR_NUMBER_VALUE
);
990 g_string_append_printf(pretty
->string
, "%g", v
);
991 if (pretty
->use_colors
) {
992 g_string_append(pretty
->string
, COLOR_RST
);
996 case BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION
:
997 case BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION
:
998 return print_enum(pretty
, field
);
999 case BT_FIELD_CLASS_TYPE_STRING
:
1003 str
= bt_field_string_get_value(field
);
1008 if (pretty
->use_colors
) {
1009 g_string_append(pretty
->string
, COLOR_STRING_VALUE
);
1011 print_escape_string(pretty
, str
);
1012 if (pretty
->use_colors
) {
1013 g_string_append(pretty
->string
, COLOR_RST
);
1017 case BT_FIELD_CLASS_TYPE_STRUCTURE
:
1018 return print_struct(pretty
, field
, print_names
, filter_fields
,
1020 case BT_FIELD_CLASS_TYPE_VARIANT
:
1021 return print_variant(pretty
, field
, print_names
);
1022 case BT_FIELD_CLASS_TYPE_STATIC_ARRAY
:
1023 return print_array(pretty
, field
, print_names
);
1024 case BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY
:
1025 return print_sequence(pretty
, field
, print_names
);
1027 // TODO: log instead
1028 fprintf(pretty
->err
, "[error] Unknown type id: %d\n", (int) class_id
);
1034 int print_stream_packet_context(struct pretty_component
*pretty
,
1035 const bt_event
*event
)
1038 const bt_packet
*packet
= NULL
;
1039 const bt_field
*main_field
= NULL
;
1041 packet
= bt_event_borrow_packet_const(event
);
1046 main_field
= bt_packet_borrow_context_field_const(packet
);
1050 if (!pretty
->start_line
) {
1051 g_string_append(pretty
->string
, ", ");
1053 pretty
->start_line
= false;
1054 if (pretty
->options
.print_scope_field_names
) {
1055 print_name_equal(pretty
, "stream.packet.context");
1057 ret
= print_field(pretty
, main_field
,
1058 pretty
->options
.print_context_field_names
,
1059 stream_packet_context_quarks
,
1060 STREAM_PACKET_CONTEXT_QUARKS_LEN
);
1067 int print_stream_event_context(struct pretty_component
*pretty
,
1068 const bt_event
*event
)
1071 const bt_field
*main_field
= NULL
;
1073 main_field
= bt_event_borrow_common_context_field_const(event
);
1077 if (!pretty
->start_line
) {
1078 g_string_append(pretty
->string
, ", ");
1080 pretty
->start_line
= false;
1081 if (pretty
->options
.print_scope_field_names
) {
1082 print_name_equal(pretty
, "stream.event.context");
1084 ret
= print_field(pretty
, main_field
,
1085 pretty
->options
.print_context_field_names
, NULL
, 0);
1092 int print_event_context(struct pretty_component
*pretty
,
1093 const bt_event
*event
)
1096 const bt_field
*main_field
= NULL
;
1098 main_field
= bt_event_borrow_specific_context_field_const(event
);
1102 if (!pretty
->start_line
) {
1103 g_string_append(pretty
->string
, ", ");
1105 pretty
->start_line
= false;
1106 if (pretty
->options
.print_scope_field_names
) {
1107 print_name_equal(pretty
, "event.context");
1109 ret
= print_field(pretty
, main_field
,
1110 pretty
->options
.print_context_field_names
, NULL
, 0);
1117 int print_event_payload(struct pretty_component
*pretty
,
1118 const bt_event
*event
)
1121 const bt_field
*main_field
= NULL
;
1123 main_field
= bt_event_borrow_payload_field_const(event
);
1127 if (!pretty
->start_line
) {
1128 g_string_append(pretty
->string
, ", ");
1130 pretty
->start_line
= false;
1131 if (pretty
->options
.print_scope_field_names
) {
1132 print_name_equal(pretty
, "event.fields");
1134 ret
= print_field(pretty
, main_field
,
1135 pretty
->options
.print_payload_field_names
, NULL
, 0);
1142 int flush_buf(FILE *stream
, struct pretty_component
*pretty
)
1146 if (pretty
->string
->len
== 0) {
1150 if (fwrite(pretty
->string
->str
, pretty
->string
->len
, 1, stream
) != 1) {
1159 int pretty_print_event(struct pretty_component
*pretty
,
1160 const bt_message
*event_msg
)
1163 const bt_event
*event
=
1164 bt_message_event_borrow_event_const(event_msg
);
1167 pretty
->start_line
= true;
1168 g_string_assign(pretty
->string
, "");
1169 ret
= print_event_header(pretty
, event_msg
);
1174 ret
= print_stream_packet_context(pretty
, event
);
1179 ret
= print_stream_event_context(pretty
, event
);
1184 ret
= print_event_context(pretty
, event
);
1189 ret
= print_event_payload(pretty
, event
);
1194 g_string_append_c(pretty
->string
, '\n');
1195 if (flush_buf(pretty
->out
, pretty
)) {
1205 int print_discarded_elements_msg(struct pretty_component
*pretty
,
1206 const bt_stream
*stream
,
1207 const bt_clock_snapshot
*begin_clock_snapshot
,
1208 const bt_clock_snapshot
*end_clock_snapshot
,
1209 uint64_t count
, const char *elem_type
)
1212 const bt_stream_class
*stream_class
= NULL
;
1213 const bt_trace
*trace
= NULL
;
1214 const char *stream_name
;
1215 const char *trace_name
;
1217 int64_t stream_class_id
;
1221 stream_name
= bt_stream_get_name(stream
);
1223 stream_name
= "(unknown)";
1226 /* Stream class ID */
1227 stream_class
= bt_stream_borrow_class_const(stream
);
1228 BT_ASSERT(stream_class
);
1229 stream_class_id
= bt_stream_class_get_id(stream_class
);
1232 stream_id
= bt_stream_get_id(stream
);
1235 trace
= bt_stream_borrow_trace_const(stream
);
1237 trace_name
= bt_trace_get_name(trace
);
1239 trace_name
= "(unknown)";
1243 trace_uuid
= bt_trace_class_get_uuid(
1244 bt_trace_borrow_class_const(trace
));
1246 /* Format message */
1247 g_string_assign(pretty
->string
, "");
1248 g_string_append_printf(pretty
->string
,
1249 "%s%sWARNING%s%s: Tracer discarded ",
1250 bt_common_color_fg_yellow(),
1251 bt_common_color_bold(),
1252 bt_common_color_reset(),
1253 bt_common_color_fg_yellow());
1255 if (count
== UINT64_C(-1)) {
1256 g_string_append_printf(pretty
->string
, "a number of %ss",
1259 g_string_append_printf(pretty
->string
,
1260 "%" PRIu64
" %s%s", count
, elem_type
,
1261 count
== 1 ? "" : "s");
1264 if (begin_clock_snapshot
&& end_clock_snapshot
) {
1265 g_string_append(pretty
->string
, " between [");
1266 print_timestamp_wall(pretty
, begin_clock_snapshot
);
1267 g_string_append(pretty
->string
, "] and [");
1268 print_timestamp_wall(pretty
, end_clock_snapshot
);
1269 g_string_append(pretty
->string
, "]");
1271 g_string_append(pretty
->string
, "(unknown time range)");
1274 g_string_append_printf(pretty
->string
, " in trace \"%s\" ", trace_name
);
1277 g_string_append_printf(pretty
->string
,
1278 "(UUID: %02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x) ",
1296 g_string_append(pretty
->string
, "(no UUID) ");
1299 g_string_append_printf(pretty
->string
,
1300 "within stream \"%s\" (stream class ID: %" PRIu64
", ",
1301 stream_name
, stream_class_id
);
1303 if (stream_id
>= 0) {
1304 g_string_append_printf(pretty
->string
,
1305 "stream ID: %" PRIu64
, stream_id
);
1307 g_string_append(pretty
->string
, "no stream ID");
1310 g_string_append_printf(pretty
->string
, ").%s\n",
1311 bt_common_color_reset());
1314 * Print to standard error stream to remain backward compatible
1315 * with Babeltrace 1.
1317 if (flush_buf(stderr
, pretty
)) {
1325 int pretty_print_discarded_items(struct pretty_component
*pretty
,
1326 const bt_message
*msg
)
1328 const bt_clock_snapshot
*begin
= NULL
;
1329 const bt_clock_snapshot
*end
= NULL
;
1330 const bt_stream
*stream
;
1331 const bt_stream_class
*stream_class
;
1332 uint64_t count
= UINT64_C(-1);
1333 const char *elem_type
;
1335 switch (bt_message_get_type(msg
)) {
1336 case BT_MESSAGE_TYPE_DISCARDED_EVENTS
:
1337 stream
= bt_message_discarded_events_borrow_stream_const(msg
);
1339 if (bt_message_discarded_events_get_count(msg
, &count
) ==
1340 BT_PROPERTY_AVAILABILITY_NOT_AVAILABLE
) {
1341 count
= UINT64_C(-1);
1344 elem_type
= "event";
1346 case BT_MESSAGE_TYPE_DISCARDED_PACKETS
:
1347 stream
= bt_message_discarded_packets_borrow_stream_const(msg
);
1349 if (bt_message_discarded_packets_get_count(msg
, &count
) ==
1350 BT_PROPERTY_AVAILABILITY_NOT_AVAILABLE
) {
1351 count
= UINT64_C(-1);
1354 elem_type
= "packet";
1361 stream_class
= bt_stream_borrow_class_const(stream
);
1363 if (bt_stream_class_borrow_default_clock_class_const(stream_class
)) {
1364 switch (bt_message_get_type(msg
)) {
1365 case BT_MESSAGE_TYPE_DISCARDED_EVENTS
:
1366 bt_message_discarded_events_borrow_default_beginning_clock_snapshot_const(
1368 bt_message_discarded_events_borrow_default_end_clock_snapshot_const(
1371 case BT_MESSAGE_TYPE_DISCARDED_PACKETS
:
1372 bt_message_discarded_packets_borrow_default_beginning_clock_snapshot_const(
1374 bt_message_discarded_packets_borrow_default_end_clock_snapshot_const(
1382 print_discarded_elements_msg(pretty
, stream
, begin
, end
,