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_event
*event
)
83 const bt_clock_snapshot
*clock_snapshot
;
85 bt_clock_snapshot_state cs_state
;
87 cs_state
= bt_event_borrow_default_clock_snapshot_const(event
, &clock_snapshot
);
88 if (cs_state
!= BT_CLOCK_SNAPSHOT_STATE_KNOWN
|| !clock_snapshot
) {
89 g_string_append(pretty
->string
, "????????????????????");
93 cycles
= bt_clock_snapshot_get_value(clock_snapshot
);
94 g_string_append_printf(pretty
->string
, "%020" PRIu64
, cycles
);
96 if (pretty
->last_cycles_timestamp
!= -1ULL) {
97 pretty
->delta_cycles
= cycles
- pretty
->last_cycles_timestamp
;
99 pretty
->last_cycles_timestamp
= cycles
;
103 void print_timestamp_wall(struct pretty_component
*pretty
,
104 const bt_clock_snapshot
*clock_snapshot
)
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 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 g_string_append(pretty
->string
, "Error");
124 if (pretty
->last_real_timestamp
!= -1ULL) {
125 pretty
->delta_real_timestamp
= ts_nsec
- pretty
->last_real_timestamp
;
128 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_event
*event
, bool *start_line
)
221 bool print_names
= pretty
->options
.print_header_field_names
;
223 const bt_stream
*stream
= NULL
;
224 const bt_stream_class
*stream_class
= NULL
;
225 const bt_clock_snapshot
*clock_snapshot
= NULL
;
226 bt_clock_snapshot_state cs_state
;
228 stream
= bt_event_borrow_stream_const(event
);
234 stream_class
= bt_stream_borrow_class_const(stream
);
240 cs_state
= bt_event_borrow_default_clock_snapshot_const(event
,
242 if (cs_state
!= BT_CLOCK_SNAPSHOT_STATE_KNOWN
|| !clock_snapshot
) {
243 /* No default clock value: skip the timestamp without an error */
248 print_name_equal(pretty
, "timestamp");
250 g_string_append(pretty
->string
, "[");
252 if (pretty
->use_colors
) {
253 g_string_append(pretty
->string
, COLOR_TIMESTAMP
);
255 if (pretty
->options
.print_timestamp_cycles
) {
256 print_timestamp_cycles(pretty
, event
);
258 clock_snapshot
= NULL
;
259 cs_state
= bt_event_borrow_default_clock_snapshot_const(event
,
261 print_timestamp_wall(pretty
, clock_snapshot
);
263 if (pretty
->use_colors
) {
264 g_string_append(pretty
->string
, COLOR_RST
);
268 g_string_append(pretty
->string
, "] ");
270 if (pretty
->options
.print_delta_field
) {
272 g_string_append(pretty
->string
, ", ");
273 print_name_equal(pretty
, "delta");
275 g_string_append(pretty
->string
, "(");
277 if (pretty
->options
.print_timestamp_cycles
) {
278 if (pretty
->delta_cycles
== -1ULL) {
279 g_string_append(pretty
->string
,
280 "+??????????\?\?) "); /* Not a trigraph. */
282 g_string_append_printf(pretty
->string
,
283 "+%012" PRIu64
, pretty
->delta_cycles
);
286 if (pretty
->delta_real_timestamp
!= -1ULL) {
287 uint64_t delta_sec
, delta_nsec
, delta
;
289 delta
= pretty
->delta_real_timestamp
;
290 delta_sec
= delta
/ NSEC_PER_SEC
;
291 delta_nsec
= delta
% NSEC_PER_SEC
;
292 g_string_append_printf(pretty
->string
,
293 "+%" PRIu64
".%09" PRIu64
,
294 delta_sec
, delta_nsec
);
296 g_string_append(pretty
->string
, "+?.?????????");
300 g_string_append(pretty
->string
, ") ");
303 *start_line
= !print_names
;
310 int print_event_header(struct pretty_component
*pretty
,
311 const bt_event
*event
)
313 bool print_names
= pretty
->options
.print_header_field_names
;
315 const bt_event_class
*event_class
= NULL
;
316 const bt_stream_class
*stream_class
= NULL
;
317 const bt_trace_class
*trace_class
= NULL
;
318 const bt_packet
*packet
= NULL
;
319 const bt_stream
*stream
= NULL
;
320 const bt_trace
*trace
= NULL
;
322 bt_property_availability prop_avail
;
324 event_class
= bt_event_borrow_class_const(event
);
325 stream_class
= bt_event_class_borrow_stream_class_const(event_class
);
326 trace_class
= bt_stream_class_borrow_trace_class_const(stream_class
);
327 packet
= bt_event_borrow_packet_const(event
);
328 stream
= bt_packet_borrow_stream_const(packet
);
329 trace
= bt_stream_borrow_trace_const(stream
);
330 ret
= print_event_timestamp(pretty
, event
, &pretty
->start_line
);
334 if (pretty
->options
.print_trace_field
) {
337 name
= bt_trace_get_name(trace
);
339 if (!pretty
->start_line
) {
340 g_string_append(pretty
->string
, ", ");
343 print_name_equal(pretty
, "trace");
346 g_string_append(pretty
->string
, name
);
349 g_string_append(pretty
->string
, " ");
353 if (pretty
->options
.print_trace_hostname_field
) {
354 const bt_value
*hostname_str
;
356 hostname_str
= bt_trace_class_borrow_environment_entry_value_by_name_const(
357 trace_class
, "hostname");
361 if (!pretty
->start_line
) {
362 g_string_append(pretty
->string
, ", ");
365 print_name_equal(pretty
, "trace:hostname");
367 str
= bt_value_string_get(hostname_str
);
368 g_string_append(pretty
->string
, str
);
372 if (pretty
->options
.print_trace_domain_field
) {
373 const bt_value
*domain_str
;
375 domain_str
= bt_trace_class_borrow_environment_entry_value_by_name_const(
376 trace_class
, "domain");
380 if (!pretty
->start_line
) {
381 g_string_append(pretty
->string
, ", ");
384 print_name_equal(pretty
, "trace:domain");
385 } else if (dom_print
) {
386 g_string_append(pretty
->string
, ":");
388 str
= bt_value_string_get(domain_str
);
389 g_string_append(pretty
->string
, str
);
393 if (pretty
->options
.print_trace_procname_field
) {
394 const bt_value
*procname_str
;
396 procname_str
= bt_trace_class_borrow_environment_entry_value_by_name_const(
397 trace_class
, "procname");
401 if (!pretty
->start_line
) {
402 g_string_append(pretty
->string
, ", ");
405 print_name_equal(pretty
, "trace:procname");
406 } else if (dom_print
) {
407 g_string_append(pretty
->string
, ":");
409 str
= bt_value_string_get(procname_str
);
410 g_string_append(pretty
->string
, str
);
414 if (pretty
->options
.print_trace_vpid_field
) {
415 const bt_value
*vpid_value
;
417 vpid_value
= bt_trace_class_borrow_environment_entry_value_by_name_const(
418 trace_class
, "vpid");
422 if (!pretty
->start_line
) {
423 g_string_append(pretty
->string
, ", ");
426 print_name_equal(pretty
, "trace:vpid");
427 } else if (dom_print
) {
428 g_string_append(pretty
->string
, ":");
430 value
= bt_value_integer_get(vpid_value
);
431 g_string_append_printf(pretty
->string
,
432 "(%" PRId64
")", value
);
436 if (pretty
->options
.print_loglevel_field
) {
437 static const char *log_level_names
[] = {
438 [ BT_EVENT_CLASS_LOG_LEVEL_EMERGENCY
] = "TRACE_EMERG",
439 [ BT_EVENT_CLASS_LOG_LEVEL_ALERT
] = "TRACE_ALERT",
440 [ BT_EVENT_CLASS_LOG_LEVEL_CRITICAL
] = "TRACE_CRIT",
441 [ BT_EVENT_CLASS_LOG_LEVEL_ERROR
] = "TRACE_ERR",
442 [ BT_EVENT_CLASS_LOG_LEVEL_WARNING
] = "TRACE_WARNING",
443 [ BT_EVENT_CLASS_LOG_LEVEL_NOTICE
] = "TRACE_NOTICE",
444 [ BT_EVENT_CLASS_LOG_LEVEL_INFO
] = "TRACE_INFO",
445 [ BT_EVENT_CLASS_LOG_LEVEL_DEBUG_SYSTEM
] = "TRACE_DEBUG_SYSTEM",
446 [ BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROGRAM
] = "TRACE_DEBUG_PROGRAM",
447 [ BT_EVENT_CLASS_LOG_LEVEL_DEBUG_PROCESS
] = "TRACE_DEBUG_PROCESS",
448 [ BT_EVENT_CLASS_LOG_LEVEL_DEBUG_MODULE
] = "TRACE_DEBUG_MODULE",
449 [ BT_EVENT_CLASS_LOG_LEVEL_DEBUG_UNIT
] = "TRACE_DEBUG_UNIT",
450 [ BT_EVENT_CLASS_LOG_LEVEL_DEBUG_FUNCTION
] = "TRACE_DEBUG_FUNCTION",
451 [ BT_EVENT_CLASS_LOG_LEVEL_DEBUG_LINE
] = "TRACE_DEBUG_LINE",
452 [ BT_EVENT_CLASS_LOG_LEVEL_DEBUG
] = "TRACE_DEBUG",
454 bt_event_class_log_level log_level
;
455 const char *log_level_str
= NULL
;
457 prop_avail
= bt_event_class_get_log_level(event_class
,
459 if (prop_avail
== BT_PROPERTY_AVAILABILITY_AVAILABLE
) {
460 log_level_str
= log_level_names
[log_level
];
461 BT_ASSERT(log_level_str
);
463 if (!pretty
->start_line
) {
464 g_string_append(pretty
->string
, ", ");
467 print_name_equal(pretty
, "loglevel");
468 } else if (dom_print
) {
469 g_string_append(pretty
->string
, ":");
472 g_string_append(pretty
->string
, log_level_str
);
473 g_string_append_printf(
474 pretty
->string
, " (%d)", (int) log_level
);
478 if (pretty
->options
.print_emf_field
) {
481 uri_str
= bt_event_class_get_emf_uri(event_class
);
483 if (!pretty
->start_line
) {
484 g_string_append(pretty
->string
, ", ");
487 print_name_equal(pretty
, "model.emf.uri");
488 } else if (dom_print
) {
489 g_string_append(pretty
->string
, ":");
492 g_string_append(pretty
->string
, uri_str
);
496 if (dom_print
&& !print_names
) {
497 g_string_append(pretty
->string
, " ");
499 if (!pretty
->start_line
) {
500 g_string_append(pretty
->string
, ", ");
502 pretty
->start_line
= true;
504 print_name_equal(pretty
, "name");
506 if (pretty
->use_colors
) {
507 g_string_append(pretty
->string
, COLOR_EVENT_NAME
);
509 g_string_append(pretty
->string
, bt_event_class_get_name(event_class
));
510 if (pretty
->use_colors
) {
511 g_string_append(pretty
->string
, COLOR_RST
);
514 g_string_append(pretty
->string
, ": ");
516 g_string_append(pretty
->string
, ", ");
524 int print_integer(struct pretty_component
*pretty
,
525 const bt_field
*field
)
528 bt_field_class_integer_preferred_display_base base
;
529 const bt_field_class
*int_fc
;
534 bool rst_color
= false;
535 bt_field_class_type ft_type
;
537 int_fc
= bt_field_borrow_class_const(field
);
539 ft_type
= bt_field_get_class_type(field
);
540 if (ft_type
== BT_FIELD_CLASS_TYPE_UNSIGNED_INTEGER
||
541 ft_type
== BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION
) {
542 v
.u
= bt_field_unsigned_integer_get_value(field
);
544 v
.s
= bt_field_signed_integer_get_value(field
);
547 if (pretty
->use_colors
) {
548 g_string_append(pretty
->string
, COLOR_NUMBER_VALUE
);
552 base
= bt_field_class_integer_get_preferred_display_base(int_fc
);
554 case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_BINARY
:
558 len
= bt_field_class_integer_get_field_value_range(int_fc
);
559 g_string_append(pretty
->string
, "0b");
560 v
.u
= _bt_piecewise_lshift(v
.u
, 64 - len
);
561 for (bitnr
= 0; bitnr
< len
; bitnr
++) {
562 g_string_append_printf(pretty
->string
, "%u", (v
.u
& (1ULL << 63)) ? 1 : 0);
563 v
.u
= _bt_piecewise_lshift(v
.u
, 1);
567 case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_OCTAL
:
569 if (ft_type
== BT_FIELD_CLASS_TYPE_SIGNED_INTEGER
||
570 ft_type
== BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION
) {
573 len
= bt_field_class_integer_get_field_value_range(
579 /* Round length to the nearest 3-bit */
580 rounded_len
= (((len
- 1) / 3) + 1) * 3;
581 v
.u
&= ((uint64_t) 1 << rounded_len
) - 1;
585 g_string_append_printf(pretty
->string
, "0%" PRIo64
, v
.u
);
588 case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
:
589 if (ft_type
== BT_FIELD_CLASS_TYPE_UNSIGNED_INTEGER
||
590 ft_type
== BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION
) {
591 g_string_append_printf(pretty
->string
, "%" PRIu64
, v
.u
);
593 g_string_append_printf(pretty
->string
, "%" PRId64
, v
.s
);
596 case BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL
:
600 len
= bt_field_class_integer_get_field_value_range(int_fc
);
602 /* Round length to the nearest nibble */
603 uint8_t rounded_len
= ((len
+ 3) & ~0x3);
605 v
.u
&= ((uint64_t) 1 << rounded_len
) - 1;
608 g_string_append_printf(pretty
->string
, "0x%" PRIX64
, v
.u
);
617 g_string_append(pretty
->string
, COLOR_RST
);
623 void print_escape_string(struct pretty_component
*pretty
, const char *str
)
627 g_string_append_c(pretty
->string
, '"');
629 for (i
= 0; i
< strlen(str
); i
++) {
630 /* Escape sequences not recognized by iscntrl(). */
633 g_string_append(pretty
->string
, "\\\\");
636 g_string_append(pretty
->string
, "\\\'");
639 g_string_append(pretty
->string
, "\\\"");
642 g_string_append(pretty
->string
, "\\\?");
646 /* Standard characters. */
647 if (!iscntrl(str
[i
])) {
648 g_string_append_c(pretty
->string
, str
[i
]);
654 g_string_append(pretty
->string
, "\\0");
657 g_string_append(pretty
->string
, "\\a");
660 g_string_append(pretty
->string
, "\\b");
663 g_string_append(pretty
->string
, "\\e");
666 g_string_append(pretty
->string
, "\\f");
669 g_string_append(pretty
->string
, "\\n");
672 g_string_append(pretty
->string
, "\\r");
675 g_string_append(pretty
->string
, "\\t");
678 g_string_append(pretty
->string
, "\\v");
681 /* Unhandled control-sequence, print as hex. */
682 g_string_append_printf(pretty
->string
, "\\x%02x", str
[i
]);
687 g_string_append_c(pretty
->string
, '"');
691 int print_enum(struct pretty_component
*pretty
,
692 const bt_field
*field
)
695 const bt_field_class
*enumeration_field_class
= NULL
;
696 bt_field_class_enumeration_mapping_label_array label_array
;
697 uint64_t label_count
;
700 enumeration_field_class
= bt_field_borrow_class_const(field
);
701 if (!enumeration_field_class
) {
706 switch (bt_field_get_class_type(field
)) {
707 case BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION
:
708 ret
= bt_field_unsigned_enumeration_get_mapping_labels(field
,
709 &label_array
, &label_count
);
711 case BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION
:
712 ret
= bt_field_signed_enumeration_get_mapping_labels(field
,
713 &label_array
, &label_count
);
724 g_string_append(pretty
->string
, "( ");
725 if (label_count
== 0) {
726 if (pretty
->use_colors
) {
727 g_string_append(pretty
->string
, COLOR_UNKNOWN
);
729 g_string_append(pretty
->string
, "<unknown>");
730 if (pretty
->use_colors
) {
731 g_string_append(pretty
->string
, COLOR_RST
);
735 for (i
= 0; i
< label_count
; i
++) {
736 const char *mapping_name
= label_array
[i
];
739 g_string_append(pretty
->string
, ", ");
741 if (pretty
->use_colors
) {
742 g_string_append(pretty
->string
, COLOR_ENUM_MAPPING_NAME
);
744 print_escape_string(pretty
, mapping_name
);
745 if (pretty
->use_colors
) {
746 g_string_append(pretty
->string
, COLOR_RST
);
750 g_string_append(pretty
->string
, " : container = ");
751 ret
= print_integer(pretty
, field
);
755 g_string_append(pretty
->string
, " )");
761 int filter_field_name(struct pretty_component
*pretty
, const char *field_name
,
762 GQuark
*filter_fields
, int filter_array_len
)
765 GQuark field_quark
= g_quark_try_string(field_name
);
767 if (!field_quark
|| pretty
->options
.verbose
) {
771 for (i
= 0; i
< filter_array_len
; i
++) {
772 if (field_quark
== filter_fields
[i
]) {
780 int print_struct_field(struct pretty_component
*pretty
,
781 const bt_field
*_struct
,
782 const bt_field_class
*struct_class
,
783 uint64_t i
, bool print_names
, uint64_t *nr_printed_fields
,
784 GQuark
*filter_fields
, int filter_array_len
)
787 const char *field_name
;
788 const bt_field
*field
= NULL
;
789 const bt_field_class
*field_class
= NULL
;;
791 field
= bt_field_structure_borrow_member_field_by_index_const(_struct
, i
);
797 bt_field_class_structure_borrow_member_by_index_const(struct_class
, i
,
798 &field_name
, &field_class
);
800 if (filter_fields
&& !filter_field_name(pretty
, field_name
,
801 filter_fields
, filter_array_len
)) {
806 if (*nr_printed_fields
> 0) {
807 g_string_append(pretty
->string
, ", ");
809 g_string_append(pretty
->string
, " ");
812 print_field_name_equal(pretty
, field_name
);
814 ret
= print_field(pretty
, field
, print_names
, NULL
, 0);
815 *nr_printed_fields
+= 1;
822 int print_struct(struct pretty_component
*pretty
,
823 const bt_field
*_struct
, bool print_names
,
824 GQuark
*filter_fields
, int filter_array_len
)
827 const bt_field_class
*struct_class
= NULL
;
828 uint64_t nr_fields
, i
, nr_printed_fields
;
830 struct_class
= bt_field_borrow_class_const(_struct
);
835 nr_fields
= bt_field_class_structure_get_member_count(struct_class
);
840 g_string_append(pretty
->string
, "{");
842 nr_printed_fields
= 0;
843 for (i
= 0; i
< nr_fields
; i
++) {
844 ret
= print_struct_field(pretty
, _struct
, struct_class
, i
,
845 print_names
, &nr_printed_fields
, filter_fields
,
852 g_string_append(pretty
->string
, " }");
859 int print_array_field(struct pretty_component
*pretty
,
860 const bt_field
*array
, uint64_t i
, bool print_names
)
862 const bt_field
*field
= NULL
;
865 g_string_append(pretty
->string
, ", ");
867 g_string_append(pretty
->string
, " ");
870 g_string_append_printf(pretty
->string
, "[%" PRIu64
"] = ", i
);
873 field
= bt_field_array_borrow_element_field_by_index_const(array
, i
);
875 return print_field(pretty
, field
, print_names
, NULL
, 0);
879 int print_array(struct pretty_component
*pretty
,
880 const bt_field
*array
, bool print_names
)
883 const bt_field_class
*array_class
= NULL
;
887 array_class
= bt_field_borrow_class_const(array
);
892 len
= bt_field_array_get_length(array
);
893 g_string_append(pretty
->string
, "[");
895 for (i
= 0; i
< len
; i
++) {
896 ret
= print_array_field(pretty
, array
, i
, print_names
);
902 g_string_append(pretty
->string
, " ]");
909 int print_sequence_field(struct pretty_component
*pretty
,
910 const bt_field
*seq
, uint64_t i
, bool print_names
)
912 const bt_field
*field
= NULL
;
915 g_string_append(pretty
->string
, ", ");
917 g_string_append(pretty
->string
, " ");
920 g_string_append_printf(pretty
->string
, "[%" PRIu64
"] = ", i
);
923 field
= bt_field_array_borrow_element_field_by_index_const(seq
, i
);
925 return print_field(pretty
, field
, print_names
, NULL
, 0);
929 int print_sequence(struct pretty_component
*pretty
,
930 const bt_field
*seq
, bool print_names
)
936 len
= bt_field_array_get_length(seq
);
942 g_string_append(pretty
->string
, "[");
945 for (i
= 0; i
< len
; i
++) {
946 ret
= print_sequence_field(pretty
, seq
, i
, print_names
);
952 g_string_append(pretty
->string
, " ]");
959 int print_variant(struct pretty_component
*pretty
,
960 const bt_field
*variant
, bool print_names
)
963 const bt_field
*field
= NULL
;
965 field
= bt_field_variant_borrow_selected_option_field_const(variant
);
967 g_string_append(pretty
->string
, "{ ");
970 // TODO: find tag's name using field path
971 // print_field_name_equal(pretty, tag_choice);
973 ret
= print_field(pretty
, field
, print_names
, NULL
, 0);
978 g_string_append(pretty
->string
, " }");
985 int print_field(struct pretty_component
*pretty
,
986 const bt_field
*field
, bool print_names
,
987 GQuark
*filter_fields
, int filter_array_len
)
989 bt_field_class_type class_id
;
991 class_id
= bt_field_get_class_type(field
);
993 case BT_FIELD_CLASS_TYPE_UNSIGNED_INTEGER
:
994 case BT_FIELD_CLASS_TYPE_SIGNED_INTEGER
:
995 return print_integer(pretty
, field
);
996 case BT_FIELD_CLASS_TYPE_REAL
:
1000 v
= bt_field_real_get_value(field
);
1001 if (pretty
->use_colors
) {
1002 g_string_append(pretty
->string
, COLOR_NUMBER_VALUE
);
1004 g_string_append_printf(pretty
->string
, "%g", v
);
1005 if (pretty
->use_colors
) {
1006 g_string_append(pretty
->string
, COLOR_RST
);
1010 case BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION
:
1011 case BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION
:
1012 return print_enum(pretty
, field
);
1013 case BT_FIELD_CLASS_TYPE_STRING
:
1017 str
= bt_field_string_get_value(field
);
1022 if (pretty
->use_colors
) {
1023 g_string_append(pretty
->string
, COLOR_STRING_VALUE
);
1025 print_escape_string(pretty
, str
);
1026 if (pretty
->use_colors
) {
1027 g_string_append(pretty
->string
, COLOR_RST
);
1031 case BT_FIELD_CLASS_TYPE_STRUCTURE
:
1032 return print_struct(pretty
, field
, print_names
, filter_fields
,
1034 case BT_FIELD_CLASS_TYPE_VARIANT
:
1035 return print_variant(pretty
, field
, print_names
);
1036 case BT_FIELD_CLASS_TYPE_STATIC_ARRAY
:
1037 return print_array(pretty
, field
, print_names
);
1038 case BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY
:
1039 return print_sequence(pretty
, field
, print_names
);
1041 // TODO: log instead
1042 fprintf(pretty
->err
, "[error] Unknown type id: %d\n", (int) class_id
);
1048 int print_stream_packet_context(struct pretty_component
*pretty
,
1049 const bt_event
*event
)
1052 const bt_packet
*packet
= NULL
;
1053 const bt_field
*main_field
= NULL
;
1055 packet
= bt_event_borrow_packet_const(event
);
1060 main_field
= bt_packet_borrow_context_field_const(packet
);
1064 if (!pretty
->start_line
) {
1065 g_string_append(pretty
->string
, ", ");
1067 pretty
->start_line
= false;
1068 if (pretty
->options
.print_scope_field_names
) {
1069 print_name_equal(pretty
, "stream.packet.context");
1071 ret
= print_field(pretty
, main_field
,
1072 pretty
->options
.print_context_field_names
,
1073 stream_packet_context_quarks
,
1074 STREAM_PACKET_CONTEXT_QUARKS_LEN
);
1081 int print_event_header_raw(struct pretty_component
*pretty
,
1082 const bt_event
*event
)
1085 const bt_field
*main_field
= NULL
;
1087 main_field
= bt_event_borrow_header_field_const(event
);
1091 if (!pretty
->start_line
) {
1092 g_string_append(pretty
->string
, ", ");
1094 pretty
->start_line
= false;
1095 if (pretty
->options
.print_scope_field_names
) {
1096 print_name_equal(pretty
, "stream.event.header");
1098 ret
= print_field(pretty
, main_field
,
1099 pretty
->options
.print_header_field_names
, NULL
, 0);
1106 int print_stream_event_context(struct pretty_component
*pretty
,
1107 const bt_event
*event
)
1110 const bt_field
*main_field
= NULL
;
1112 main_field
= bt_event_borrow_common_context_field_const(event
);
1116 if (!pretty
->start_line
) {
1117 g_string_append(pretty
->string
, ", ");
1119 pretty
->start_line
= false;
1120 if (pretty
->options
.print_scope_field_names
) {
1121 print_name_equal(pretty
, "stream.event.context");
1123 ret
= print_field(pretty
, main_field
,
1124 pretty
->options
.print_context_field_names
, NULL
, 0);
1131 int print_event_context(struct pretty_component
*pretty
,
1132 const bt_event
*event
)
1135 const bt_field
*main_field
= NULL
;
1137 main_field
= bt_event_borrow_specific_context_field_const(event
);
1141 if (!pretty
->start_line
) {
1142 g_string_append(pretty
->string
, ", ");
1144 pretty
->start_line
= false;
1145 if (pretty
->options
.print_scope_field_names
) {
1146 print_name_equal(pretty
, "event.context");
1148 ret
= print_field(pretty
, main_field
,
1149 pretty
->options
.print_context_field_names
, NULL
, 0);
1156 int print_event_payload(struct pretty_component
*pretty
,
1157 const bt_event
*event
)
1160 const bt_field
*main_field
= NULL
;
1162 main_field
= bt_event_borrow_payload_field_const(event
);
1166 if (!pretty
->start_line
) {
1167 g_string_append(pretty
->string
, ", ");
1169 pretty
->start_line
= false;
1170 if (pretty
->options
.print_scope_field_names
) {
1171 print_name_equal(pretty
, "event.fields");
1173 ret
= print_field(pretty
, main_field
,
1174 pretty
->options
.print_payload_field_names
, NULL
, 0);
1181 int flush_buf(FILE *stream
, struct pretty_component
*pretty
)
1185 if (pretty
->string
->len
== 0) {
1189 if (fwrite(pretty
->string
->str
, pretty
->string
->len
, 1, stream
) != 1) {
1198 int pretty_print_event(struct pretty_component
*pretty
,
1199 const bt_message
*event_msg
)
1202 const bt_event
*event
=
1203 bt_message_event_borrow_event_const(event_msg
);
1206 pretty
->start_line
= true;
1207 g_string_assign(pretty
->string
, "");
1208 ret
= print_event_header(pretty
, event
);
1213 ret
= print_stream_packet_context(pretty
, event
);
1218 if (pretty
->options
.verbose
) {
1219 ret
= print_event_header_raw(pretty
, event
);
1225 ret
= print_stream_event_context(pretty
, event
);
1230 ret
= print_event_context(pretty
, event
);
1235 ret
= print_event_payload(pretty
, event
);
1240 g_string_append_c(pretty
->string
, '\n');
1241 if (flush_buf(pretty
->out
, pretty
)) {
1251 int print_discarded_elements_msg(
1252 struct pretty_component
*pretty
, const bt_packet
*packet
,
1253 uint64_t count
, const char *elem_type
)
1257 const bt_stream
*stream
= NULL
;
1258 const bt_stream_class
*stream_class
= NULL
;
1259 const bt_trace
*trace
= NULL
;
1260 const char *stream_name
;
1261 const char *trace_name
;
1262 const unsigned char *trace_uuid
;
1263 int64_t stream_class_id
;
1265 bt_clock_snapshot
*begin_clock_snapshot
= NULL
;
1266 bt_clock_snapshot
*end_clock_snapshot
= NULL
;
1270 stream
= bt_packet_borrow_stream_const(packet
);
1272 stream_name
= bt_stream_get_name(stream
);
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_class_borrow_trace_const(stream_class
);
1285 trace_name
= bt_trace_get_name(trace
);
1287 trace_name
= "(unknown)";
1291 trace_uuid
= bt_trace_get_uuid(trace
);
1293 /* Beginning and end times */
1294 (void) bt_packet_borrow_previous_packet_default_end_clock_snapshot_const(
1295 packet
, &begin_clock_snapshot
);
1296 (void) bt_packet_borrow_default_end_clock_snapshot_const(packet
,
1297 &end_clock_snapshot
);
1299 /* Format message */
1300 g_string_assign(pretty
->string
, "");
1301 g_string_append_printf(pretty
->string
,
1302 "%s%sWARNING%s%s: Tracer discarded %" PRId64
" %s%s ",
1303 bt_common_color_fg_yellow(),
1304 bt_common_color_bold(),
1305 bt_common_color_reset(),
1306 bt_common_color_fg_yellow(),
1307 count
, elem_type
, count
== 1 ? "" : "s");
1309 if (begin_clock_snapshot
&& end_clock_snapshot
) {
1310 g_string_append(pretty
->string
, "between [");
1311 print_timestamp_wall(pretty
, begin_clock_snapshot
);
1312 g_string_append(pretty
->string
, "] and [");
1313 print_timestamp_wall(pretty
, end_clock_snapshot
);
1314 g_string_append(pretty
->string
, "]");
1316 g_string_append(pretty
->string
, "(unknown time range)");
1319 g_string_append_printf(pretty
->string
, " in trace \"%s\" ", trace_name
);
1322 g_string_append_printf(pretty
->string
,
1323 "(UUID: %02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x) ",
1341 g_string_append(pretty
->string
, "(no UUID) ");
1344 g_string_append_printf(pretty
->string
,
1345 "within stream \"%s\" (stream class ID: %" PRId64
", ",
1346 stream_name
, stream_class_id
);
1348 if (stream_id
>= 0) {
1349 g_string_append_printf(pretty
->string
,
1350 "stream ID: %" PRId64
, stream_id
);
1352 g_string_append(pretty
->string
, "no stream ID");
1355 g_string_append_printf(pretty
->string
, ").%s\n",
1356 bt_common_color_reset());
1359 * Print to standard error stream to remain backward compatible
1360 * with Babeltrace 1.
1362 if (flush_buf(stderr
, pretty
)) {
1372 int pretty_print_packet(struct pretty_component
*pretty
,
1373 const bt_message
*packet_beginning_msg
)
1376 const bt_packet
*packet
= bt_message_packet_beginning_borrow_packet_const(
1377 packet_beginning_msg
);
1381 if (bt_packet_get_discarded_event_count(packet
, &count
) ==
1382 BT_PACKET_PROPERTY_AVAILABILITY_AVAILABLE
&&
1384 status
= print_discarded_elements_msg(pretty
, packet
,
1391 if (bt_packet_get_discarded_packet_count(packet
, &count
) ==
1392 BT_PACKET_PROPERTY_AVAILABILITY_AVAILABLE
&&
1394 status
= print_discarded_elements_msg(pretty
, packet
,